mirror of
https://github.com/yldio/copilot.git
synced 2024-11-14 07:10:05 +02:00
refactor Input and Select
This commit is contained in:
parent
bd1ff8171a
commit
8ac2a7c60f
23
ui/src/components/form/label-row.js
Normal file
23
ui/src/components/form/label-row.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
const Column = require('../column');
|
||||||
|
const React = require('react');
|
||||||
|
const Row = require('../row');
|
||||||
|
|
||||||
|
const LabelRow = (props) => {
|
||||||
|
const labels = React.Children.map(props.children, (children) => (
|
||||||
|
<Column md={6} xs={12}>
|
||||||
|
{children}
|
||||||
|
</Column>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
{labels}
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
LabelRow.propTypes = {
|
||||||
|
children: React.PropTypes.node
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = LabelRow;
|
24
ui/src/components/form/label.js
Normal file
24
ui/src/components/form/label.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
const constants = require('../../shared/constants');
|
||||||
|
const fns = require('../../shared/functions');
|
||||||
|
const Styled = require('styled-components');
|
||||||
|
|
||||||
|
const {
|
||||||
|
colors
|
||||||
|
} = constants;
|
||||||
|
|
||||||
|
const {
|
||||||
|
remcalc
|
||||||
|
} = fns;
|
||||||
|
|
||||||
|
const {
|
||||||
|
default: styled
|
||||||
|
} = Styled;
|
||||||
|
|
||||||
|
module.exports = styled.label`
|
||||||
|
width: 100%;
|
||||||
|
font-size: ${remcalc(16)};
|
||||||
|
font-weight: 600;
|
||||||
|
font-style: normal;
|
||||||
|
font-stretch: normal;
|
||||||
|
color: ${colors.brandSecondaryColor};
|
||||||
|
`;
|
29
ui/src/components/form/msg.js
Normal file
29
ui/src/components/form/msg.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
const constants = require('../../shared/constants');
|
||||||
|
const Label = require('./label');
|
||||||
|
const match = require('../../shared/match');
|
||||||
|
const Styled = require('styled-components');
|
||||||
|
|
||||||
|
const {
|
||||||
|
breakpoints,
|
||||||
|
colors
|
||||||
|
} = constants;
|
||||||
|
|
||||||
|
const {
|
||||||
|
default: styled
|
||||||
|
} = Styled;
|
||||||
|
|
||||||
|
const color = match.prop({
|
||||||
|
warning: colors.inputWarning,
|
||||||
|
error: colors.inputError,
|
||||||
|
//disabled: colors.brandInactiveColor
|
||||||
|
})('type');
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = styled(Label)`
|
||||||
|
color: ${color};
|
||||||
|
|
||||||
|
${breakpoints.medium`
|
||||||
|
float: right;
|
||||||
|
text-align: right;
|
||||||
|
`}
|
||||||
|
`;
|
67
ui/src/components/form/outlet.js
Normal file
67
ui/src/components/form/outlet.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
const constants = require('../../shared/constants');
|
||||||
|
const fns = require('../../shared/functions');
|
||||||
|
const Styled = require('styled-components');
|
||||||
|
|
||||||
|
const {
|
||||||
|
colors,
|
||||||
|
boxes
|
||||||
|
} = constants;
|
||||||
|
|
||||||
|
const {
|
||||||
|
remcalc
|
||||||
|
} = fns;
|
||||||
|
|
||||||
|
const {
|
||||||
|
css
|
||||||
|
} = Styled;
|
||||||
|
|
||||||
|
const colorWithDisabled = (props) => props.disabled
|
||||||
|
? colors.brandInactiveColor
|
||||||
|
: colors.fonts.regular;
|
||||||
|
|
||||||
|
const colorWithDefaultValue = (props) => props.value === props.defaultValue
|
||||||
|
? colors.brandInactiveColor
|
||||||
|
: colorWithDisabled(props);
|
||||||
|
|
||||||
|
const color = (props) => props.defaultValue
|
||||||
|
? colorWithDefaultValue(props)
|
||||||
|
: colorWithDisabled(props);
|
||||||
|
|
||||||
|
const height = (props) => !props.multiple
|
||||||
|
? remcalc(48)
|
||||||
|
: 'auto';
|
||||||
|
|
||||||
|
const paddingTop = (props) => props.multiple
|
||||||
|
? remcalc(20)
|
||||||
|
: remcalc(13);
|
||||||
|
|
||||||
|
module.exports = css`
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: ${height};
|
||||||
|
|
||||||
|
margin-bottom: ${remcalc(8)};
|
||||||
|
margin-top: ${remcalc(8)};
|
||||||
|
padding: ${paddingTop} ${remcalc(18)};
|
||||||
|
|
||||||
|
border-radius: ${boxes.borderRadius};
|
||||||
|
background-color: ${colors.brandPrimaryColor};
|
||||||
|
box-shadow: ${boxes.insetShaddow};
|
||||||
|
border: ${boxes.border.unchecked};
|
||||||
|
|
||||||
|
font-size: ${remcalc(16)};
|
||||||
|
line-height: normal !important;
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-stretch: normal;
|
||||||
|
color: ${color};
|
||||||
|
|
||||||
|
appearance: none;
|
||||||
|
outline: 0;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: ${colors.brandPrimary};
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
`;
|
7
ui/src/components/form/view.js
Normal file
7
ui/src/components/form/view.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
const Styled = require('styled-components');
|
||||||
|
|
||||||
|
const {
|
||||||
|
default: styled
|
||||||
|
} = Styled;
|
||||||
|
|
||||||
|
module.exports = styled.div``;
|
@ -1,162 +1,80 @@
|
|||||||
const React = require('react');
|
|
||||||
|
|
||||||
const composers = require('../../shared/composers');
|
|
||||||
const constants = require('../../shared/constants');
|
|
||||||
const fns = require('../../shared/functions');
|
const fns = require('../../shared/functions');
|
||||||
|
const React = require('react');
|
||||||
const Styled = require('styled-components');
|
const Styled = require('styled-components');
|
||||||
|
|
||||||
const {
|
const Label = require('../form/label');
|
||||||
boxes,
|
const LabelRow = require('../form/label-row');
|
||||||
colors
|
const Msg = require('../form/msg');
|
||||||
} = constants;
|
const Outlet = require('../form/outlet');
|
||||||
|
const View = require('../form/view');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
remcalc,
|
rndId
|
||||||
} = fns;
|
} = fns;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
baseBox
|
default: styled
|
||||||
} = composers;
|
|
||||||
|
|
||||||
const {
|
|
||||||
default: styled,
|
|
||||||
css
|
|
||||||
} = Styled;
|
} = Styled;
|
||||||
|
|
||||||
const successBakcground = css`
|
const StyledInput = styled.input`
|
||||||
background-color: ${colors.brandSecondary};
|
${Outlet}
|
||||||
background-image: url('./input-confirm.svg');
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: 98% ${remcalc(20)};
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const defaultBackground = css`
|
const Input = (props) => {
|
||||||
background-color: ${colors.brandSecondary};
|
const {
|
||||||
`;
|
|
||||||
|
|
||||||
const Label = styled.label`
|
|
||||||
color: ${props => props.error ? colors.alert : colors.fonts.regular}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const InputField = styled.input`
|
|
||||||
${baseBox()};
|
|
||||||
|
|
||||||
${props => props.success ? successBakcground : defaultBackground }
|
|
||||||
|
|
||||||
border-color: ${props => props.error ? colors.alert : 'auto'}
|
|
||||||
color: ${props => props.error ? colors.alert : colors.fonts.semibold}
|
|
||||||
display: block;
|
|
||||||
font-size: ${remcalc(16)};
|
|
||||||
padding: ${remcalc('15 18')};
|
|
||||||
visibility: visible;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
border-color: ${boxes.border.checked};
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Error = styled.span`
|
|
||||||
float: right;
|
|
||||||
color: ${colors.alert};
|
|
||||||
font-size: ${remcalc(14)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Input = ({
|
|
||||||
autoComplete,
|
|
||||||
autoFocus,
|
|
||||||
children,
|
children,
|
||||||
className,
|
id = rndId(),
|
||||||
disabled = false,
|
label = '',
|
||||||
error,
|
error = '',
|
||||||
form,
|
warning = ''
|
||||||
id,
|
} = props;
|
||||||
inputMode,
|
|
||||||
label,
|
const viewProps = [
|
||||||
labelledby,
|
'children',
|
||||||
list,
|
'style',
|
||||||
name,
|
'className'
|
||||||
onChange,
|
];
|
||||||
pattern,
|
|
||||||
placeholder,
|
// reset props for <input />
|
||||||
readOnly,
|
const newProps = Object.keys(props).reduce((sum, key) => ({
|
||||||
required,
|
...sum,
|
||||||
selectionDirection,
|
[key]: viewProps.indexOf(key) < 0 ? props[key] : null
|
||||||
spellCheck,
|
}),{});
|
||||||
style,
|
|
||||||
success,
|
const _label = !label.length ? null : (
|
||||||
tabIndex,
|
<Label htmlFor={id}>
|
||||||
type,
|
{label}
|
||||||
value
|
</Label>
|
||||||
}) => {
|
);
|
||||||
const _label = label || children;
|
|
||||||
const _children = label && children ? children : null;
|
const msgType = error ? 'error' : (warning ? 'warning' : null);
|
||||||
const _error = error ? (<Error>{error}</Error>) : null;
|
|
||||||
|
const _msg = !(error || warning) ? null : (
|
||||||
|
<Msg type={msgType}>
|
||||||
|
{error ? error : warning}
|
||||||
|
</Msg>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<View className={props.className} style={props.style}>
|
||||||
<Label
|
<LabelRow>
|
||||||
error={error}
|
|
||||||
htmlFor={id}
|
|
||||||
>
|
|
||||||
{_label}
|
{_label}
|
||||||
</Label>
|
{_msg}
|
||||||
{_error}
|
</LabelRow>
|
||||||
<InputField
|
<StyledInput {...newProps} />
|
||||||
aria-labelledby={labelledby}
|
{children}
|
||||||
autoComplete={autoComplete}
|
</View>
|
||||||
autoFocus={autoFocus}
|
|
||||||
disabled={disabled}
|
|
||||||
error={error}
|
|
||||||
form={form}
|
|
||||||
id={id}
|
|
||||||
inputMode={inputMode}
|
|
||||||
list={list}
|
|
||||||
name={name}
|
|
||||||
onChange={onChange}
|
|
||||||
pattern={pattern}
|
|
||||||
placeholder={placeholder}
|
|
||||||
readOnly={readOnly}
|
|
||||||
required={required}
|
|
||||||
selectionDirection={selectionDirection}
|
|
||||||
spellCheck={spellCheck}
|
|
||||||
success={success}
|
|
||||||
tabIndex={tabIndex}
|
|
||||||
type={type}
|
|
||||||
value={value}
|
|
||||||
/>
|
|
||||||
{_children}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Input.propTypes = {
|
Input.propTypes = {
|
||||||
autoComplete: React.PropTypes.string,
|
|
||||||
autoFocus: React.PropTypes.bool,
|
|
||||||
children: React.PropTypes.node,
|
children: React.PropTypes.node,
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
disabled: React.PropTypes.bool,
|
|
||||||
error: React.PropTypes.string,
|
error: React.PropTypes.string,
|
||||||
form: React.PropTypes.string,
|
|
||||||
id: React.PropTypes.string,
|
id: React.PropTypes.string,
|
||||||
inputMode: React.PropTypes.string,
|
|
||||||
label: React.PropTypes.string,
|
label: React.PropTypes.string,
|
||||||
labelledby: React.PropTypes.string,
|
|
||||||
list: React.PropTypes.string,
|
|
||||||
name: React.PropTypes.string,
|
|
||||||
onChange: React.PropTypes.func,
|
|
||||||
pattern: React.PropTypes.string,
|
|
||||||
placeholder: React.PropTypes.string,
|
|
||||||
readOnly: React.PropTypes.bool,
|
|
||||||
required: React.PropTypes.bool,
|
|
||||||
selectionDirection: React.PropTypes.string,
|
|
||||||
spellCheck: React.PropTypes.bool,
|
|
||||||
style: React.PropTypes.object,
|
style: React.PropTypes.object,
|
||||||
success: React.PropTypes.bool,
|
warning: React.PropTypes.string
|
||||||
tabIndex: React.PropTypes.string,
|
|
||||||
type: React.PropTypes.string,
|
|
||||||
value: React.PropTypes.string
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Input;
|
module.exports = Input;
|
||||||
|
@ -1,123 +1,91 @@
|
|||||||
const fns = require('../../shared/functions');
|
const fns = require('../../shared/functions');
|
||||||
const composers = require('../../shared/composers');
|
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
const Styled = require('styled-components');
|
const Styled = require('styled-components');
|
||||||
|
|
||||||
const {
|
const Label = require('../form/label');
|
||||||
rndId,
|
const LabelRow = require('../form/label-row');
|
||||||
remcalc
|
const Msg = require('../form/msg');
|
||||||
} = fns;
|
const Outlet = require('../form/outlet');
|
||||||
|
const View = require('../form/view');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
pseudoEl
|
rndId
|
||||||
} = composers;
|
} = fns;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
default: styled
|
default: styled
|
||||||
} = Styled;
|
} = Styled;
|
||||||
|
|
||||||
// TODO: this should be a constant
|
const defaultValue = rndId();
|
||||||
const StyledLabel = styled.div`
|
|
||||||
color: #464646;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SelectWrapper = styled.div`
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
border-left: ${remcalc(5)} solid transparent;
|
|
||||||
border-right: ${remcalc(5)} solid transparent;
|
|
||||||
border-bottom: ${remcalc(5)} solid black;
|
|
||||||
|
|
||||||
${pseudoEl({
|
|
||||||
top: remcalc(25),
|
|
||||||
right: remcalc(20)
|
|
||||||
})}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
|
|
||||||
const StyledSelect = styled.select`
|
const StyledSelect = styled.select`
|
||||||
font-size: ${remcalc(16)};
|
${Outlet}
|
||||||
min-width: ${remcalc(288)};
|
|
||||||
min-height: ${remcalc(54)};
|
|
||||||
border-radius: ${remcalc(4)};
|
|
||||||
padding-left: ${remcalc(20)};
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
box-shadow: inset 0 ${remcalc(3)} 0 0 rgba(0, 0, 0, 0.05);
|
|
||||||
border: solid ${remcalc(1)} #D8D8D8;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
${pseudoEl()}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* select[multiple] is valid CSS syntax - not added to lint library yet */
|
|
||||||
/* stylelint-disable */
|
|
||||||
&[multiple] {
|
|
||||||
/* stylelint-enable */
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
|
|
||||||
& option {
|
|
||||||
padding-left: ${remcalc(15)};
|
|
||||||
padding-right: ${remcalc(15)};
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Select = ({
|
const Select = (props) => {
|
||||||
autoFocus,
|
const {
|
||||||
children,
|
children,
|
||||||
className,
|
disabled = false,
|
||||||
disabled,
|
error = '',
|
||||||
form,
|
|
||||||
id = rndId(),
|
id = rndId(),
|
||||||
label,
|
label = '',
|
||||||
multiple,
|
multiple = false,
|
||||||
name,
|
placeholder = '',
|
||||||
required,
|
value = defaultValue,
|
||||||
selected
|
warning = ''
|
||||||
}) => {
|
} = props;
|
||||||
return (
|
|
||||||
<div className={className}>
|
|
||||||
<StyledLabel htmlFor={id}>
|
|
||||||
{label}
|
|
||||||
</StyledLabel>
|
|
||||||
|
|
||||||
<SelectWrapper>
|
const _label = !label.length ? null : (
|
||||||
|
<Label htmlFor={id}>
|
||||||
|
{label}
|
||||||
|
</Label>
|
||||||
|
);
|
||||||
|
|
||||||
|
const _placeholder = !placeholder ? null : (
|
||||||
|
<option disabled value={defaultValue}>
|
||||||
|
{placeholder}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
|
||||||
|
const msgType = error ? 'error' : (warning ? 'warning' : null);
|
||||||
|
|
||||||
|
const _msg = !(error || warning) ? null : (
|
||||||
|
<Msg type={msgType}>
|
||||||
|
{error ? error : warning}
|
||||||
|
</Msg>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View {...props} id=''>
|
||||||
|
<LabelRow>
|
||||||
|
{_label}
|
||||||
|
{_msg}
|
||||||
|
</LabelRow>
|
||||||
<StyledSelect
|
<StyledSelect
|
||||||
autoFocus={autoFocus}
|
defaultValue={defaultValue}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
form={form}
|
|
||||||
id={id}
|
id={id}
|
||||||
label={label}
|
|
||||||
multiple={multiple}
|
multiple={multiple}
|
||||||
name={name}
|
placeholder={placeholder}
|
||||||
required={required}
|
value={_placeholder ? value : undefined}
|
||||||
selected={selected}
|
|
||||||
>
|
>
|
||||||
|
{_placeholder}
|
||||||
{children}
|
{children}
|
||||||
</StyledSelect>
|
</StyledSelect>
|
||||||
</SelectWrapper>
|
</View>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Select.propTypes = {
|
Select.propTypes = {
|
||||||
autoFocus: React.PropTypes.bool,
|
|
||||||
children: React.PropTypes.node,
|
children: React.PropTypes.node,
|
||||||
className: React.PropTypes.string,
|
|
||||||
disabled: React.PropTypes.bool,
|
disabled: React.PropTypes.bool,
|
||||||
form: React.PropTypes.string,
|
error: React.PropTypes.string,
|
||||||
id: React.PropTypes.string,
|
id: React.PropTypes.string,
|
||||||
label: React.PropTypes.string,
|
label: React.PropTypes.string,
|
||||||
multiple: React.PropTypes.bool,
|
multiple: React.PropTypes.bool,
|
||||||
name: React.PropTypes.string,
|
placeholder: React.PropTypes.string,
|
||||||
required: React.PropTypes.bool,
|
value: React.PropTypes.string,
|
||||||
selected: React.PropTypes.bool
|
warning: React.PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Select;
|
module.exports = Select;
|
||||||
|
@ -5,22 +5,76 @@ const {
|
|||||||
} = require('@kadira/storybook');
|
} = require('@kadira/storybook');
|
||||||
|
|
||||||
const Select = require('./');
|
const Select = require('./');
|
||||||
|
const Base = require('../base');
|
||||||
|
|
||||||
|
|
||||||
storiesOf('Select', module)
|
storiesOf('Select', module)
|
||||||
.add('Default', () => (
|
.add('Default', () => (
|
||||||
<Select label='example select'>
|
<Base>
|
||||||
<option>Apple</option>
|
<Select label='Data Centers' placeholder='Select Location'>
|
||||||
<option>Banana</option>
|
<option value="1">Amsterdam, EU</option>
|
||||||
<option>Pear</option>
|
<option>San Francisco, USA</option>
|
||||||
<option>Orange</option>
|
<option>Seoul, South Korea</option>
|
||||||
|
<option>Tokyo, Japan</option>
|
||||||
</Select>
|
</Select>
|
||||||
|
</Base>
|
||||||
|
))
|
||||||
|
.add('disabled', () => (
|
||||||
|
<Base>
|
||||||
|
<Select
|
||||||
|
disabled
|
||||||
|
label='Data Centers'
|
||||||
|
placeholder='Select Location'
|
||||||
|
value='2'
|
||||||
|
>
|
||||||
|
<option value="1">Amsterdam, EU</option>
|
||||||
|
<option>San Francisco, USA</option>
|
||||||
|
<option>Seoul, South Korea</option>
|
||||||
|
<option>Tokyo, Japan</option>
|
||||||
|
</Select>
|
||||||
|
</Base>
|
||||||
|
))
|
||||||
|
.add('selected', () => (
|
||||||
|
<Base>
|
||||||
|
<Select
|
||||||
|
label='Data Centers'
|
||||||
|
placeholder='Select Location'
|
||||||
|
value='2'
|
||||||
|
>
|
||||||
|
<option value="1">Amsterdam, EU</option>
|
||||||
|
<option>San Francisco, USA</option>
|
||||||
|
<option>Seoul, South Korea</option>
|
||||||
|
<option>Tokyo, Japan</option>
|
||||||
|
</Select>
|
||||||
|
</Base>
|
||||||
))
|
))
|
||||||
.add('multiple', () => (
|
.add('multiple', () => (
|
||||||
<Select label='example multiple select' multiple>
|
<Base>
|
||||||
<option>1</option>
|
<Select label='Data Centers' multiple>
|
||||||
<option>2</option>
|
<option>Amsterdam, EU</option>
|
||||||
<option>3</option>
|
<option>San Francisco, USA</option>
|
||||||
<option>4</option>
|
<option>Seoul, South Korea</option>
|
||||||
<option>5</option>
|
<option>Tokyo, Japan</option>
|
||||||
</Select>
|
</Select>
|
||||||
|
</Base>
|
||||||
|
))
|
||||||
|
.add('warning', () => (
|
||||||
|
<Base>
|
||||||
|
<Select label='Data Centers' warning='Be warned!'>
|
||||||
|
<option>Amsterdam, EU</option>
|
||||||
|
<option>San Francisco, USA</option>
|
||||||
|
<option>Seoul, South Korea</option>
|
||||||
|
<option>Tokyo, Japan</option>
|
||||||
|
</Select>
|
||||||
|
</Base>
|
||||||
|
))
|
||||||
|
.add('error', () => (
|
||||||
|
<Base>
|
||||||
|
<Select error='How dare you?!' label='Data Centers'>
|
||||||
|
<option>Amsterdam, EU</option>
|
||||||
|
<option>San Francisco, USA</option>
|
||||||
|
<option>Seoul, South Korea</option>
|
||||||
|
<option>Tokyo, Japan</option>
|
||||||
|
</Select>
|
||||||
|
</Base>
|
||||||
));
|
));
|
Loading…
Reference in New Issue
Block a user