From 4358a016bd150262b968ad895a6269bda7cb2d50 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Fri, 19 Jan 2018 12:53:58 +0200 Subject: [PATCH 1/7] Add FieldCheckbox component --- .../FieldCheckbox/FieldCheckbox.css | 55 ++++++++++++++++ .../FieldCheckbox/FieldCheckbox.example.js | 42 +++++++++++++ src/components/FieldCheckbox/FieldCheckbox.js | 62 +++++++++++++++++++ .../SelectSingleFilter/SelectSingleFilter.css | 2 +- src/components/index.js | 1 + src/examples.js | 2 + src/marketplaceFonts.css | 14 ++--- 7 files changed, 167 insertions(+), 11 deletions(-) create mode 100644 src/components/FieldCheckbox/FieldCheckbox.css create mode 100644 src/components/FieldCheckbox/FieldCheckbox.example.js create mode 100644 src/components/FieldCheckbox/FieldCheckbox.js diff --git a/src/components/FieldCheckbox/FieldCheckbox.css b/src/components/FieldCheckbox/FieldCheckbox.css new file mode 100644 index 00000000..4da42133 --- /dev/null +++ b/src/components/FieldCheckbox/FieldCheckbox.css @@ -0,0 +1,55 @@ +@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 */ + &: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; +} diff --git a/src/components/FieldCheckbox/FieldCheckbox.example.js b/src/components/FieldCheckbox/FieldCheckbox.example.js new file mode 100644 index 00000000..6a11c31a --- /dev/null +++ b/src/components/FieldCheckbox/FieldCheckbox.example.js @@ -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 ( +
+ + + + + ); +}; + +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', +}; diff --git a/src/components/FieldCheckbox/FieldCheckbox.js b/src/components/FieldCheckbox/FieldCheckbox.js new file mode 100644 index 00000000..0f5541f2 --- /dev/null +++ b/src/components/FieldCheckbox/FieldCheckbox.js @@ -0,0 +1,62 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import { Field } from 'redux-form'; + +import css from './FieldCheckbox.css'; + +const FieldCheckbox = props => { + const { rootClassName, className, svgClassName, id, name, text } = props; + + const classes = classNames(rootClassName || css.root, className); + const svgClasses = classNames(svgClassName, css.checkbox); + + return ( + + + + + ); +}; + +FieldCheckbox.defaultProps = { + className: null, + rootClassName: null, + svgClassName: null, + text: null, +}; + +const { node, string } = PropTypes; + +FieldCheckbox.propTypes = { + className: string, + rootClassName: string, + svgClassName: string, + id: string.isRequired, + name: string.isRequired, + text: node, +}; + +export default FieldCheckbox; diff --git a/src/components/SelectSingleFilter/SelectSingleFilter.css b/src/components/SelectSingleFilter/SelectSingleFilter.css index 34ab88c1..42cf37c0 100644 --- a/src/components/SelectSingleFilter/SelectSingleFilter.css +++ b/src/components/SelectSingleFilter/SelectSingleFilter.css @@ -69,7 +69,7 @@ } .menuItem { - @apply --marketplaceSearchFilterOptionFontStyles; + @apply --marketplaceListingAttributeFontStyles; color: var(--matterColor); /* Layout */ diff --git a/src/components/index.js b/src/components/index.js index 98955b6a..7dc1790a 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -27,6 +27,7 @@ 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'; diff --git a/src/examples.js b/src/examples.js index 5f705ca7..d4d264a2 100644 --- a/src/examples.js +++ b/src/examples.js @@ -9,6 +9,7 @@ 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 FieldReviewRating from './components/FieldReviewRating/FieldReviewRating.example'; import * as Footer from './components/Footer/Footer.example'; import * as IconBannedUser from './components/IconBannedUser/IconBannedUser.example'; @@ -88,6 +89,7 @@ export { EmailVerificationForm, EnquiryForm, ExpandingTextarea, + FieldCheckbox, FieldReviewRating, Footer, IconBannedUser, diff --git a/src/marketplaceFonts.css b/src/marketplaceFonts.css index b0b5deae..3e10ae9d 100644 --- a/src/marketplaceFonts.css +++ b/src/marketplaceFonts.css @@ -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 ================ */ From eaa199305c0a9053400174549b76b11bee82194d Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Fri, 19 Jan 2018 12:55:01 +0200 Subject: [PATCH 2/7] Add FieldSetCheckbox component --- .../FieldSetCheckbox/FieldSetCheckbox.css | 28 +++++++ .../FieldSetCheckbox.example.js | 80 +++++++++++++++++++ .../FieldSetCheckbox/FieldSetCheckbox.js | 60 ++++++++++++++ src/components/index.js | 1 + src/examples.js | 2 + 5 files changed, 171 insertions(+) create mode 100644 src/components/FieldSetCheckbox/FieldSetCheckbox.css create mode 100644 src/components/FieldSetCheckbox/FieldSetCheckbox.example.js create mode 100644 src/components/FieldSetCheckbox/FieldSetCheckbox.js diff --git a/src/components/FieldSetCheckbox/FieldSetCheckbox.css b/src/components/FieldSetCheckbox/FieldSetCheckbox.css new file mode 100644 index 00000000..0550ae37 --- /dev/null +++ b/src/components/FieldSetCheckbox/FieldSetCheckbox.css @@ -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; + } +} diff --git a/src/components/FieldSetCheckbox/FieldSetCheckbox.example.js b/src/components/FieldSetCheckbox/FieldSetCheckbox.example.js new file mode 100644 index 00000000..06a628b5 --- /dev/null +++ b/src/components/FieldSetCheckbox/FieldSetCheckbox.example.js @@ -0,0 +1,80 @@ +import React from 'react'; +import { reduxForm, propTypes as formPropTypes } from 'redux-form'; +import { Button } from '../../components'; +import FieldSetCheckbox from './FieldSetCheckbox'; + +const formName = 'Styleguide.FieldSetCheckbox.Form'; + +const legend =

