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 diff --git a/react/src/components/atoms/buttons/ButtonSearch/ButtonSearch.md b/react/src/components/atoms/buttons/ButtonSearch/ButtonSearch.md deleted file mode 100644 index 650e74ff26..0000000000 --- a/react/src/components/atoms/buttons/ButtonSearch/ButtonSearch.md +++ /dev/null @@ -1,18 +0,0 @@ -### Description -A button used for a keyword search. - -### Changes for React -* `classes` array: To improve reusability of this component, classes can now be added to the button by adding them to the new `classes` array. -* `ariaLabel` string: To improve accessablitily of this component, an aria-label can be added if the displayed text is not helpful to assistive technologies. - -### Variables -~~~ -onClick: - type: function / optional -text: - type: string / optional -ariaLabel: - type: string / optional -classes: - type: array (string) / optional -~~~ diff --git a/react/src/components/atoms/buttons/ButtonSearch/ButtonSearch.stories.js b/react/src/components/atoms/buttons/ButtonSearch/ButtonSearch.stories.js deleted file mode 100644 index 60cc725769..0000000000 --- a/react/src/components/atoms/buttons/ButtonSearch/ButtonSearch.stories.js +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; - -import { storiesOf } from '@storybook/react'; -import { withInfo } from '@storybook/addon-info'; -import { text, withKnobs } from '@storybook/addon-knobs/react'; -import { action } from '@storybook/addon-actions'; - -import ButtonSearch from '.'; -import ButtonSearchReadme from './ButtonSearch.md'; - -storiesOf('atoms/buttons', module) - .addDecorator(withKnobs) - .add( - 'ButtonSearch', - withInfo(`
${ButtonSearchReadme}
`)(() => { - const props = { - text: text('ButtonSearch.text', 'Search'), - ariaLabel: text('ButtonSearch.ariaLabel', 'Search'), - onClick: action('ButtonSearch.onClick') - }; - - return(); - }) - ); diff --git a/react/src/components/atoms/buttons/ButtonSearch/index.js b/react/src/components/atoms/buttons/ButtonSearch/index.js deleted file mode 100644 index 899a81d2c7..0000000000 --- a/react/src/components/atoms/buttons/ButtonSearch/index.js +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import SvgSearch from '../../icons/SvgSearch'; - -const ButtonSearch = (buttonSearch) => { - const onButtonClick = Object.prototype.hasOwnProperty.call(buttonSearch, 'onClick'); - return(( - - )); -}; - -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; 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..a32983cf1d 100644 --- a/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.md +++ b/react/src/components/atoms/buttons/ButtonWithIcon/ButtonWithIcon.md @@ -1,2 +1,9 @@ ### 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). +* `classes` array: To improve reusability of this component, classes can now be added to the button by adding them to the new `classes` array. +* `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..6902eb448f 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, ''), iconColor: select('ButtonWithIcon.iconColor', buttonWithIconOptions.color), canExpand: boolean('ButtonWithIcon.canExpand', true), expanded: boolean('ButtonWithIcon.expanded', true), @@ -37,6 +38,21 @@ storiesOf('atoms/buttons', module) // Set the icon prop to the actual element based on knob selection. props.icon = icons[props.icon]; + return( + + ); + }) + ) + .add( + 'ButtonSearch', + withInfo(`
${buttonWithIconReadme}
`)(() => { + const props = { + onClick: action('ButtonWithIcon clicked') + }; + + // 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..d70ff4849a 100644 --- a/react/src/components/atoms/buttons/ButtonWithIcon/index.js +++ b/react/src/components/atoms/buttons/ButtonWithIcon/index.js @@ -21,28 +21,36 @@ class ButtonWithIcon extends React.Component { } } render() { - let classNames = this.props.classes.join(' '); - if (this.props.canExpand) { + const { + classes, canExpand, expanded, capitalized, iconSize, iconColor, icon, type + } = this.props; + let classNames = classes.join(' '); + if (canExpand) { classNames += ' ma__button-icon--expandable'; - classNames += this.props.expanded ? ' ma__button-icon--expanded' : ''; + if (expanded) { + classNames += ' ma__button-icon--expanded'; + } } - if (this.props.capitalized) { + if (capitalized) { classNames += ' ma__button-capitalized'; } - if (this.props.iconSize === 'small') { + if (iconSize === 'small' || icon.type.name === 'SvgChevron') { classNames += ' ma__icon-small'; } - if (this.props.iconColor === 'green') { + if (iconColor === 'green') { classNames += ' ma__icon-green'; } + if (icon.type.name === 'SvgSearch') { + classNames += ' ma__button-search'; + } const buttonProps = { - type: 'submit', + type, className: `ma__button-icon ${classNames}`, onClick: this.handleClick, tabIndex: 0 }; return( - @@ -57,6 +65,8 @@ ButtonWithIcon.propTypes = { setButtonRef: PropTypes.func, // Button text. text: PropTypes.string, + /** HTML