Introduce Form Element Set

pull/4064/head
Alex P 2018-07-30 14:28:16 -07:00
parent cb2c539ec5
commit 6c00d9ad0e
9 changed files with 398 additions and 0 deletions

View File

@ -0,0 +1,110 @@
/*
Form Styles
------------------------------------------------------------------------------
*/
@import 'src/style/modules/influx-colors';
@import 'src/style/modules/variables';
@import 'src/style/modules/mixins';
$grid--form-gutter: 6px;
.form--wrapper {
width: calc(100% + #{$grid--form-gutter * 2});
margin-left: -$grid--form-gutter;
margin-right: -$grid--form-gutter;
display: inline-flex;
flex-wrap: wrap;
}
/*
Form Elements
------------------------------------------------------------------------------
*/
.form--element {
display: inline-flex;
flex-direction: column;
align-items: stretch;
margin-bottom: $ix-marg-b;
}
.form--element.col {
&-xs,
&-sm,
&-md,
&-lg {
&-12,
&-11,
&-10,
&-9,
&-8,
&-7,
&-6,
&-5,
&-4,
&-3,
&-2,
&-1 {
padding-left: $grid--form-gutter;
padding-right: $grid--form-gutter;
}
}
}
/*
Form Group Addons
------------------------------------------------------------------------------
*/
.form--label {
width: 100%;
display: inline-block;
font-size: 12px;
font-weight: 600;
color: $g11-sidewalk;
margin: 0 0 $ix-marg-a 0;
padding: 0 ($form-sm-padding + $ix-border);
@extend %no-user-select;
}
.form--help-text {
display: inline-block;
font-size: 12px;
font-style: italic;
line-height: 16px;
font-weight: 600;
color: $g11-sidewalk;
margin: $ix-marg-a 0 0 0;
padding: 0 ($form-sm-padding + $ix-border);
@extend %no-user-select;
}
.form--element-error {
display: inline-block;
font-size: 12px;
line-height: 16px;
font-weight: 600;
color: $c-dreamsicle;
margin: $ix-marg-a 0 0 0;
padding: 0 ($form-sm-padding + $ix-border);
@extend %no-user-select;
}
/*
Form Divider
------------------------------------------------------------------------------
*/
.form--divider {
width: 100%;
height: $form-sm-height - $ix-marg-b;
}
/*
Form Submit
------------------------------------------------------------------------------
*/
.form--submit {
align-items: center;
margin-top: $form-sm-height - $ix-marg-b;
margin-bottom: 0;
}

View File

@ -0,0 +1,45 @@
// Libraries
import React, {Component} from 'react'
// Components
import FormElement from 'src/reusable_ui/components/form_layout/FormElement'
import FormLabel from 'src/reusable_ui/components/form_layout/FormLabel'
import FormDivider from 'src/reusable_ui/components/form_layout/FormDivider'
import FormFooter from 'src/reusable_ui/components/form_layout/FormFooter'
// Styles
import './Form.scss'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
children: JSX.Element[]
}
@ErrorHandling
class Form extends Component<Props> {
public static Element = FormElement
public static Label = FormLabel
public static Divider = FormDivider
public static Footer = FormFooter
public render() {
const {children} = this.props
this.validateChildCount()
return <div className="form--wrapper">{children}</div>
}
private validateChildCount = (): void => {
const {children} = this.props
if (React.Children.count(children) === 0) {
throw new Error(
'Form require at least 1 child element. We recommend using <Form.Element>'
)
}
}
}
export default Form

View File

@ -0,0 +1,13 @@
// Libraries
import React, {Component} from 'react'
import {ErrorHandling} from 'src/shared/decorators/errors'
@ErrorHandling
class FormDivider extends Component {
public render() {
return <label className="form---divider" />
}
}
export default FormDivider

View File