Amenities

; + +const componentProps = { + name: '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 { form, handleSubmit, invalid, pristine, submitting } = props; + + const submitDisabled = invalid || pristine || submitting; + + return ( +
+ + + + + ); +}; + +FormComponent.propTypes = formPropTypes; + +const Form = reduxForm({ + form: formName, +})(FormComponent); + +export const WithTwoColumns = { + component: Form, + props: { + onSubmit: values => { + console.log('Submit values: ', values); + }, + }, + group: 'inputs', +}; diff --git a/src/components/FieldSetCheckbox/FieldSetCheckbox.js b/src/components/FieldSetCheckbox/FieldSetCheckbox.js new file mode 100644 index 00000000..fd157608 --- /dev/null +++ b/src/components/FieldSetCheckbox/FieldSetCheckbox.js @@ -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 './FieldSetCheckbox.css'; + +class FieldSetCheckbox extends Component { + constructor(props) { + super(props); + this.state = { selected: [] }; + } + + render() { + const { rootClassName, className, name, legend, options, twoColumns } = this.props; + const classes = classNames(rootClassName || css.root, className); + const listClasses = twoColumns ? classNames(css.list, css.twoColumns) : css.list; + + return ( +
+ {legend ? {legend} : null} +
    + {options.map(option => { + const id = `${name}-${option.name}`; + return ( +
  • + +
  • + ); + })} +
+
+ ); + } +} + +FieldSetCheckbox.defaultProps = { + rootClassName: null, + className: null, + legend: null, + twoColumns: false, +}; + +const { arrayOf, bool, node, shape, string } = PropTypes; + +FieldSetCheckbox.propTypes = { + rootClassName: string, + className: string, + name: string.isRequired, + legend: node, + options: arrayOf( + shape({ + name: string.isRequired, + text: node.isRequired, + }) + ).isRequired, + twoColumns: bool, +}; + +export default FieldSetCheckbox; diff --git a/src/components/index.js b/src/components/index.js index 7dc1790a..bacf1b8a 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -32,6 +32,7 @@ export { default as FieldCustomAttributeSelect, } from './FieldCustomAttributeSelect/FieldCustomAttributeSelect'; export { default as FieldReviewRating } from './FieldReviewRating/FieldReviewRating'; +export { default as FieldSetCheckbox } from './FieldSetCheckbox/FieldSetCheckbox'; export { default as Footer } from './Footer/Footer'; export { default as Form } from './Form/Form'; export { default as IconBannedUser } from './IconBannedUser/IconBannedUser'; diff --git a/src/examples.js b/src/examples.js index d4d264a2..befdaeaa 100644 --- a/src/examples.js +++ b/src/examples.js @@ -11,6 +11,7 @@ import * as EditListingWizard from './components/EditListingWizard/EditListingWi import * as ExpandingTextarea from './components/ExpandingTextarea/ExpandingTextarea.example'; import * as FieldCheckbox from './components/FieldCheckbox/FieldCheckbox.example'; import * as FieldReviewRating from './components/FieldReviewRating/FieldReviewRating.example'; +import * as FieldSetCheckbox from './components/FieldSetCheckbox/FieldSetCheckbox.example'; import * as Footer from './components/Footer/Footer.example'; import * as IconBannedUser from './components/IconBannedUser/IconBannedUser.example'; import * as IconCheckmark from './components/IconCheckmark/IconCheckmark.example'; @@ -91,6 +92,7 @@ export { ExpandingTextarea, FieldCheckbox, FieldReviewRating, + FieldSetCheckbox, Footer, IconBannedUser, IconCheckmark, From 6bf7c85528d226040780dcaa764d3b3e1ad5bcc4 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Mon, 22 Jan 2018 11:02:26 +0200 Subject: [PATCH 3/7] Remove unused prop --- src/components/FieldSetCheckbox/FieldSetCheckbox.example.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/FieldSetCheckbox/FieldSetCheckbox.example.js b/src/components/FieldSetCheckbox/FieldSetCheckbox.example.js index 06a628b5..28758e3c 100644 --- a/src/components/FieldSetCheckbox/FieldSetCheckbox.example.js +++ b/src/components/FieldSetCheckbox/FieldSetCheckbox.example.js @@ -3,7 +3,7 @@ import { reduxForm, propTypes as formPropTypes } from 'redux-form'; import { Button } from '../../components'; import FieldSetCheckbox from './FieldSetCheckbox'; -const formName = 'Styleguide.FieldSetCheckbox.Form'; +const formName = 'Styleguide.FieldSetCheckbox'; const legend =

