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

port over first form components

This commit is contained in:
Matthias Kretschmann 2019-01-23 17:37:20 +01:00
parent 5995d75709
commit 3fbebcad81
Signed by: m
GPG Key ID: 606EEEF3C479A91F
5 changed files with 293 additions and 0 deletions

View File

@ -0,0 +1,7 @@
@import '../../../styles/variables';
.help {
font-size: $font-size-small;
color: darken($brand-grey-light, 10%);
margin-top: $spacer / 4;
}

View File

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

View File

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

View File

@ -0,0 +1,177 @@
@import '../../styles/variables';
.formGroup {
margin-bottom: $spacer;
}
.input-wrap {
background: $brand-gradient;
border-radius: $border-radius;
width: 100%;
padding: 2px;
display: flex;
position: relative;
&.is-focused {
background: $brand-black;
}
.is-dimmed & {
background: $brand-grey-lighter;
&.is-focused {
background: $brand-grey-light;
}
}
}
.input-wrap-search {
.input {
padding-left: $spacer * 1.25;
}
svg {
position: absolute;
left: $spacer / 3;
width: 1.25rem;
height: 1.25rem;
top: 50%;
margin-top: -.75rem;
fill: rgba($brand-grey-light, .7);
}
}
.input {
font-size: $font-size-base;
font-family: $font-family-button;
color: $brand-black;
border: none;
box-shadow: none;
width: 100%;
background: $brand-white;
padding: $spacer / 3;
margin: 0;
border-radius: $border-radius;
transition: .2s ease-out;
min-height: 43px;
appearance: none;
&:focus {
border: none;
box-shadow: none;
outline: 0;
}
&::placeholder {
font-family: $font-family-base;
font-size: $font-size-base;
color: $brand-grey-light;
font-weight: $font-weight-base;
transition: .2s ease-out;
opacity: .7;
}
&[readonly],
&[disabled] {
background-color: $brand-grey-lighter;
cursor: not-allowed;
pointer-events: none;
}
// &::-webkit-credentials-auto-fill-button,
// &::-webkit-caps-lock-indicator {
// background: $brand-white;
// }
// &:-webkit-autofill,
// &:-webkit-autofill:hover,
// &:-webkit-autofill:focus {
// -webkit-text-fill-color: $brand-white;
// box-shadow: 0 0 0 1000px $brand-black inset;
// transition: background-color 5000s ease-in-out 0s;
// }
}
// stylelint-disable-next-line
select.input {
height: 43px;
padding-right: 3rem;
border: 0;
// custom arrow
// stylelint-disable
background-image: linear-gradient(45deg, transparent 50%, $brand-purple 50%),
linear-gradient(135deg, $brand-purple 50%, transparent 50%),
linear-gradient(
to right,
$brand-pink 1px,
lighten($brand-grey-lighter, 5%) 2px,
lighten($brand-grey-lighter, 5%)
);
background-position: calc(100% - 18px) calc(1rem + 5px),
calc(100% - 13px) calc(1rem + 5px), 100% 0;
background-size: 5px 5px, 5px 5px, 2.5rem 3rem;
// stylelint-enable
background-repeat: no-repeat;
&:focus {
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 {
font-size: $font-size-small;
min-height: 32px;
padding: $spacer / 4;
&::placeholder {
font-size: $font-size-small;
}
}
// stylelint-disable-next-line
select.input-sm {
height: 32px;
padding-right: 2rem;
// custom arrow
background-position: calc(100% - 14px) 1rem, calc(100% - 9px) 1rem, 100% 0;
background-size: 5px 5px, 5px 5px, 2rem 3rem;
}

View File

@ -0,0 +1,88 @@
import React, { PureComponent } from 'react'
import { ReactComponent as SearchIcon } from '../../../svg/search.svg'
import FormHelp from './FormHelp'
import styles from './FormInput.module.scss'
interface IFormInputProps {
name: string
label: string
placeholder: string
required?: boolean
help?: string
tag?: string
type: string
small?: boolean
additionalComponent?: void
}
interface IFormInputState {
isFocused: boolean
}
export default class FormInput extends PureComponent<
IFormInputProps,
IFormInputState
> {
public state: IFormInputState = { isFocused: false }
public inputWrapClasses() {
if (this.props.type === 'search') {
return 'input-wrap input-wrap-search'
} 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'
} else {
return 'input-wrap'
}
}
public handleBlur() {
this.setState({ isFocused: true })
}
public handleFocus() {
this.setState({ isFocused: false })
}
public render() {
const {
name,
label,
required,
type,
help,
small,
additionalComponent,
...props
} = this.props
return (
<div className={styles.formGroup}>
<label
htmlFor={name}
className={styles.label}
title={required ? 'Required' : ''}
>
{label}
</label>
<div className={this.inputWrapClasses()}>
<input
className={small ? 'input input-sm' : 'input'}
id={name}
name={name}
required={required}
type={type}
{...props}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
{type === 'search' && <SearchIcon />}
</div>
{help && <FormHelp>{help}</FormHelp>}
{additionalComponent && additionalComponent}
</div>
)
}
}