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:
parent
3fbebcad81
commit
be1faa96de
@ -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)
|
@ -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>
|
@ -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;
|
||||
|
@ -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>
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user