@reusable-ui/hamburger-menu-button
Version:
A toggleable hamburger button for showing/hiding menu in Navbar.
90 lines (89 loc) • 3.66 kB
JavaScript
// react:
import {
// react:
default as React, } from 'react';
// cssfn:
import {
// checks if a certain css feature is supported by the running browser:
supportsHasPseudoClass, } from '@cssfn/core'; // writes css in javascript
import {
// style sheets:
dynamicStyleSheet, } from '@cssfn/cssfn-react'; // writes css in react hook
// reusable-ui core:
import {
// react helper hooks:
useEvent, useMergeEvents, useMergeClasses, useUncontrollableActivatable, } from '@reusable-ui/core'; // a set of reusable-ui packages which are responsible for building any component
// reusable-ui components:
import { ToggleButton, } from '@reusable-ui/toggle-button'; // a base component
// internals:
import {
// states:
useHamburgerable, } from './states/hamburgerable.js';
// styles:
export const useHamburgerMenuButtonStyleSheet = dynamicStyleSheet(() => import(/* webpackPrefetch: true */ './styles/styles.js'), {
id: '5sj70x1zsf',
lazyCsr: supportsHasPseudoClass(), // dealing with browsers that don't support the :has() selector
});
const HamburgerMenuButton = (props) => {
// styles:
const styleSheet = useHamburgerMenuButtonStyleSheet();
// states:
const [isActive, , toggleActive] = useUncontrollableActivatable(props);
const hamburgerableState = useHamburgerable(isActive);
// rest props:
const {
// components:
toggleButtonComponent = React.createElement(ToggleButton, null), ...restToggleButtonProps } = props;
// classes:
const stateClasses = useMergeClasses(
// preserves the original `stateClasses` from `toggleButtonComponent`:
toggleButtonComponent.props.stateClasses,
// preserves the original `stateClasses` from `props`:
props.stateClasses,
// states:
hamburgerableState.class);
// handlers:
const handleClickInternal = useEvent((event) => {
// conditions:
if (event.defaultPrevented)
return; // the event was already handled by user => nothing to do
// actions:
toggleActive(); // handle click as toggle [active]
event.preventDefault(); // handled
});
const handleClick = useMergeEvents(
// preserves the original `onClick` from `toggleButtonComponent`:
toggleButtonComponent.props.onClick,
// preserves the original `onClick` from `props`:
props.onClick,
// actions:
handleClickInternal);
// fn props:
const activeFn = (toggleButtonComponent.props.active ?? isActive);
// jsx:
/* <ToggleButton> */
return React.cloneElement(toggleButtonComponent,
// props:
{
// other props:
...restToggleButtonProps,
...toggleButtonComponent.props,
// accessibilities:
label: toggleButtonComponent.props.label ?? props.label ?? 'Toggle navigation',
// classes:
mainClass: toggleButtonComponent.props.mainClass ?? props.mainClass ?? styleSheet.main,
stateClasses,
// states:
active: activeFn,
// handlers:
onClick: handleClick,
},
// children:
toggleButtonComponent.props.children ?? (React.createElement("svg", { viewBox: '0 0 24 24' },
React.createElement("polyline", { points: '3,4 21,4',
// handlers:
onAnimationStart: hamburgerableState.handleAnimationStart, onAnimationEnd: hamburgerableState.handleAnimationEnd }),
React.createElement("polyline", { points: '3,12 21,12' }),
React.createElement("polyline", { points: '3,20 21,20' }))));
};
export { HamburgerMenuButton, HamburgerMenuButton as default, };