Edit file File name : button-group.js Content :import { createContext, memo, useContext, useMemo, isValidElement, Children, cloneElement, } from '@wordpress/element'; import { motion, LayoutGroup } from 'framer-motion'; import { classNames } from '../helpers'; const ButtonGroupContext = createContext( {} ); ButtonGroupContext.displayName = 'ButtonGroupContext'; const useButtonGroupState = () => useContext( ButtonGroupContext ); const nonElementChildrenTypes = [ 'string', 'number' ]; function ButtonGroup( { value, by = 'id', onChange, children } ) { const layoutGroupId = useMemo( () => Math.random().toString( 16 ).substring( 3 ), [] ); const renderChildren = Children.map( children, ( child, index ) => { if ( isValidElement( child ) ) { return cloneElement( child, { index } ); } return child; } ); const handleChange = ( newValue ) => () => { if ( typeof onChange !== 'function' ) { console.error( 'ButtonGroup: onChange prop must be a function' ); return; } onChange( newValue ); }; const contextValue = useMemo( () => ( { onChange: handleChange, selectedValue: value, by, lastItemIndex: Children.count( children ) - 1, } ), [ onChange, value, children ] ); return ( <div className="isolate inline-flex rounded-md shadow-sm border border-solid border-zip-dark-theme-border divide-solid divide-x divide-zip-dark-theme-border"> <LayoutGroup id={ `button-group-${ layoutGroupId }` }> <ButtonGroupContext.Provider value={ contextValue }> { renderChildren } </ButtonGroupContext.Provider> </LayoutGroup> </div> ); } ButtonGroup = memo( ButtonGroup ); ButtonGroup.ButtonItem = ( { children, value, className, index, ...props } ) => { const { onChange, lastItemIndex, selectedValue, by } = // eslint-disable-next-line react-hooks/rules-of-hooks useButtonGroupState(); const isSelected = selectedValue?.[ by ] === value?.[ by ]; const renderChildren = Children.map( children, ( child ) => { if ( nonElementChildrenTypes.includes( typeof child ) ) { return <span className="z-10">{ children }</span>; } if ( isValidElement( child ) ) { const existingClassName = child.props.className; return cloneElement( child, { className: classNames( 'z-10', existingClassName ), } ); } return child; } ); return ( <button type="button" className={ classNames( index === 0 && 'rounded-l-md', index === lastItemIndex && 'rounded-r-md', index !== 0 && '-ml-px', 'relative w-auto h-auto flex justify-center items-center bg-zip-dark-theme-bg p-2 text-sm font-normal text-zip-dark-theme-icon-active focus:outline-none focus-visible:outline-none border-0 shadow-sm cursor-pointer active:outline-none z-auto transition-colors ease-out duration-[250ms]', isSelected && 'text-zip-dark-theme-heading bg-zip-dark-theme-bg cursor-default z-[1]', isSelected && index <= lastItemIndex && '!border-transparent', className ) } onClick={ onChange( value ) } { ...props } > { renderChildren } { isSelected && ( <motion.span className="bg-zip-dark-theme-content-background rounded absolute inset-0 z-0" layoutId="active-mode" layoutDependency={ value } transition={ { layout: { duration: 0.25, ease: 'easeOut', }, } } /> ) } </button> ); }; ButtonGroup.ButtonItem = memo( ButtonGroup.ButtonItem ); export default ButtonGroup; Save