From a3f6c79ffbc195dad4de0c6eb1ac2ae7ffea4443 Mon Sep 17 00:00:00 2001 From: Minghua Sun Date: Thu, 19 Jul 2018 17:41:42 -0400 Subject: [PATCH 01/12] extend ButtonWIthIcon to replace ButtonSearch --- .../ButtonSearch/ButtonSearch.stories.js | 2 +- .../atoms/buttons/ButtonSearch/index.js | 2 +- .../ButtonWithIcon.knob.options.js | 5 ++++ .../buttons/ButtonWithIcon/ButtonWithIcon.md | 6 ++++ .../ButtonWithIcon/ButtonWithIcon.stories.js | 29 +++++++++++++++++-- .../atoms/buttons/ButtonWithIcon/index.js | 20 +++++++++---- 6 files changed, 55 insertions(+), 9 deletions(-) diff --git a/react/src/components/atoms/buttons/ButtonSearch/ButtonSearch.stories.js b/react/src/components/atoms/buttons/ButtonSearch/ButtonSearch.stories.js index 60cc725769..93c9fd3a7b 100644 --- a/react/src/components/atoms/buttons/ButtonSearch/ButtonSearch.stories.js +++ b/react/src/components/atoms/buttons/ButtonSearch/ButtonSearch.stories.js @@ -11,7 +11,7 @@ import ButtonSearchReadme from './ButtonSearch.md'; storiesOf('atoms/buttons', module) .addDecorator(withKnobs) .add( - 'ButtonSearch', + 'ButtonSearchold', withInfo(`
${ButtonSearchReadme}
`)(() => { const props = { text: text('ButtonSearch.text', 'Search'), diff --git a/react/src/components/atoms/buttons/ButtonSearch/index.js b/react/src/components/atoms/buttons/ButtonSearch/index.js index 899a81d2c7..da79fc12e2 100644 --- a/react/src/components/atoms/buttons/ButtonSearch/index.js +++ b/react/src/components/atoms/buttons/ButtonSearch/index.js @@ -11,7 +11,7 @@ const ButtonSearch = (buttonSearch) => { className={buttonSearch.classes.join(' ')} onClick={(e) => { if (onButtonClick) buttonSearch.onClick(e); }} > - {buttonSearch.text} + {buttonSearch.text} )); diff --git a/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.knob.options.js b/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.knob.options.js index c375504caf..c6711fa337 100644 --- a/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.knob.options.js +++ b/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.knob.options.js @@ -6,5 +6,10 @@ export default { color: { '': 'grey (default)', green: 'green' + }, + type: { + button: 'button', + submit: 'submit', + reset: 'reset' } }; diff --git a/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.md b/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.md index c06169dafe..947cf4b242 100644 --- a/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.md +++ b/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.md @@ -1,2 +1,8 @@ ### Description A button that displays with an icon component. +e.g. ButtonSearch, which is used for submitting a keyword search. +e.g. Button with chevron, which is used for toggling between the expanded state and the collapsed state. + +### Changes for React +* Button with Icon is a common button pattern that is currently not available in Patternlab. It's an extension on top of the [Button Search atom](https://mayflower.digital.mass.gov/?p=atoms-button-search). +* `ariaLabel` string: To improve accessibility of this component, an aria-label can be added if the displayed text is not helpful to assistive technologies. diff --git a/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js b/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js index 3fd00b63f3..0bfcbd6a8e 100644 --- a/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js +++ b/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js @@ -25,9 +25,10 @@ storiesOf('atoms/buttons', module) const props = { onClick: action('ButtonWithIcon clicked'), text: text('ButtonWithIcon.text', 'Button With Icon'), + type: select('ButtonWithIcon.type', buttonWithIconOptions.type, 'submit'), classes: array('ButtonWithIcon.classes', []), icon: select('ButtonWithIcon.icon', Object.keys(icons), 'chevron'), - iconSize: select('ButtonWithIcon.iconSize', buttonWithIconOptions.size), + iconSize: select('ButtonWithIcon.iconSize', buttonWithIconOptions.size, 'small'), iconColor: select('ButtonWithIcon.iconColor', buttonWithIconOptions.color), canExpand: boolean('ButtonWithIcon.canExpand', true), expanded: boolean('ButtonWithIcon.expanded', true), @@ -41,4 +42,28 @@ storiesOf('atoms/buttons', module) ); }) - ); + ) + .add( + 'ButtonSearch', + withInfo(`
${buttonWithIconReadme}
`)(() => { + const props = { + onClick: action('ButtonWithIcon clicked'), + text: text('ButtonWithIcon.text', 'Search'), + type: select('ButtonWithIcon.type', buttonWithIconOptions.type, 'submit'), + classes: array('ButtonWithIcon.classes', []), + icon: select('ButtonWithIcon.icon', Object.keys(icons), 'search'), + iconSize: select('ButtonWithIcon.iconSize', buttonWithIconOptions.size, ''), + iconColor: select('ButtonWithIcon.iconColor', buttonWithIconOptions.color, 'green'), + canExpand: boolean('ButtonWithIcon.canExpand', false), + expanded: boolean('ButtonWithIcon.expanded', true), + capitalized: boolean('ButtonWithIcon.capitalized', false) + }; + + // Set the icon prop to the actual element based on knob selection. + props.icon = icons[props.icon]; + + return( + + ); + }) + ) diff --git a/react/src/components/atoms/buttons/ButtonWithIcon/index.js b/react/src/components/atoms/buttons/ButtonWithIcon/index.js index c885dea3ff..1331736908 100644 --- a/react/src/components/atoms/buttons/ButtonWithIcon/index.js +++ b/react/src/components/atoms/buttons/ButtonWithIcon/index.js @@ -36,13 +36,13 @@ class ButtonWithIcon extends React.Component { classNames += ' ma__icon-green'; } const buttonProps = { - type: 'submit', + type: this.props.type, className: `ma__button-icon ${classNames}`, onClick: this.handleClick, tabIndex: 0 }; return( - @@ -57,6 +57,8 @@ ButtonWithIcon.propTypes = { setButtonRef: PropTypes.func, // Button text. text: PropTypes.string, + /** HTML - )); -}; - -ButtonSearch.propTypes = { - /** Custom click handler function. */ - onClick: PropTypes.func, - /** The text to display in the button */ - text: PropTypes.string, - /** The aria-label property is used to provide the label to any assistive - * technologies. This is useful if the text value is not descriptive of the - * button's functionality. */ - ariaLabel: PropTypes.string.isRequired, - /** Optional classes to apply to the button in place of the default */ - classes: PropTypes.arrayOf(PropTypes.string) -}; - -ButtonSearch.defaultProps = { - text: 'Search', - classes: ['ma__button-search'] -}; - -export default ButtonSearch; From bd51dfb5ecdc953865940ce742515997a8e1d1ca Mon Sep 17 00:00:00 2001 From: Minghua Sun Date: Thu, 19 Jul 2018 18:51:37 -0400 Subject: [PATCH 06/12] fix double border --- .../components/molecules/HeaderSearch/HeaderSearch.scss | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/react/src/components/molecules/HeaderSearch/HeaderSearch.scss b/react/src/components/molecules/HeaderSearch/HeaderSearch.scss index b978265d81..073215dd10 100644 --- a/react/src/components/molecules/HeaderSearch/HeaderSearch.scss +++ b/react/src/components/molecules/HeaderSearch/HeaderSearch.scss @@ -5,6 +5,10 @@ display: flex; position: relative; + .ma__button-icon { + border-right: none; + } + &--responsive { @media ($bp-medium-max) { > div:first-child { @@ -15,8 +19,5 @@ } .ma__form { display: flex; - .ma__button-icon { - border-right: none; - } } } From cae56c04a929424377b4ba5d3c5631bd954199e0 Mon Sep 17 00:00:00 2001 From: Minghua Sun Date: Thu, 19 Jul 2018 19:19:34 -0400 Subject: [PATCH 07/12] remove button search --- react/src/components/molecules/SearchBannerForm/index.js | 6 +++--- react/src/index.js | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/react/src/components/molecules/SearchBannerForm/index.js b/react/src/components/molecules/SearchBannerForm/index.js index c6be0a2df2..bc86ea488d 100644 --- a/react/src/components/molecules/SearchBannerForm/index.js +++ b/react/src/components/molecules/SearchBannerForm/index.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import InputText from '../../atoms/forms/InputText'; -import ButtonSearch from '../../atoms/buttons/ButtonSearch'; +import ButtonWithIcon from '../../atoms/buttons/ButtonWithIcon'; const SearchBannerForm = (searchBannerForm) => { let { classes = [] } = searchBannerForm.buttonSearch; @@ -13,7 +13,7 @@ const SearchBannerForm = (searchBannerForm) => {
- + ); }; @@ -26,7 +26,7 @@ SearchBannerForm.propTypes = { /** The properties for the text input field */ inputText: PropTypes.shape(InputText.propTypes).isRequired, /** The Search button */ - buttonSearch: PropTypes.shape(ButtonSearch.propTypes).isRequired + buttonSearch: PropTypes.shape(ButtonWithIcon.propTypes).isRequired }; export default SearchBannerForm; diff --git a/react/src/index.js b/react/src/index.js index c866ba7f66..d82f52dada 100644 --- a/react/src/index.js +++ b/react/src/index.js @@ -10,7 +10,6 @@ export Placeholder from './components/base/Placeholder' export Divider from './components/atoms/Divider'; // @atoms/@buttons export Button from './components/atoms/buttons/Button'; -export ButtonSearch from './components/atoms/buttons/ButtonSearch'; export ButtonSort from './components/atoms/buttons/ButtonSort'; export ButtonToggle from './components/atoms/buttons/ButtonToggle'; export ButtonWithIcon from './components/atoms/buttons/ButtonWithIcon'; From f26f1423274bbba4c3c706da5221fa7ae330adbb Mon Sep 17 00:00:00 2001 From: Minghua Sun Date: Tue, 24 Jul 2018 10:04:55 -0400 Subject: [PATCH 08/12] update based on comments --- .../ButtonWithIcon/ButtonWithIcon.stories.js | 2 +- .../atoms/buttons/ButtonWithIcon/index.js | 25 +++++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js b/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js index b0f67680f9..8208f4c215 100644 --- a/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js +++ b/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js @@ -66,4 +66,4 @@ storiesOf('atoms/buttons', module) ); }) - ) + ); diff --git a/react/src/components/atoms/buttons/ButtonWithIcon/index.js b/react/src/components/atoms/buttons/ButtonWithIcon/index.js index e2f9ecc424..f8e9484dd5 100644 --- a/react/src/components/atoms/buttons/ButtonWithIcon/index.js +++ b/react/src/components/atoms/buttons/ButtonWithIcon/index.js @@ -21,27 +21,30 @@ class ButtonWithIcon extends React.Component { } } render() { - const { classes, canExpand, expanded, capitalized, iconSize, iconColor, icon, type } = this.props - let classNames = classes.join(' '); + const { + classes, canExpand, expanded, capitalized, iconSize, iconColor, icon, type + } = this.props; if (canExpand) { - classNames += ' ma__button-icon--expandable'; - classNames += expanded ? ' ma__button-icon--expanded' : ''; + classes.push('ma__button-icon--expandable'); + if (expanded) { + classes.push('ma__button-icon--expanded'); + } } if (capitalized) { - classNames += ' ma__button-capitalized'; + classes.push('ma__button-capitalized'); } if (iconSize === 'small' || icon.type.name === 'SvgChevron') { - classNames += ' ma__icon-small'; + classes.push('ma__icon-small'); } if (iconColor === 'green') { - classNames += ' ma__icon-green'; + classes.push('ma__icon-green'); } if (icon.type.name === 'SvgSearch') { - classNames += ' ma__button-search'; + classes.push('ma__button-search'); } - console.log(type.name) + const classNames = classes.join(' '); const buttonProps = { - type: type, + type, className: `ma__button-icon ${classNames}`, onClick: this.handleClick, tabIndex: 0 @@ -81,7 +84,7 @@ ButtonWithIcon.propTypes = { /** The aria-label property is used to provide the label to any assistive * technologies. This is useful if the text value is not descriptive of the * button's functionality. */ - ariaLabel: PropTypes.string, + ariaLabel: PropTypes.string }; ButtonWithIcon.defaultProps = { From e637d20e3f42e2fa1fa28315607e4ff8c4803b36 Mon Sep 17 00:00:00 2001 From: Minghua Sun Date: Tue, 24 Jul 2018 10:29:27 -0400 Subject: [PATCH 09/12] revert push to array then join --- .../atoms/buttons/ButtonWithIcon/index.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/react/src/components/atoms/buttons/ButtonWithIcon/index.js b/react/src/components/atoms/buttons/ButtonWithIcon/index.js index f8e9484dd5..d70ff4849a 100644 --- a/react/src/components/atoms/buttons/ButtonWithIcon/index.js +++ b/react/src/components/atoms/buttons/ButtonWithIcon/index.js @@ -24,25 +24,25 @@ class ButtonWithIcon extends React.Component { const { classes, canExpand, expanded, capitalized, iconSize, iconColor, icon, type } = this.props; + let classNames = classes.join(' '); if (canExpand) { - classes.push('ma__button-icon--expandable'); + classNames += ' ma__button-icon--expandable'; if (expanded) { - classes.push('ma__button-icon--expanded'); + classNames += ' ma__button-icon--expanded'; } } if (capitalized) { - classes.push('ma__button-capitalized'); + classNames += ' ma__button-capitalized'; } if (iconSize === 'small' || icon.type.name === 'SvgChevron') { - classes.push('ma__icon-small'); + classNames += ' ma__icon-small'; } if (iconColor === 'green') { - classes.push('ma__icon-green'); + classNames += ' ma__icon-green'; } if (icon.type.name === 'SvgSearch') { - classes.push('ma__button-search'); + classNames += ' ma__button-search'; } - const classNames = classes.join(' '); const buttonProps = { type, className: `ma__button-icon ${classNames}`, From fec3fbc1e1aeaa328fc380053e66fecc36bfd062 Mon Sep 17 00:00:00 2001 From: Minghua Sun Date: Tue, 24 Jul 2018 16:22:00 -0400 Subject: [PATCH 10/12] attach props to buttonSearch --- .../molecules/HeaderSearch/HeaderSearch.stories.js | 5 +---- react/src/components/molecules/HeaderSearch/index.js | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/react/src/components/molecules/HeaderSearch/HeaderSearch.stories.js b/react/src/components/molecules/HeaderSearch/HeaderSearch.stories.js index 242f93e8ef..3ac8fc95c5 100644 --- a/react/src/components/molecules/HeaderSearch/HeaderSearch.stories.js +++ b/react/src/components/molecules/HeaderSearch/HeaderSearch.stories.js @@ -16,10 +16,7 @@ storiesOf('molecules', module).addDecorator(withKnobs) const props = { placeholder: text('HeaderSearch.placeholder', 'Search Mass.gov'), buttonSearch: { - onClick: (e) => { - action('Button clicked')(e); - e.preventDefault(); - }, + onClick: action('Button clicked'), ariaLabel: text('HeaderSearch.buttonSearch.ariaLabel', 'Search'), text: text('HeaderSearch.buttonSearch.text', 'Search') }, diff --git a/react/src/components/molecules/HeaderSearch/index.js b/react/src/components/molecules/HeaderSearch/index.js index e44667e223..c9fad5a498 100644 --- a/react/src/components/molecules/HeaderSearch/index.js +++ b/react/src/components/molecules/HeaderSearch/index.js @@ -46,7 +46,7 @@ class HeaderSearch extends React.Component { type="search" value={this.state.value} /> - + From 58be836171305563b53a8b646dc92991ed8b1de4 Mon Sep 17 00:00:00 2001 From: Minghua Sun Date: Wed, 25 Jul 2018 14:57:16 -0400 Subject: [PATCH 11/12] add changelog --- changelogs/react-button-refactor.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelogs/react-button-refactor.txt diff --git a/changelogs/react-button-refactor.txt b/changelogs/react-button-refactor.txt new file mode 100644 index 0000000000..559c09a90a --- /dev/null +++ b/changelogs/react-button-refactor.txt @@ -0,0 +1,4 @@ +___DESCRIPTION___ +change +minor +- (React) Refactored ButtonWithIcon to replace ButtonSearch component #81 From 8c95fc008f6ce4c08868b0ddb01e5953e97ee32e Mon Sep 17 00:00:00 2001 From: Minghua Sun Date: Tue, 7 Aug 2018 11:51:00 -0400 Subject: [PATCH 12/12] remove knobs from buttonSearch --- .../buttons/ButtonWithIcon/ButtonWithIcon.stories.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js b/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js index 8208f4c215..6902eb448f 100644 --- a/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js +++ b/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.stories.js @@ -47,16 +47,7 @@ storiesOf('atoms/buttons', module) 'ButtonSearch', withInfo(`
${buttonWithIconReadme}
`)(() => { const props = { - onClick: action('ButtonWithIcon clicked'), - text: text('ButtonWithIcon.text', 'Search'), - type: select('ButtonWithIcon.type', buttonWithIconOptions.type, 'submit'), - classes: array('ButtonWithIcon.classes', []), - icon: select('ButtonWithIcon.icon', Object.keys(icons), 'search'), - iconSize: select('ButtonWithIcon.iconSize', buttonWithIconOptions.size, ''), - iconColor: select('ButtonWithIcon.iconColor', buttonWithIconOptions.color, 'green'), - canExpand: boolean('ButtonWithIcon.canExpand', false), - expanded: boolean('ButtonWithIcon.expanded', true), - capitalized: boolean('ButtonWithIcon.capitalized', false) + onClick: action('ButtonWithIcon clicked') }; // Set the icon prop to the actual element based on knob selection.