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 React from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import FormHelp from './FormHelp' import Help from './Help'
it('FormHelp renders without crashing', () => { it('FormHelp renders without crashing', () => {
const div = document.createElement('div') const div = document.createElement('div')
ReactDOM.render( 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 div
) )
ReactDOM.unmountComponentAtNode(div) ReactDOM.unmountComponentAtNode(div)

View File

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

View File

@ -1,10 +1,10 @@
@import '../../styles/variables'; @import '../../../styles/variables';
.formGroup { .formGroup {
margin-bottom: $spacer; margin-bottom: $spacer;
} }
.input-wrap { .inputWrap {
background: $brand-gradient; background: $brand-gradient;
border-radius: $border-radius; border-radius: $border-radius;
width: 100%; width: 100%;
@ -12,10 +12,6 @@
display: flex; display: flex;
position: relative; position: relative;
&.is-focused {
background: $brand-black;
}
.is-dimmed & { .is-dimmed & {
background: $brand-grey-lighter; background: $brand-grey-lighter;
@ -25,7 +21,14 @@
} }
} }
.input-wrap-search { .isFocused {
composes: inputWrap;
background: $brand-black;
}
.inputWrapSearch {
composes: inputWrap;
.input { .input {
padding-left: $spacer * 1.25; padding-left: $spacer * 1.25;
} }
@ -92,8 +95,29 @@
// } // }
} }
// stylelint-disable-next-line .label {
select.input { 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; height: 43px;
padding-right: 3rem; padding-right: 3rem;
border: 0; border: 0;
@ -118,45 +142,12 @@ select.input {
outline: 0; outline: 0;
font-family: $font-family-base; 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 // Size modifiers
.input-sm {
.inputSmall {
composes: input;
font-size: $font-size-small; font-size: $font-size-small;
min-height: 32px; min-height: 32px;
padding: $spacer / 4; padding: $spacer / 4;
@ -166,8 +157,8 @@ select.input {
} }
} }
// stylelint-disable-next-line .selectSmall {
select.input-sm { composes: select;
height: 32px; height: 32px;
padding-right: 2rem; padding-right: 2rem;

View File

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

View File

@ -8,9 +8,25 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-wrap: wrap; flex-wrap: wrap;
padding-top: 4rem;
padding-bottom: 4rem;
> div { > div {
text-align: center; text-align: center;
width: 100%; 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 React, { Component } from 'react'
import Button from '../components/atoms/Button' import Button from '../components/atoms/Button'
import Input from '../components/atoms/Form/Input'
import styles from './Home.module.scss' import styles from './Home.module.scss'
class Home extends Component { class Home extends Component {
@ -13,6 +14,47 @@ class Home extends Component {
<Button href="https://hello.com"> <Button href="https://hello.com">
I am a link disguised as a button I am a link disguised as a button
</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> </div>
) )
} }