fix(striker-ui): make IconButton change based on state

main
Tsu-ba-me 2 years ago
parent f62342317d
commit 53ae8ecdbd
  1. 121
      striker-ui/components/IconButton/IconButton.tsx
  2. 16
      striker-ui/types/IconButton.d.ts

@ -1,9 +1,16 @@
import { FC } from 'react'; import {
Done as MUIDoneIcon,
Edit as MUIEditIcon,
Visibility as MUIVisibilityIcon,
VisibilityOff as MUIVisibilityOffIcon,
} from '@mui/icons-material';
import { import {
IconButton as MUIIconButton, IconButton as MUIIconButton,
IconButtonProps as MUIIconButtonProps, IconButtonProps as MUIIconButtonProps,
inputClasses as muiInputClasses, inputClasses as muiInputClasses,
styled,
} from '@mui/material'; } from '@mui/material';
import { createElement, FC, ReactNode, useMemo } from 'react';
import { import {
BLACK, BLACK,
@ -13,35 +20,93 @@ import {
TEXT, TEXT,
} from '../../lib/consts/DEFAULT_THEME'; } from '../../lib/consts/DEFAULT_THEME';
export type IconButtonProps = MUIIconButtonProps; type IconButtonProps = IconButtonOptionalProps & MUIIconButtonProps;
const ContainedIconButton = styled(MUIIconButton)({
borderRadius: BORDER_RADIUS,
backgroundColor: GREY,
color: BLACK,
'&:hover': {
backgroundColor: TEXT,
},
[`&.${muiInputClasses.disabled}`]: {
backgroundColor: DISABLED,
},
});
const NormalIconButton = styled(MUIIconButton)({
color: GREY,
});
const MAP_TO_VISIBILITY_ICON: IconButtonMapToStateIcon = {
false: MUIVisibilityIcon,
true: MUIVisibilityOffIcon,
};
const MAP_TO_EDIT_ICON: IconButtonMapToStateIcon = {
false: MUIEditIcon,
true: MUIDoneIcon,
};
const MAP_TO_MAP_PRESET: Record<
IconButtonPresetMapToStateIcon,
IconButtonMapToStateIcon
> = {
edit: MAP_TO_EDIT_ICON,
visibility: MAP_TO_VISIBILITY_ICON,
};
const MAP_TO_VARIANT: Record<IconButtonVariant, CreatableComponent> = {
contained: ContainedIconButton,
normal: NormalIconButton,
};
const IconButton: FC<IconButtonProps> = ({ const IconButton: FC<IconButtonProps> = ({
children, children,
sx, defaultIcon,
...iconButtonRestProps iconProps,
}) => ( mapPreset,
<MUIIconButton mapToIcon: externalMapToIcon,
{...{ state,
...iconButtonRestProps, variant = 'contained',
sx: { ...restIconButtonProps
borderRadius: BORDER_RADIUS, }) => {
backgroundColor: GREY, const mapToIcon = useMemo<IconButtonMapToStateIcon | undefined>(
color: BLACK, () => externalMapToIcon ?? (mapPreset && MAP_TO_MAP_PRESET[mapPreset]),
[externalMapToIcon, mapPreset],
'&:hover': { );
backgroundColor: TEXT,
}, const iconButtonContent = useMemo(() => {
let result: ReactNode;
[`&.${muiInputClasses.disabled}`]: {
backgroundColor: DISABLED, if (mapToIcon) {
}, const iconElementType: CreatableComponent | undefined = state
? mapToIcon[state] ?? defaultIcon
...sx, : defaultIcon;
},
}} if (iconElementType) {
> result = createElement(iconElementType, iconProps);
{children} }
</MUIIconButton> } else {
); result = children;
}
return result;
}, [children, mapToIcon, state, defaultIcon, iconProps]);
const iconButtonElementType = useMemo(
() => MAP_TO_VARIANT[variant],
[variant],
);
return createElement(
iconButtonElementType,
restIconButtonProps,
iconButtonContent,
);
};
export type { IconButtonProps };
export default IconButton; export default IconButton;

@ -0,0 +1,16 @@
type CreatableComponent = Parameters<typeof import('react').createElement>[0];
type IconButtonPresetMapToStateIcon = 'edit' | 'visibility';
type IconButtonMapToStateIcon = Record<string, CreatableComponent>;
type IconButtonVariant = 'contained' | 'normal';
type IconButtonOptionalProps = {
defaultIcon?: CreatableComponent;
iconProps?: import('@mui/material').SvgIconProps;
mapPreset?: IconButtonPresetMapToStateIcon;
mapToIcon?: IconButtonMapToStateIcon;
state?: string;
variant?: IconButtonVariant;
};
Loading…
Cancel
Save