diff --git a/UNRELEASED.md b/UNRELEASED.md index 594a480d6c4..986073cfccd 100644 --- a/UNRELEASED.md +++ b/UNRELEASED.md @@ -16,4 +16,6 @@ ### Code quality +- Converted `Option` into a functional component ([#2541](https://github.com/Shopify/polaris-react/pull/2541)) + ### Deprecations diff --git a/src/components/OptionList/components/Option/Option.tsx b/src/components/OptionList/components/Option/Option.tsx index a6a5f08370e..ec01e053bca 100644 --- a/src/components/OptionList/components/Option/Option.tsx +++ b/src/components/OptionList/components/Option/Option.tsx @@ -1,5 +1,6 @@ -import React from 'react'; +import React, {useCallback} from 'react'; +import {useToggle} from 'utilities/use-toggle'; import {classNames} from '../../../../utilities/css'; import {IconProps} from '../../../../types'; import {ThumbnailProps} from '../../../Thumbnail'; @@ -24,106 +25,92 @@ export interface OptionProps { onClick(section: number, option: number): void; } -interface State { - focused: boolean; -} - -export class Option extends React.Component { - state: State = { - focused: false, - }; - - render() { - const { - label, - value, - id, - select, - active, - allowMultiple, - disabled, - role, - media, - } = this.props; - const {focused} = this.state; - - const mediaMarkup = media ? ( -
{media}
- ) : null; - - const singleSelectClassName = classNames( - styles.SingleSelectOption, - focused && styles.focused, - disabled && styles.disabled, - select && styles.select, - active && styles.active, - ); - - const multiSelectClassName = classNames( - styles.Label, - active && styles.active, - ); - - const checkBoxRole = role === 'option' ? 'presentation' : undefined; - - const optionMarkup = allowMultiple ? ( - - ) : ( - - ); - - const scrollMarkup = active ? : null; - - return ( -
  • - {scrollMarkup} - {optionMarkup} -
  • - ); - } - - private handleClick = () => { - const {onClick, section, index, disabled} = this.props; - +export function Option({ + label, + value, + id, + select, + active, + allowMultiple, + disabled, + role, + media, + onClick, + section, + index, +}: OptionProps) { + const {value: focused, toggle: toggleFocused} = useToggle(false); + + const handleClick = useCallback(() => { if (disabled) { return; } onClick(section, index); - }; - - private toggleFocus = () => { - this.setState((prevState) => ({focused: !prevState.focused})); - }; + }, [disabled, index, onClick, section]); + + const mediaMarkup = media ? ( +
    {media}
    + ) : null; + + const singleSelectClassName = classNames( + styles.SingleSelectOption, + focused && styles.focused, + disabled && styles.disabled, + select && styles.select, + active && styles.active, + ); + + const multiSelectClassName = classNames( + styles.Label, + active && styles.active, + ); + + const checkBoxRole = role === 'option' ? 'presentation' : undefined; + + const optionMarkup = allowMultiple ? ( + + ) : ( + + ); + + const scrollMarkup = active ? : null; + + return ( +
  • + {scrollMarkup} + {optionMarkup} +
  • + ); }