1
0
mirror of https://github.com/oceanprotocol/commons.git synced 2023-03-15 18:03:00 +01:00

one input component for form elements: input, select, textarea

This commit is contained in:
Matthias Kretschmann 2019-01-24 13:55:19 +01:00
parent 3fbebcad81
commit be1faa96de
Signed by: m
GPG Key ID: 606EEEF3C479A91F
7 changed files with 135 additions and 79 deletions

View File

@ -1,12 +1,12 @@
import React from 'react'
import ReactDOM from 'react-dom'
import FormHelp from './FormHelp'
import Help from './Help'
it('FormHelp renders without crashing', () => {
const div = document.createElement('div')
ReactDOM.render(
<FormHelp>Price of your data set asset in Ocean Tokens.</FormHelp>,
<Help>Price of your data set asset in Ocean Tokens.</Help>,
div
)
ReactDOM.unmountComponentAtNode(div)

View File

@ -1,5 +1,5 @@
import React from 'react'
import styles from './FormHelp.module.scss'
import styles from './Help.module.scss'
const FormHelp = ({ children }: { children: string }) => (
<div className={styles.help}>{children}</div>

View File

@ -1,10 +1,10 @@
@import '../../styles/variables';
@import '../../../styles/variables';
.formGroup {
margin-bottom: $spacer;
}
.input-wrap {
.inputWrap {
background: $brand-gradient;
border-radius: $border-radius;
width: 100%;
@ -12,10 +12,6 @@
display: flex;
position: relative;
&.is-focused {
background: $brand-black;
}
.is-dimmed & {
background: $brand-grey-lighter;
@ -25,7 +21,14 @@
}
}
.input-wrap-search {
.isFocused {
composes: inputWrap;
background: $brand-black;
}
.inputWrapSearch {
composes: inputWrap;
.input {
padding-left: $spacer * 1.25;
}
@ -92,8 +95,29 @@
// }
}
// stylelint-disable-next-line
select.input {
.label {
color: $brand-grey;
font-size: $font-size-base;
font-family: $font-family-title;
line-height: 1.2;
display: block;
margin-bottom: $spacer / 6;
}
.required {
composes: label;
&:after {
content: '*';
font-size: $font-size-base;
color: $brand-grey-light;
display: inline-block;
margin-left: .1rem;
}
}
.select {
composes: input;
height: 43px;
padding-right: 3rem;
border: 0;
@ -118,45 +142,12 @@ select.input {
outline: 0;
font-family: $font-family-base;
}
// stylelint-disable
.is-dimmed & {
background-image: linear-gradient(
45deg,
transparent 50%,
$brand-grey-light 50%
),
linear-gradient(135deg, $brand-grey-light 50%, transparent 50%),
linear-gradient(
to right,
$brand-grey-lighter 1px,
lighten($brand-grey-lighter, 5%) 2px,
lighten($brand-grey-lighter, 5%)
);
}
// stylelint-enable
}
.label {
color: $brand-grey;
font-size: $font-size-base;
font-family: $font-family-title;
line-height: 1.2;
display: block;
margin-bottom: $spacer / 6;
&.is-required {
&:after {
content: '*';
font-size: $font-size-base;
color: $brand-grey-light;
display: inline-block;
margin-left: .1rem;
}
}
}
// Size modifiers
.input-sm {
.inputSmall {
composes: input;
font-size: $font-size-small;
min-height: 32px;
padding: $spacer / 4;
@ -166,8 +157,8 @@ select.input {
}
}
// stylelint-disable-next-line
select.input-sm {
.selectSmall {
composes: select;
height: 32px;
padding-right: 2rem;

View File

@ -1,48 +1,51 @@
import React, { PureComponent } from 'react'
import { ReactComponent as SearchIcon } from '../../../svg/search.svg'
import FormHelp from './FormHelp'
import styles from './FormInput.module.scss'
// import { ReactComponent as SearchIcon } from '../../../svg/search.svg'
import Help from './Help'
import styles from './Input.module.scss'
interface IFormInputProps {
interface IInputProps {
name: string
label: string
placeholder: string
placeholder?: string
required?: boolean
help?: string
tag?: string
type: string
type?: string
small?: boolean
additionalComponent?: void
}
interface IFormInputState {
interface IInputState {
isFocused: boolean
}
export default class FormInput extends PureComponent<
IFormInputProps,
IFormInputState
> {
public state: IFormInputState = { isFocused: false }
const Tag = ({ ...props }) => {
if (props.tag && props.tag === 'select') {
return <select className={styles.select} {...props} />
} else if (props.tag && props.tag === 'textarea') {
return <textarea className={styles.input} {...props} />
} else {
return <input className={styles.input} {...props} />
}
}
export default class Input extends PureComponent<IInputProps, IInputState> {
public state: IInputState = { isFocused: false }
public inputWrapClasses() {
if (this.props.type === 'search') {
return 'input-wrap input-wrap-search'
return styles.inputWrapSearch
} else if (this.props.type === 'search' && this.state.isFocused) {
return 'input-wrap input-wrap-search is-focused'
} else if (this.state.isFocused && this.props.type !== 'search') {
return 'input-wrap is-focused'
return styles.isFocused
} else {
return 'input-wrap'
return styles.inputWrap
}
}
public handleBlur() {
this.setState({ isFocused: true })
}
public handleFocus() {
this.setState({ isFocused: false })
public toggleFocus = () => {
this.setState({ isFocused: !this.state.isFocused })
}
public render() {
@ -53,7 +56,9 @@ export default class FormInput extends PureComponent<
type,
help,
small,
tag,
additionalComponent,
children,
...props
} = this.props
@ -61,25 +66,27 @@ export default class FormInput extends PureComponent<
<div className={styles.formGroup}>
<label
htmlFor={name}
className={styles.label}
className={required ? styles.required : styles.label}
title={required ? 'Required' : ''}
>
{label}
</label>
<div className={this.inputWrapClasses()}>
<input
className={small ? 'input input-sm' : 'input'}
<Tag
id={name}
name={name}
required={required}
type={type}
tag={tag}
{...props}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
{type === 'search' && <SearchIcon />}
onFocus={this.toggleFocus}
onBlur={this.toggleFocus}
>
{children}
</Tag>
{/* {type === 'search' && <SearchIcon />} */}
</div>
{help && <FormHelp>{help}</FormHelp>}
{help && <Help>{help}</Help>}
{additionalComponent && additionalComponent}
</div>

View File

@ -8,9 +8,25 @@
align-items: center;
justify-content: center;
flex-wrap: wrap;
padding-top: 4rem;
padding-bottom: 4rem;
> div {
text-align: center;
width: 100%;
}
}
.form {
width: 100%;
background: $brand-grey-lighter;
margin: 0 auto;
max-width: 40rem;
padding: $spacer;
margin-top: 4rem;
fieldset {
border: 0;
padding: 0;
}
}

View File

@ -1,5 +1,6 @@
import React, { Component } from 'react'
import Button from '../components/atoms/Button'
import Input from '../components/atoms/Form/Input'
import styles from './Home.module.scss'
class Home extends Component {
@ -13,6 +14,47 @@ class Home extends Component {
<Button href="https://hello.com">
I am a link disguised as a button
</Button>
<form className={styles.form}>
<fieldset>
<Input
name="hellotext"
label="Hello Text"
placeholder="Hello placeholder"
type="text"
required={true}
/>
<Input
name="hellotextwithhelp"
label="Hello Text with Help"
placeholder="Hello placeholder"
type="text"
required={true}
help="Help me Obiwan."
/>
<Input
name="hellosearch"
label="Hello Search"
placeholder="Hello placeholder"
type="search"
/>
<Input
name="helloselect"
label="Hello Select"
tag="select"
>
<option value="0">---</option>
<option value="1">Hello Option</option>
<option value="2">Hello Option</option>
</Input>
<Input
name="hellotextarea"
label="Hello Textarea"
placeholder="Hello placeholder"
tag="textarea"
/>
</fieldset>
</form>
</div>
)
}