@ -0,0 +1,100 @@
// Libraries
import React, {Component} from 'react'
import classnames from 'classnames'
// Components
import FormLabel from 'src/reusable_ui/components/form_layout/FormLabel'
import FormElementError from 'src/reusable_ui/components/form_layout/FormElementError'
import FormHelpText from 'src/reusable_ui/components/form_layout/FormHelpText'
// Types
import {Columns} from 'src/reusable_ui/types'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
children: JSX.Element
label?: string
helpText?: string
errorMessage?: string
colsXS?: Columns
colsSM?: Columns
colsMD?: Columns
colsLG?: Columns
offsetXS?: Columns
offsetSM?: Columns
offsetMD?: Columns
offsetLG?: Columns
}
@ErrorHandling
class FormElement extends Component<Props> {
public static defaultProps: Partial<Props> = {
label: '',
helpText: '',
errorMessage: '',
colsXS: Columns.Twelve,
}
public render() {
const {children} = this.props
return (
<div className={this.className}>
{this.groupLabel}
{children}
{this.errorMessage}
{this.helpText}
</div>
)
}
private get className(): string {
const {
colsXS,
colsSM,
colsMD,
colsLG,
offsetXS,
offsetSM,
offsetMD,
offsetLG,
} = this.props
return classnames('form--element', {
[`col-xs-${colsXS}`]: colsXS,
[`col-sm-${colsSM}`]: colsSM,
[`col-md-${colsMD}`]: colsMD,
[`col-lg-${colsLG}`]: colsLG,
[`col-xs-offset-${offsetXS}`]: offsetXS,
[`col-sm-offset-${offsetSM}`]: offsetSM,
[`col-md-offset-${offsetMD}`]: offsetMD,
[`col-lg-offset-${offsetLG}`]: offsetLG,
})
}
private get groupLabel(): JSX.Element {
const {label} = this.props
if (label) {
return <FormLabel label={label} />
}
}
private get helpText(): JSX.Element {
const {helpText} = this.props
if (helpText) {
return <FormHelpText text={helpText} />
}
}
private get errorMessage(): JSX.Element {
const {errorMessage} = this.props
if (errorMessage) {
return <FormElementError message={errorMessage} />
}
}
}
export default FormElement

View File

@ -0,0 +1,19 @@
// Libraries
import React, {Component} from 'react'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
message: string
}
@ErrorHandling
class FormElementError extends Component<Props> {
public render() {
const {message} = this.props
return <span className="form--element-error">{message}</span>
}
}
export default FormElementError

View File

@ -0,0 +1,58 @@
// Libraries
import React, {Component} from 'react'
import classnames from 'classnames'
// Types
import {Columns} from 'src/reusable_ui/types'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
children: JSX.Element | JSX.Element[]
colsXS?: Columns
colsSM?: Columns
colsMD?: Columns
colsLG?: Columns
offsetXS?: Columns
offsetSM?: Columns
offsetMD?: Columns
offsetLG?: Columns
}
@ErrorHandling
class FormFooter extends Component<Props> {
public static defaultProps: Partial<Props> = {
colsXS: Columns.Twelve,
}
public render() {
const {children} = this.props
return <div className={this.className}>{children}</div>
}
private get className(): string {
const {
colsXS,
colsSM,
colsMD,
colsLG,
offsetXS,
offsetSM,
offsetMD,
offsetLG,
} = this.props
return classnames('form--element form--submit', {
[`col-xs-${colsXS}`]: colsXS,
[`col-sm-${colsSM}`]: colsSM,
[`col-md-${colsMD}`]: colsMD,
[`col-lg-${colsLG}`]: colsLG,
[`col-xs-offset-${offsetXS}`]: offsetXS,
[`col-sm-offset-${offsetSM}`]: offsetSM,
[`col-md-offset-${offsetMD}`]: offsetMD,
[`col-lg-offset-${offsetLG}`]: offsetLG,
})
}
}
export default FormFooter

View File

@ -0,0 +1,19 @@
// Libraries
import React, {Component} from 'react'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
text: string
}
@ErrorHandling
class FormHelpText extends Component<Props> {
public render() {
const {text} = this.props
return <span className="form--help-text">{text}</span>
}
}
export default FormHelpText

View File

@ -0,0 +1,19 @@
// Libraries
import React, {Component} from 'react'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
label: string
}
@ErrorHandling
class FormLabel extends Component<Props> {
public render() {
const {label} = this.props
return <label className="form--label">{label}</label>
}
}
export default FormLabel

View File

@ -125,3 +125,18 @@ export enum IconFont {
Stop = 'stop',
Zap = 'zap',
}
export enum Columns {
One = 1,
Two = 2,
Three = 3,
Four = 4,
Five = 5,
Six = 6,
Seven = 7,
Eight = 8,
Nine = 9,
Ten = 10,
Eleven = 11,
Twelve = 12,
}