From 81af2455cec89fbcf2a2e778f972e206075fd18c Mon Sep 17 00:00:00 2001 From: Abbey Hart Date: Wed, 8 Jan 2020 14:53:26 -0600 Subject: [PATCH] fix(radio-tile, selectable-tile): deprecate iconDescription and add handleOnChange function (#4966) * fix(radio-tile,tile): refactor radio tile to fn and add onChange to tile * chore(tile): removes default prop for deprecated icon description Co-authored-by: Josh Black --- .../src/components/RadioTile/RadioTile.js | 234 +++++++++--------- .../react/src/components/Tile/Tile-story.js | 12 +- packages/react/src/components/Tile/Tile.js | 39 +-- 3 files changed, 152 insertions(+), 133 deletions(-) diff --git a/packages/react/src/components/RadioTile/RadioTile.js b/packages/react/src/components/RadioTile/RadioTile.js index c336173d23bf..4969aba75587 100644 --- a/packages/react/src/components/RadioTile/RadioTile.js +++ b/packages/react/src/components/RadioTile/RadioTile.js @@ -6,128 +6,138 @@ */ import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useRef } from 'react'; import uid from '../../tools/uniqueId'; import classNames from 'classnames'; import { settings } from 'carbon-components'; import { CheckmarkFilled16 as CheckmarkFilled } from '@carbon/icons-react'; import { keys, matches } from '../../internal/keyboard'; +import deprecate from '../../prop-types/deprecate'; const { prefix } = settings; -export default class RadioTile extends React.Component { - static propTypes = { - /** - * `true` if this tile should be selected. - */ - checked: PropTypes.bool, - - /** - * The CSS class names. - */ - className: PropTypes.string, - - /** - * `true` if the `` should be checked at initialization. - */ - defaultChecked: PropTypes.bool, - - /** - * The ID of the ``. - */ - id: PropTypes.string, - - /** - * The `name` of the ``. - */ - name: PropTypes.string, - - /** - * The description of the tile checkmark icon. - */ - iconDescription: PropTypes.string, - - /** - * The handler of the massaged `change` event on the ``. - */ - onChange: PropTypes.func, - - /** - * The `value` of the ``. - */ - value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, - - /** - * Specify the tab index of the wrapper element - */ - tabIndex: PropTypes.number, - - /** - * `true` to use the light version. - */ - light: PropTypes.bool, - }; - - static defaultProps = { - iconDescription: 'Tile checkmark', - onChange: () => {}, - tabIndex: 0, - light: false, - }; - - uid = this.props.id || uid(); - - handleChange = evt => { - this.props.onChange(this.props.value, this.props.name, evt); - }; - - handleKeyDown = evt => { +function RadioTile({ + children, + className, + // eslint-disable-next-line no-unused-vars + iconDescription, + light, + checked, + name, + value, + id, + onChange, + tabIndex, + ...other +}) { + const { current: inputId } = useRef(id || uid()); + const classes = classNames( + className, + `${prefix}--tile`, + `${prefix}--tile--selectable`, + { + [`${prefix}--tile--is-selected`]: checked, + [`${prefix}--tile--light`]: light, + } + ); + + function handleOnChange(evt) { + onChange(value, name, evt); + } + + function handleOnKeyDown(evt) { if (matches(evt, [keys.Enter, keys.Space])) { evt.preventDefault(); - this.props.onChange(this.props.value, this.props.name, evt); + onChange(value, name, evt); } - }; - - render() { - const { - children, - className, - iconDescription, - light, - ...other - } = this.props; - const classes = classNames( - className, - `${prefix}--tile`, - `${prefix}--tile--selectable`, - { - [`${prefix}--tile--is-selected`]: this.props.checked, - [`${prefix}--tile--light`]: light, - } - ); - - return ( - <> - - - - ); } + + return ( + <> + + + + ); } + +RadioTile.propTypes = { + /** + * `true` if this tile should be selected. + */ + checked: PropTypes.bool, + + /** + * The CSS class names. + */ + className: PropTypes.string, + + /** + * `true` if the `` should be checked at initialization. + */ + defaultChecked: PropTypes.bool, + + /** + * The ID of the ``. + */ + id: PropTypes.string, + + /** + * The `name` of the ``. + */ + name: PropTypes.string, + + /** + * The description of the tile checkmark icon. + */ + iconDescription: deprecate( + PropTypes.string, + 'The `iconDescription` prop for `RadioTile` is no longer needed and has ' + + 'been deprecated. It will be moved in the next major release.' + ), + + /** + * The handler of the massaged `change` event on the ``. + */ + onChange: PropTypes.func, + + /** + * The `value` of the ``. + */ + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + + /** + * Specify the tab index of the wrapper element + */ + tabIndex: PropTypes.number, + + /** + * `true` to use the light version. + */ + light: PropTypes.bool, +}; + +RadioTile.defaultProps = { + onChange: () => {}, + tabIndex: 0, + light: false, +}; + +export default RadioTile; diff --git a/packages/react/src/components/Tile/Tile-story.js b/packages/react/src/components/Tile/Tile-story.js index 9f9c7ebd61b5..6737a4300141 100644 --- a/packages/react/src/components/Tile/Tile-story.js +++ b/packages/react/src/components/Tile/Tile-story.js @@ -138,22 +138,22 @@ storiesOf('Tile', module) } ) .add( - 'Selectable', + 'Radio', () => { const radioProps = props.radio(); return ( - - Selectable Tile + + Radio Tile - Selectable Tile + Radio Tile - Selectable Tile + Radio Tile ); diff --git a/packages/react/src/components/Tile/Tile.js b/packages/react/src/components/Tile/Tile.js index 7d39370de127..a197223bb196 100644 --- a/packages/react/src/components/Tile/Tile.js +++ b/packages/react/src/components/Tile/Tile.js @@ -14,6 +14,7 @@ import { ChevronDown16, } from '@carbon/icons-react'; import { keys, matches } from '../../internal/keyboard'; +import deprecate from '../../prop-types/deprecate'; const { prefix } = settings; @@ -218,7 +219,11 @@ export class SelectableTile extends Component { /** * The description of the checkmark icon. */ - iconDescription: PropTypes.string, + iconDescription: deprecate( + PropTypes.string, + 'The `iconDescription` prop for `RadioTile` is no longer needed and has ' + + 'been deprecated. It will be moved in the next major release.' + ), /** * Specify the tab index of the wrapper element @@ -235,7 +240,6 @@ export class SelectableTile extends Component { static defaultProps = { value: 'value', title: 'title', - iconDescription: 'Tile checkmark', selected: false, handleClick: () => {}, handleKeyDown: () => {}, @@ -244,6 +248,16 @@ export class SelectableTile extends Component { light: false, }; + static getDerivedStateFromProps({ selected }, state) { + const { prevSelected } = state; + return prevSelected === selected + ? null + : { + selected, + prevSelected: selected, + }; + } + handleClick = evt => { evt.preventDefault(); evt.persist(); @@ -279,15 +293,10 @@ export class SelectableTile extends Component { } }; - static getDerivedStateFromProps({ selected }, state) { - const { prevSelected } = state; - return prevSelected === selected - ? null - : { - selected, - prevSelected: selected, - }; - } + handleOnChange = event => { + this.setState({ selected: event.target.checked }); + this.props.onChange(event); + }; render() { const { @@ -297,10 +306,12 @@ export class SelectableTile extends Component { value, name, title, + // eslint-disable-next-line no-unused-vars iconDescription, className, handleClick, // eslint-disable-line handleKeyDown, // eslint-disable-line + // eslint-disable-next-line no-unused-vars onChange, light, ...other @@ -326,7 +337,7 @@ export class SelectableTile extends Component { id={id} className={`${prefix}--tile-input`} value={value} - onChange={onChange} + onChange={this.handleOnChange} type="checkbox" name={name} title={title} @@ -340,9 +351,7 @@ export class SelectableTile extends Component { onClick={this.handleClick} onKeyDown={this.handleKeyDown}> - - {iconDescription && {iconDescription}} - + {children}