material-you-react/src/primitive-components/button-components/icon-button/icon-button.tsx

86 lines
2.5 KiB
TypeScript

'use client';
import { Icon } from '../../components';
import { bool, oneOf, string } from 'prop-types';
import { ButtonLayout } from '../button-layout/button-layout';
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
import { IconButtonProps, StateToggleIconType } from './icon-button.types';
/**
* Icon button-layout component
** description
*/
export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
(
{
icon,
className = '',
toggled = false,
disabled = false,
selected = false,
variant = 'default',
centralRipple = false,
...props
},
ref,
) => {
const [toggleIcon, setToggleIcon] = useState<StateToggleIconType>({
state: selected == true ? 'selected' : 'unselected',
icon: toggled ? toggled.unselected ?? 'add_circle' : 'add_circle',
});
const extraClassStyles = `m3-icon-button ${toggleIcon.state} ${variant} ${toggled ? 'toggled' : ''} ${className}`;
const toggle = (extraClassStyles: string, icon: string) => {
setToggleIcon({
state: extraClassStyles,
icon: icon,
});
};
const buttonRef = useRef<HTMLButtonElement>(null);
const callback = event => {
if (toggled) {
if (toggleIcon.state === 'selected') {
toggle('', toggled.unselected ?? 'add_circle');
} else {
toggle('selected', toggled.selected ?? 'add_circle');
}
}
if (props.onClick) {
props.onClick.apply(null, event);
}
};
useImperativeHandle(ref, () => buttonRef.current);
return (
<ButtonLayout
{...props}
centralRipple={centralRipple}
className={extraClassStyles}
disabled={disabled}
onClick={callback}
ref={buttonRef}
>
<Icon
fillIcon={toggleIcon.state === 'selected' ? 1 : 0}
iconSize={28}
svgSize={40}
>
{toggled ? toggleIcon.icon : icon ? icon : undefined}
</Icon>
</ButtonLayout>
);
},
);
IconButton.propTypes = {
icon: string,
selected: bool,
centralRipple: bool,
variant: oneOf(['default', 'filled', 'tonal', 'outlined']),
};