UNPKG

@intility/bifrost-react

Version:

React library for Intility's design system, Bifrost.

115 lines (114 loc) 4.69 kB
"use client"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import classNames from "classnames"; import { FocusTrap } from "focus-trap-react"; import { forwardRef, useEffect } from "react"; import useBreakpoint from "../../hooks/useBreakpoint.js"; import isInert from "../../utils/isInert.js"; import CloseButton from "../common/CloseButton.internal.js"; const Drawer = /*#__PURE__*/ forwardRef(({ children, className, position = "right", header, footer, isOpen = false, overlay = undefined, disableFocusTrap = false, noPadding = false, onRequestClose, ...props }, ref)=>{ const isLarge = useBreakpoint("large"); // if overlay prop is undefined, an overlay will be displayed (with css) for // screens under 1280px ('large'), unless it's a bottom drawer const overlayEnabled = overlay ?? (position !== "bottom" && !isLarge); const drawerContent = /*#__PURE__*/ _jsxs(_Fragment, { children: [ onRequestClose && /*#__PURE__*/ _jsx(CloseButton, { onClick: onRequestClose }), header && /*#__PURE__*/ _jsx("header", { className: "bf-drawer-header", "data-testid": "bf-drawer-header", children: header }), children ] }); return /*#__PURE__*/ _jsxs(_Fragment, { children: [ /*#__PURE__*/ _jsx(FocusTrap, { active: isOpen && overlayEnabled && !disableFocusTrap, focusTrapOptions: { allowOutsideClick: true, fallbackFocus: ".bf-drawer-focus-trap-fallback", initialFocus: false }, children: /*#__PURE__*/ _jsx("div", { className: classNames("bf-drawer", "bf-scrollbar-small", "bf-drawer-focus-trap-fallback", "bf-container", "bf-open-sans", className, { "bf-drawer-open": isOpen, "bf-drawer-with-footer": footer, "bf-drawer-with-close": onRequestClose, "bf-drawer-bottom": position === "bottom", "bf-drawer-nopadding": noPadding }), "data-testid": "bf-drawer", ref: ref, tabIndex: -1, // inert is an attribute to disable interactivity (like clicks and // focus) and AT (Assistive Technologies, like screen reader). inert: isInert(!isOpen), ...props, children: /*#__PURE__*/ _jsx("div", { children: footer ? /*#__PURE__*/ _jsxs(_Fragment, { children: [ /*#__PURE__*/ _jsx("div", { className: "bf-drawer-content bf-scrollbar-small", children: drawerContent }), /*#__PURE__*/ _jsx("div", { className: "bf-drawer-footer", children: footer }) ] }) : drawerContent }) }) }), overlayEnabled && /*#__PURE__*/ _jsx(Overlay, { onRequestClose: onRequestClose, open: isOpen }) ] }); }); Drawer.displayName = "Drawer"; // INTERNAL Overlay const Overlay = ({ onRequestClose, open })=>{ // close drawer on ESC useEffect(()=>{ if (!open || !onRequestClose) return; const closeDrawerOnEsc = (e)=>{ if (e.key === "Escape") { e.stopPropagation(); onRequestClose(e); } }; document.addEventListener("keydown", closeDrawerOnEsc); return ()=>{ document.removeEventListener("keydown", closeDrawerOnEsc); }; }, [ onRequestClose, open ]); // disable body scrollbar useEffect(()=>{ if (!open) return; document.documentElement.classList.add("bf-drawer-overlay-active"); return ()=>{ document.documentElement.classList.remove("bf-drawer-overlay-active"); }; }, [ open ]); return /*#__PURE__*/ _jsx("div", { className: classNames("bf-drawer-overlay", { "bf-drawer-overlay-open": open }), onClick: (e)=>{ e.stopPropagation(); onRequestClose?.(e); } }); }; export default Drawer;