@furystack/shades-common-components
Version:
Common UI components for FuryStack Shades
95 lines • 3.58 kB
JavaScript
import { Shade, createComponent } from '@furystack/shades';
import { cssVariableTheme } from '../../services/css-variable-theme.js';
import { LayoutService } from '../../services/layout-service.js';
/**
* Default toggle button for collapsible drawers.
*
* Provides a hamburger menu icon that toggles the drawer open/closed
* via LayoutService. The icon animates between menu and close states.
*
* @example
* ```tsx
* // In AppBar
* <AppBar>
* <DrawerToggleButton position="left" />
* <Typography variant="h3">My App</Typography>
* </AppBar>
*
* // With custom aria-label
* <DrawerToggleButton
* position="left"
* ariaLabel="Toggle navigation menu"
* />
* ```
*/
export const DrawerToggleButton = Shade({
customElementName: 'shade-drawer-toggle-button',
css: {
display: 'inline-block',
fontFamily: cssVariableTheme.typography.fontFamily,
'& button': {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '40px',
height: '40px',
padding: '0',
margin: '0',
border: 'none',
borderRadius: '50%',
background: 'transparent',
cursor: 'pointer',
transition: `background-color ${cssVariableTheme.transitions.duration.normal} ease`,
color: cssVariableTheme.text.primary,
},
'& button:hover': {
backgroundColor: cssVariableTheme.button.hover,
},
'& button:focus-visible': {
outline: `2px solid ${cssVariableTheme.palette.primary.main}`,
outlineOffset: '2px',
},
// Hamburger icon container
'& .hamburger': {
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
width: '20px',
height: '14px',
},
'& .hamburger span': {
display: 'block',
width: '100%',
height: '2px',
backgroundColor: 'currentColor',
borderRadius: '1px',
transition: `transform ${cssVariableTheme.transitions.duration.slow} ease, opacity ${cssVariableTheme.transitions.duration.slow} ease`,
},
// Open state - transform to X
'& .hamburger.open span:nth-child(1)': {
transform: 'translateY(6px) rotate(45deg)',
},
'& .hamburger.open span:nth-child(2)': {
opacity: '0',
},
'& .hamburger.open span:nth-child(3)': {
transform: 'translateY(-6px) rotate(-45deg)',
},
},
render: ({ props, injector, useObservable }) => {
const layoutService = injector.get(LayoutService);
const { position, ariaLabel = 'Toggle drawer' } = props;
// Subscribe to drawer state to update icon
const [drawerState] = useObservable('drawerState', layoutService.drawerState);
const isOpen = drawerState[position]?.open ?? false;
const handleClick = () => {
layoutService.toggleDrawer(position);
};
return (createComponent("button", { type: "button", onclick: handleClick, "aria-label": ariaLabel, "aria-expanded": isOpen ? 'true' : 'false', "data-testid": `drawer-toggle-${position}` },
createComponent("div", { className: `hamburger ${isOpen ? 'open' : ''}` },
createComponent("span", null),
createComponent("span", null),
createComponent("span", null))));
},
});
//# sourceMappingURL=drawer-toggle-button.js.map