mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 12:43:11 +10:00
Add SelectField component
This commit is contained in:
parent
d1e7483842
commit
a25d535fd6
6 changed files with 170 additions and 1 deletions
17
src/components/SelectField/SelectField.css
Normal file
17
src/components/SelectField/SelectField.css
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
|
||||
}
|
||||
|
||||
.select {
|
||||
border-bottom-color: var(--attentionColor);
|
||||
}
|
||||
|
||||
.selectSuccess {
|
||||
border-bottom-color: var(--successColor);
|
||||
}
|
||||
|
||||
.selectError {
|
||||
border-bottom-color: var(--failColor);
|
||||
}
|
||||
45
src/components/SelectField/SelectField.example.js
Normal file
45
src/components/SelectField/SelectField.example.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* eslint-disable no-console */
|
||||
import React from 'react';
|
||||
import { reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import * as validators from '../../util/validators';
|
||||
import { Button } from '../../components';
|
||||
import SelectField from './SelectField';
|
||||
|
||||
const formName = 'Styleguide.SelectField.Form';
|
||||
|
||||
const FormComponent = props => {
|
||||
const { form, handleSubmit, invalid, pristine, submitting } = props;
|
||||
const required = validators.required('This field is required');
|
||||
const submitDisabled = invalid || pristine || submitting;
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<SelectField
|
||||
id={`${form}.select1`}
|
||||
name="select1"
|
||||
label="Choose an option:"
|
||||
validate={required}
|
||||
>
|
||||
<option value="">Pick something...</option>
|
||||
<option value="first">First option</option>
|
||||
<option value="second">Second option</option>
|
||||
</SelectField>
|
||||
<Button style={{ marginTop: 24 }} type="submit" disabled={submitDisabled}>Submit</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
FormComponent.propTypes = formPropTypes;
|
||||
|
||||
const Form = reduxForm({
|
||||
form: formName,
|
||||
})(FormComponent);
|
||||
|
||||
export const Select = {
|
||||
component: Form,
|
||||
props: {
|
||||
onSubmit: values => {
|
||||
console.log('submit values:', values);
|
||||
},
|
||||
},
|
||||
group: 'inputs',
|
||||
};
|
||||
67
src/components/SelectField/SelectField.js
Normal file
67
src/components/SelectField/SelectField.js
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import React, { PropTypes } from 'react';
|
||||
import { Field } from 'redux-form';
|
||||
import classNames from 'classnames';
|
||||
import { ValidationError } from '../../components';
|
||||
|
||||
import css from './SelectField.css';
|
||||
|
||||
const SelectFieldComponent = props => {
|
||||
const { rootClassName, className, id, label, input, meta, children } = props;
|
||||
|
||||
if (label && !id) {
|
||||
throw new Error('id required when a label is given');
|
||||
}
|
||||
|
||||
const { valid, invalid, touched, error } = meta;
|
||||
|
||||
// Error message and input error styles are only shown if the
|
||||
// field has been touched and the validation has failed.
|
||||
const hasError = touched && invalid && error;
|
||||
|
||||
const selectClasses = classNames(css.select, {
|
||||
[css.selectSuccess]: valid,
|
||||
[css.selectError]: hasError,
|
||||
});
|
||||
const selectProps = { className: selectClasses, ...input };
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
return (
|
||||
<div className={classes}>
|
||||
{label ? <label htmlFor={id}>{label}</label> : null}
|
||||
<select {...selectProps}>{children}</select>
|
||||
<ValidationError fieldMeta={meta} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
SelectFieldComponent.defaultProps = {
|
||||
rootClassName: null,
|
||||
className: null,
|
||||
id: null,
|
||||
label: null,
|
||||
children: null,
|
||||
};
|
||||
|
||||
const { string, object, node } = PropTypes;
|
||||
|
||||
SelectFieldComponent.propTypes = {
|
||||
rootClassName: string,
|
||||
className: string,
|
||||
|
||||
// Label is optional, but if it is given, an id is also required so
|
||||
// the label can reference the input in the `for` attribute
|
||||
id: string,
|
||||
label: string,
|
||||
|
||||
// Generated by redux-form's Field component
|
||||
input: object.isRequired,
|
||||
meta: object.isRequired,
|
||||
|
||||
children: node,
|
||||
};
|
||||
|
||||
const SelectField = props => {
|
||||
return <Field component={SelectFieldComponent} {...props} />;
|
||||
};
|
||||
|
||||
export default SelectField;
|
||||
|
|
@ -40,6 +40,7 @@ import SaleDetailsPanel from './SaleDetailsPanel/SaleDetailsPanel';
|
|||
import SearchIcon from './SearchIcon/SearchIcon';
|
||||
import SearchResultsPanel from './SearchResultsPanel/SearchResultsPanel';
|
||||
import Select from './Select/Select';
|
||||
import SelectField from './SelectField/SelectField';
|
||||
import StripeBankAccountToken from './StripeBankAccountToken/StripeBankAccountToken';
|
||||
import TabNav from './TabNav/TabNav';
|
||||
import Tabs from './Tabs/Tabs';
|
||||
|
|
@ -92,6 +93,7 @@ export {
|
|||
SearchIcon,
|
||||
SearchResultsPanel,
|
||||
Select,
|
||||
SelectField,
|
||||
StripeBankAccountToken,
|
||||
TabNav,
|
||||
Tabs,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import * as LocationAutocompleteInput
|
|||
from './components/LocationAutocompleteInput/LocationAutocompleteInput.example';
|
||||
import * as PaginationLinks from './components/PaginationLinks/PaginationLinks.example';
|
||||
import * as ResponsiveImage from './components/ResponsiveImage/ResponsiveImage.example';
|
||||
import * as SelectField from './components/SelectField/SelectField.example';
|
||||
import * as StripeBankAccountToken
|
||||
from './components/StripeBankAccountToken/StripeBankAccountToken.example';
|
||||
import * as TabNav from './components/TabNav/TabNav.example';
|
||||
|
|
@ -73,6 +74,7 @@ export {
|
|||
PasswordForgottenForm,
|
||||
PayoutDetailsForm,
|
||||
ResponsiveImage,
|
||||
SelectField,
|
||||
SignupForm,
|
||||
StripeBankAccountToken,
|
||||
StripePaymentForm,
|
||||
|
|
|
|||
|
|
@ -373,6 +373,41 @@
|
|||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
--marketplaceSelectStyles: {
|
||||
|
||||
/* Dimensions */
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 5px 0 4px 0;
|
||||
|
||||
/* Unset user agent styles */
|
||||
appearance: none;
|
||||
|
||||
/* Borders */
|
||||
border: none;
|
||||
border-bottom-width: 2px;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: var(--marketplaceColor);
|
||||
border-radius: 0;
|
||||
|
||||
/* Background */
|
||||
background-image: url('data:image/svg+xml;utf8,<svg width="16" height="10" viewBox="0 0 16 10" xmlns="http://www.w3.org/2000/svg"><path d="M15.027 2.5a.577.577 0 0 0 0-.813L13.545.214a.566.566 0 0 0-.804 0L8 4.955 3.259.215a.566.566 0 0 0-.804 0L.973 1.686a.577.577 0 0 0 0 .813l6.625 6.616c.223.223.58.223.804 0L15.027 2.5z" fill="#4A4A4A" fill-rule="evenodd"/></svg>');
|
||||
background-size: 16px 16px;
|
||||
background-position: center right;
|
||||
|
||||
/* Effects */
|
||||
|
||||
cursor: pointer;
|
||||
transition: border-bottom-color var(--transitionStyle);
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
border-bottom-color: var(--matterColor);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ================ Custom media queries ================ */
|
||||
|
|
@ -401,6 +436,7 @@ h6 { @apply --marketplaceH6FontStyles; }
|
|||
html,
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
li {
|
||||
@apply --marketplaceDefaultFontStyles
|
||||
}
|
||||
|
|
@ -441,7 +477,7 @@ label {
|
|||
}
|
||||
|
||||
select {
|
||||
border: none;
|
||||
@apply --marketplaceSelectStyles;
|
||||
}
|
||||
|
||||
input {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue