diff --git a/packages/eui/src/components/accordion/accordion.tsx b/packages/eui/src/components/accordion/accordion.tsx index 7964ba60ce0b..cac3c79a56db 100644 --- a/packages/eui/src/components/accordion/accordion.tsx +++ b/packages/eui/src/components/accordion/accordion.tsx @@ -6,14 +6,15 @@ * Side Public License, v 1. */ -import React, { Component, HTMLAttributes, ReactNode } from 'react'; +import React, { + FunctionComponent, + HTMLAttributes, + ReactNode, + useState, +} from 'react'; import classNames from 'classnames'; -import { - htmlIdGenerator, - withEuiTheme, - WithEuiThemeProps, -} from '../../services'; +import { useEuiMemoizedStyles, useGeneratedHtmlId } from '../../services'; import { CommonProps } from '../common'; import { EuiLoadingSpinner } from '../loading'; import type { EuiButtonIconProps } from '../button'; @@ -114,133 +115,93 @@ export type EuiAccordionProps = CommonProps & isDisabled?: boolean; }; -type EuiAccordionState = { - isOpen: boolean; -}; - -export class EuiAccordionClass extends Component< - WithEuiThemeProps & EuiAccordionProps, - EuiAccordionState -> { - static defaultProps = { - initialIsOpen: false, - borders: 'none' as const, - paddingSize: 'none' as const, - arrowDisplay: 'left' as const, - isLoading: false, - isDisabled: false, - isLoadingMessage: false, - element: 'div' as const, - buttonElement: 'button' as const, - role: 'group' as const, - }; - - state = { - isOpen: this.props.forceState - ? this.props.forceState === 'open' - : this.props.initialIsOpen!, - }; - - get isOpen() { - return this.props.forceState - ? this.props.forceState === 'open' - : this.state.isOpen; - } - - onToggle = () => { - const { forceState } = this.props; +export const EuiAccordion: FunctionComponent = ({ + children, + className, + id, + role = 'group', + element: Element = 'div', + buttonElement = 'button', + buttonProps, + buttonClassName, + buttonContentClassName, + buttonContent, + arrowDisplay = 'left', + arrowProps, + extraAction, + paddingSize = 'none', + borders = 'none', + initialIsOpen = false, + forceState, + isLoading = false, + isLoadingMessage = false, + isDisabled = false, + onToggle, + ...rest +}) => { + const [isOpenState, setIsOpenState] = useState( + forceState ? forceState === 'open' : initialIsOpen + ); + + const isOpen = forceState ? forceState === 'open' : isOpenState; + + const onAccordionToggle = () => { if (forceState) { - const nextState = !this.isOpen; - this.props.onToggle?.(nextState); + onToggle?.(!isOpen); } else { - this.setState( - (prevState) => ({ - isOpen: !prevState.isOpen, - }), - () => { - this.props.onToggle?.(this.state.isOpen); - } - ); + const nextState = !isOpenState; + setIsOpenState(nextState); + onToggle?.(nextState); } }; - generatedId = htmlIdGenerator()(); - - render() { - const { - children, - className, - id, - role, - element: Element = 'div', - buttonElement, - buttonProps, - buttonClassName, - buttonContentClassName, - buttonContent, - arrowDisplay, - arrowProps, - extraAction, - paddingSize, - borders, - initialIsOpen, - forceState, - isLoading, - isLoadingMessage, - isDisabled, - theme, - ...rest - } = this.props; - - const classes = classNames( - 'euiAccordion', - { 'euiAccordion-isOpen': this.isOpen }, - className - ); - - const styles = euiAccordionStyles(theme); - const cssStyles = [ - styles.euiAccordion, - borders !== 'none' && styles.borders.borders, - borders !== 'none' && styles.borders[borders!], - ]; - - const buttonId = buttonProps?.id ?? this.generatedId; - - return ( - - : extraAction} - /> - - - {children} - - - ); - } -} - -export const EuiAccordion = withEuiTheme(EuiAccordionClass); + const generatedId = useGeneratedHtmlId(); + const buttonId = buttonProps?.id ?? generatedId; + + const classes = classNames( + 'euiAccordion', + { 'euiAccordion-isOpen': isOpen }, + className + ); + + const styles = useEuiMemoizedStyles(euiAccordionStyles); + const cssStyles = [ + styles.euiAccordion, + borders !== 'none' && styles.borders.borders, + borders !== 'none' && styles.borders[borders], + ]; + + return ( + + : extraAction} + /> + + + {children} + + + ); +};