Amenities

; @@ -48,7 +48,7 @@ const componentProps = { }; const FormComponent = props => { - const { form, handleSubmit, invalid, pristine, submitting } = props; + const { handleSubmit, invalid, pristine, submitting } = props; const submitDisabled = invalid || pristine || submitting; From 0d32e60ae650140a17ff14ef78ebcd2c0a451068 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Mon, 22 Jan 2018 11:14:41 +0200 Subject: [PATCH 4/7] Highlight checkbox text on focus --- src/components/FieldCheckbox/FieldCheckbox.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/FieldCheckbox/FieldCheckbox.css b/src/components/FieldCheckbox/FieldCheckbox.css index 4da42133..d03b9882 100644 --- a/src/components/FieldCheckbox/FieldCheckbox.css +++ b/src/components/FieldCheckbox/FieldCheckbox.css @@ -22,7 +22,8 @@ display: inline; } - /* Hightlight the text on hover */ + /* Hightlight the text on hover and focus */ + &:focus + label .text, &:hover + label .text { color: var(--matterColorDark); } From 294b67b18175c3880f6db42406d0b47e22ca9da8 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Mon, 22 Jan 2018 11:15:10 +0200 Subject: [PATCH 5/7] Extract the checkbox svg into a separate component However, the icon component is not exposed to be used elsewhere as it is so tightly coupled to the input and label tags in the css. --- src/components/FieldCheckbox/FieldCheckbox.js | 57 +++++++++++-------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/src/components/FieldCheckbox/FieldCheckbox.js b/src/components/FieldCheckbox/FieldCheckbox.js index 0f5541f2..16daa3b6 100644 --- a/src/components/FieldCheckbox/FieldCheckbox.js +++ b/src/components/FieldCheckbox/FieldCheckbox.js @@ -5,36 +5,49 @@ import { Field } from 'redux-form'; import css from './FieldCheckbox.css'; +const IconCheckbox = props => { + const svgClasses = classNames(props.className, css.checkbox); + + return ( + + + + + + + + + + ); +}; + +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); - const svgClasses = classNames(svgClassName, css.checkbox); return ( @@ -48,8 +61,6 @@ FieldCheckbox.defaultProps = { text: null, }; -const { node, string } = PropTypes; - FieldCheckbox.propTypes = { className: string, rootClassName: string, From 23001ec9ab3ce9039e23d9ca5df2471b51f51f7e Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Mon, 22 Jan 2018 11:28:50 +0200 Subject: [PATCH 6/7] Rename FieldSetCheckbox to FieldGroupCheckbox --- .../FieldGroupCheckbox.css} | 0 .../FieldGroupCheckbox.example.js} | 6 +++--- .../FieldGroupCheckbox.js} | 10 +++++----- src/components/index.js | 2 +- src/examples.js | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) rename src/components/{FieldSetCheckbox/FieldSetCheckbox.css => FieldGroupCheckbox/FieldGroupCheckbox.css} (100%) rename src/components/{FieldSetCheckbox/FieldSetCheckbox.example.js => FieldGroupCheckbox/FieldGroupCheckbox.example.js} (90%) rename src/components/{FieldSetCheckbox/FieldSetCheckbox.js => FieldGroupCheckbox/FieldGroupCheckbox.js} (87%) diff --git a/src/components/FieldSetCheckbox/FieldSetCheckbox.css b/src/components/FieldGroupCheckbox/FieldGroupCheckbox.css similarity index 100% rename from src/components/FieldSetCheckbox/FieldSetCheckbox.css rename to src/components/FieldGroupCheckbox/FieldGroupCheckbox.css diff --git a/src/components/FieldSetCheckbox/FieldSetCheckbox.example.js b/src/components/FieldGroupCheckbox/FieldGroupCheckbox.example.js similarity index 90% rename from src/components/FieldSetCheckbox/FieldSetCheckbox.example.js rename to src/components/FieldGroupCheckbox/FieldGroupCheckbox.example.js index 28758e3c..df2c3517 100644 --- a/src/components/FieldSetCheckbox/FieldSetCheckbox.example.js +++ b/src/components/FieldGroupCheckbox/FieldGroupCheckbox.example.js @@ -1,9 +1,9 @@ import React from 'react'; import { reduxForm, propTypes as formPropTypes } from 'redux-form'; import { Button } from '../../components'; -import FieldSetCheckbox from './FieldSetCheckbox'; +import FieldGroupCheckbox from './FieldGroupCheckbox'; -const formName = 'Styleguide.FieldSetCheckbox'; +const formName = 'Styleguide.FieldGroupCheckbox'; const legend =

Amenities

; @@ -54,7 +54,7 @@ const FormComponent = props => { return (
- +