mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 20:53:24 +10:00
Merge pull request #660 from sharetribe/multi-select-component
Field component for multiple checkboxes
This commit is contained in:
commit
24390c3b8d
10 changed files with 350 additions and 11 deletions
56
src/components/FieldCheckbox/FieldCheckbox.css
Normal file
56
src/components/FieldCheckbox/FieldCheckbox.css
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
width: 0;
|
||||
|
||||
/* Highlight the borders if the checkbox is hovered, focused or checked */
|
||||
&:hover + label .box,
|
||||
&:focus + label .box,
|
||||
&:checked + label .box {
|
||||
stroke: var(--marketplaceColor);
|
||||
}
|
||||
|
||||
/* Display the "check" when checked */
|
||||
&:checked + label .checked {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* Hightlight the text on hover and focus */
|
||||
&:focus + label .text,
|
||||
&:hover + label .text {
|
||||
color: var(--matterColorDark);
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.checked {
|
||||
display: none;
|
||||
fill: var(--marketplaceColor);
|
||||
}
|
||||
|
||||
.box {
|
||||
stroke: var(--matterColorAnti);
|
||||
}
|
||||
|
||||
.text {
|
||||
@apply --marketplaceListingAttributeFontStyles;
|
||||
color: var(--matterColor);
|
||||
margin-top: -1px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
42
src/components/FieldCheckbox/FieldCheckbox.example.js
Normal file
42
src/components/FieldCheckbox/FieldCheckbox.example.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import React from 'react';
|
||||
import { reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import { Button } from '../../components';
|
||||
import FieldCheckbox from './FieldCheckbox';
|
||||
|
||||
const formName = 'Styleguide.FieldCheckbox.Form';
|
||||
|
||||
const FormComponent = props => {
|
||||
const { form, handleSubmit, invalid, pristine, submitting } = props;
|
||||
|
||||
const submitDisabled = invalid || pristine || submitting;
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<FieldCheckbox
|
||||
id="field-checkbox-example-id"
|
||||
name="field-checkbox-example-name"
|
||||
text="Check here"
|
||||
/>
|
||||
|
||||
<Button style={{ marginTop: 24 }} type="submit" disabled={submitDisabled}>
|
||||
Submit
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
FormComponent.propTypes = formPropTypes;
|
||||
|
||||
const Form = reduxForm({
|
||||
form: formName,
|
||||
})(FormComponent);
|
||||
|
||||
export const Checkbox = {
|
||||
component: Form,
|
||||
props: {
|
||||
onSubmit: values => {
|
||||
console.log('Submit values of FieldCheckbox: ', values);
|
||||
},
|
||||
},
|
||||
group: 'inputs',
|
||||
};
|
||||
73
src/components/FieldCheckbox/FieldCheckbox.js
Normal file
73
src/components/FieldCheckbox/FieldCheckbox.js
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { Field } from 'redux-form';
|
||||
|
||||
import css from './FieldCheckbox.css';
|
||||
|
||||
const IconCheckbox = props => {
|
||||
const svgClasses = classNames(props.className, css.checkbox);
|
||||
|
||||
return (
|
||||
<svg className={svgClasses} width="14" height="14" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<g transform="translate(2 2)">
|
||||
<path
|
||||
className={css.checked}
|
||||
fill="#C0392B"
|
||||
d="M9.9992985 1.5048549l-.0194517 6.9993137C9.977549 9.3309651 9.3066522 10 8.4798526 10H1.5001008c-.8284271 0-1.5-.6715729-1.5-1.5l-.000121-7c0-.8284271.6715728-1.5 1.5-1.5h.000121l6.9993246.0006862c.8284272.000067 1.4999458.671694 1.499879 1.5001211a1.5002208 1.5002208 0 0 1-.0000059.0040476z"
|
||||
/>
|
||||
<path
|
||||
className={css.box}
|
||||
strokeWidth="2"
|
||||
d="M10.9992947 1.507634l-.0194518 6.9993137C10.9760133 9.8849417 9.8578519 11 8.4798526 11H1.5001008c-1.3807119 0-2.5-1.1192881-2.5-2.4999827L-1.0000202 1.5c0-1.3807119 1.119288-2.5 2.500098-2.5l6.9994284.0006862c1.3807118.0001115 2.4999096 1.11949 2.4997981 2.5002019-.0000018.003373-.0000018.003373-.0000096.0067458z"
|
||||
/>
|
||||
</g>
|
||||
<path
|
||||
d="M5.636621 10.7824771L3.3573694 8.6447948c-.4764924-.4739011-.4764924-1.2418639 0-1.7181952.4777142-.473901 1.251098-.473901 1.7288122 0l1.260291 1.1254782 2.8256927-4.5462307c.3934117-.5431636 1.1545778-.6695372 1.7055985-.278265.5473554.3912721.6731983 1.150729.2797866 1.6951077l-3.6650524 5.709111c-.2199195.306213-.5803433.5067097-.9920816.5067097-.3225487 0-.6328797-.1263736-.8637952-.3560334z"
|
||||
fill="#FFF"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
IconCheckbox.defaultProps = { className: null };
|
||||
|
||||
const { node, string } = PropTypes;
|
||||
|
||||
IconCheckbox.propTypes = { className: string };
|
||||
|
||||
const FieldCheckbox = props => {
|
||||
const { rootClassName, className, svgClassName, id, name, text } = props;
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
return (
|
||||
<span className={classes}>
|
||||
<Field id={id} name={name} className={css.input} type="checkbox" component="input" />
|
||||
<label htmlFor={id} className={css.label}>
|
||||
<IconCheckbox className={svgClassName} />
|
||||
<span className={css.text}>{text}</span>
|
||||
</label>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
FieldCheckbox.defaultProps = {
|
||||
className: null,
|
||||
rootClassName: null,
|
||||
svgClassName: null,
|
||||
text: null,
|
||||
};
|
||||
|
||||
FieldCheckbox.propTypes = {
|
||||
className: string,
|
||||
rootClassName: string,
|
||||
svgClassName: string,
|
||||
id: string.isRequired,
|
||||
name: string.isRequired,
|
||||
text: node,
|
||||
};
|
||||
|
||||
export default FieldCheckbox;
|
||||
28
src/components/FieldGroupCheckbox/FieldGroupCheckbox.css
Normal file
28
src/components/FieldGroupCheckbox/FieldGroupCheckbox.css
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.twoColumns {
|
||||
@media (--viewportMedium) {
|
||||
columns: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 2px 0;
|
||||
|
||||
/* Fix broken multi-column layout in Chrome */
|
||||
page-break-inside: avoid;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
padding: 4px 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
import React from 'react';
|
||||
import { reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import { Button } from '../../components';
|
||||
import FieldGroupCheckbox from './FieldGroupCheckbox';
|
||||
|
||||
const formName = 'Styleguide.FieldGroupCheckboxForm';
|
||||
|
||||
const legend = <h3>Amenities</h3>;
|
||||
|
||||
const componentProps = {
|
||||
id: `${formName}.amenities`,
|
||||
legend: legend,
|
||||
options: [
|
||||
{
|
||||
name: 'towels',
|
||||
text: 'Towels',
|
||||
},
|
||||
{
|
||||
name: 'bathroom',
|
||||
text: 'Bathfoom',
|
||||
},
|
||||
{
|
||||
name: 'swimming_pool',
|
||||
text: 'Swimming pool',
|
||||
},
|
||||
{
|
||||
name: 'own_drinks',
|
||||
text: 'Own drinks allowed',
|
||||
},
|
||||
{
|
||||
name: 'jacuzzi',
|
||||
text: 'Jacuzzi',
|
||||
},
|
||||
{
|
||||
name: 'audiovisual_entertainment',
|
||||
text: 'Audiovisual entertainment',
|
||||
},
|
||||
{
|
||||
name: 'barbeque',
|
||||
text: 'Barbeque',
|
||||
},
|
||||
{
|
||||
name: 'own_food_allowed',
|
||||
text: 'Own food allowed',
|
||||
},
|
||||
],
|
||||
twoColumns: true,
|
||||
};
|
||||
|
||||
const FormComponent = props => {
|
||||
const { handleSubmit, invalid, pristine, submitting } = props;
|
||||
|
||||
const submitDisabled = invalid || pristine || submitting;
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<FieldGroupCheckbox {...componentProps} />
|
||||
|
||||
<Button style={{ marginTop: 24 }} type="submit" disabled={submitDisabled}>
|
||||
Submit
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
FormComponent.propTypes = formPropTypes;
|
||||
|
||||
const Form = reduxForm({
|
||||
form: formName,
|
||||
})(FormComponent);
|
||||
|
||||
export const WithTwoColumns = {
|
||||
component: Form,
|
||||
props: {
|
||||
onSubmit: values => {
|
||||
console.log('Submit values: ', values);
|
||||
},
|
||||
},
|
||||
group: 'inputs',
|
||||
};
|
||||
60
src/components/FieldGroupCheckbox/FieldGroupCheckbox.js
Normal file
60
src/components/FieldGroupCheckbox/FieldGroupCheckbox.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { FieldCheckbox } from '../../components';
|
||||
import css from './FieldGroupCheckbox.css';
|
||||
|
||||
class FieldGroupCheckbox extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { selected: [] };
|
||||
}
|
||||
|
||||
render() {
|
||||
const { rootClassName, className, id, legend, options, twoColumns } = this.props;
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
const listClasses = twoColumns ? classNames(css.list, css.twoColumns) : css.list;
|
||||
|
||||
return (
|
||||
<fieldset className={classes}>
|
||||
{legend ? <legend>{legend}</legend> : null}
|
||||
<ul className={listClasses}>
|
||||
{options.map(option => {
|
||||
const fieldId = `${id}.${option.name}`;
|
||||
return (
|
||||
<li key={fieldId} className={css.item}>
|
||||
<FieldCheckbox id={fieldId} name={option.name} text={option.text} />
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</fieldset>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FieldGroupCheckbox.defaultProps = {
|
||||
rootClassName: null,
|
||||
className: null,
|
||||
legend: null,
|
||||
twoColumns: false,
|
||||
};
|
||||
|
||||
const { arrayOf, bool, node, shape, string } = PropTypes;
|
||||
|
||||
FieldGroupCheckbox.propTypes = {
|
||||
rootClassName: string,
|
||||
className: string,
|
||||
id: string.isRequired,
|
||||
legend: node,
|
||||
options: arrayOf(
|
||||
shape({
|
||||
name: string.isRequired,
|
||||
text: node.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
twoColumns: bool,
|
||||
};
|
||||
|
||||
export default FieldGroupCheckbox;
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
}
|
||||
|
||||
.menuItem {
|
||||
@apply --marketplaceSearchFilterOptionFontStyles;
|
||||
@apply --marketplaceListingAttributeFontStyles;
|
||||
color: var(--matterColor);
|
||||
|
||||
/* Layout */
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@ export { default as EditListingWizard } from './EditListingWizard/EditListingWiz
|
|||
export { default as ExpandingTextarea } from './ExpandingTextarea/ExpandingTextarea';
|
||||
export { default as ExternalLink } from './ExternalLink/ExternalLink';
|
||||
export { default as FilterPanel } from './FilterPanel/FilterPanel';
|
||||
export { default as FieldCheckbox } from './FieldCheckbox/FieldCheckbox';
|
||||
export {
|
||||
default as FieldCustomAttributeSelect,
|
||||
} from './FieldCustomAttributeSelect/FieldCustomAttributeSelect';
|
||||
export { default as FieldGroupCheckbox } from './FieldGroupCheckbox/FieldGroupCheckbox';
|
||||
export { default as FieldReviewRating } from './FieldReviewRating/FieldReviewRating';
|
||||
export { default as Footer } from './Footer/Footer';
|
||||
export { default as Form } from './Form/Form';
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import * as CurrencyInputField from './components/CurrencyInputField/CurrencyInp
|
|||
import * as DateRangeInputField from './components/DateRangeInputField/DateRangeInputField.example';
|
||||
import * as EditListingWizard from './components/EditListingWizard/EditListingWizard.example';
|
||||
import * as ExpandingTextarea from './components/ExpandingTextarea/ExpandingTextarea.example';
|
||||
import * as FieldCheckbox from './components/FieldCheckbox/FieldCheckbox.example';
|
||||
import * as FieldGroupCheckbox from './components/FieldGroupCheckbox/FieldGroupCheckbox.example';
|
||||
import * as FieldReviewRating from './components/FieldReviewRating/FieldReviewRating.example';
|
||||
import * as Footer from './components/Footer/Footer.example';
|
||||
import * as IconBannedUser from './components/IconBannedUser/IconBannedUser.example';
|
||||
|
|
@ -88,6 +90,8 @@ export {
|
|||
EmailVerificationForm,
|
||||
EnquiryForm,
|
||||
ExpandingTextarea,
|
||||
FieldCheckbox,
|
||||
FieldGroupCheckbox,
|
||||
FieldReviewRating,
|
||||
Footer,
|
||||
IconBannedUser,
|
||||
|
|
|
|||
|
|
@ -262,17 +262,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
--marketplaceSearchFilterOptionFontStyles {
|
||||
--marketplaceListingAttributeFontStyles {
|
||||
font-family: 'sofiapro', Helvetica, Arial, sans-serif;
|
||||
font-weight: var(--fontWeightSemiBold);
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
font-weight: var(--fontWeightMedium);
|
||||
font-size: 18px;
|
||||
line-height: 32px;
|
||||
}
|
||||
font-weight: var(--fontWeightMedium);
|
||||
font-size: 18px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
/* ================ Tabbed navigation font styles ================ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue