diff --git a/src/components/Filter/components/Filter/components/Backdrop/backdrop.styles.ts b/src/components/Filter/components/Filter/components/Backdrop/backdrop.styles.ts new file mode 100644 index 00000000..662030be --- /dev/null +++ b/src/components/Filter/components/Filter/components/Backdrop/backdrop.styles.ts @@ -0,0 +1,9 @@ +import styled from "@emotion/styled"; +import { Backdrop } from "@mui/material"; + +export const StyledBackdrop = styled(Backdrop)` + background-color: transparent; + overflow: hidden; + overscroll-behavior: none; + z-index: 1300; +`; diff --git a/src/components/Filter/components/Filter/components/Backdrop/backdrop.tsx b/src/components/Filter/components/Filter/components/Backdrop/backdrop.tsx new file mode 100644 index 00000000..54264260 --- /dev/null +++ b/src/components/Filter/components/Filter/components/Backdrop/backdrop.tsx @@ -0,0 +1,15 @@ +import { Portal } from "@mui/material"; +import { JSX } from "react"; +import { useCloseOnEscape } from "../../hooks/UseCloseOnEscape/hook"; +import { StyledBackdrop } from "./backdrop.styles"; +import { BACKDROP_PROPS } from "./constants"; +import { BackdropProps } from "./types"; + +export const Backdrop = (props: BackdropProps): JSX.Element => { + useCloseOnEscape({ onClose: props.onClick, open: props.open }); + return ( + + + + ); +}; diff --git a/src/components/Filter/components/Filter/components/Backdrop/constants.ts b/src/components/Filter/components/Filter/components/Backdrop/constants.ts new file mode 100644 index 00000000..b588f319 --- /dev/null +++ b/src/components/Filter/components/Filter/components/Backdrop/constants.ts @@ -0,0 +1,5 @@ +import { BackdropProps } from "@mui/material"; + +export const BACKDROP_PROPS: Omit = { + slotProps: { transition: { unmountOnExit: true } }, +}; diff --git a/src/components/Filter/components/Filter/components/Backdrop/types.ts b/src/components/Filter/components/Filter/components/Backdrop/types.ts new file mode 100644 index 00000000..eed58f27 --- /dev/null +++ b/src/components/Filter/components/Filter/components/Backdrop/types.ts @@ -0,0 +1,5 @@ +import { BackdropProps as MBackdropProps } from "@mui/material"; + +export interface BackdropProps extends Omit { + onClick: () => void; +} diff --git a/src/components/Filter/components/Filter/components/DrawerTransition/constants.ts b/src/components/Filter/components/Filter/components/DrawerTransition/constants.ts new file mode 100644 index 00000000..5ac7258c --- /dev/null +++ b/src/components/Filter/components/Filter/components/DrawerTransition/constants.ts @@ -0,0 +1,8 @@ +import { SlideProps } from "@mui/material"; + +export const SIDE_PROPS: Omit = { + direction: "right", + easing: "ease-out", + timeout: { enter: 250, exit: 300 }, + unmountOnExit: true, +}; diff --git a/src/components/Filter/components/Filter/components/DrawerTransition/drawerTransition.tsx b/src/components/Filter/components/Filter/components/DrawerTransition/drawerTransition.tsx index 6d11987d..c4a94079 100644 --- a/src/components/Filter/components/Filter/components/DrawerTransition/drawerTransition.tsx +++ b/src/components/Filter/components/Filter/components/DrawerTransition/drawerTransition.tsx @@ -1,24 +1,26 @@ -import { Slide as MSlide, SlideProps as MSlideProps } from "@mui/material"; -import { JSX, forwardRef } from "react"; +import { Slide } from "@mui/material"; +import { JSX } from "react"; +import { SIDE_PROPS } from "./constants"; +import { DrawerTransitionProps } from "./types"; -export const DrawerTransition = forwardRef( - function DrawerTransition( - { - children, - ...props /* Spread props to allow for Mui SlideProps specific prop overrides. */ - }: MSlideProps, - ref, - ): JSX.Element { - return ( - - {children} - - ); - }, -); +/** + * Slide transition used for the drawer-surface filter popover. + * @param props - Component props (extends MUI SlideProps). + * @param props.children - Transition child. + * @param props.placement - Popper placement; consumed only to keep it off the DOM. + * @param props.ref - Forwarded ref. + * @returns Slide transition element. + */ +export const DrawerTransition = ({ + children, + // eslint-disable-next-line @typescript-eslint/no-unused-vars -- destructured out so it doesn't spread onto the DOM Slide element + placement: _placement, + ref, + ...props +}: DrawerTransitionProps): JSX.Element => { + return ( + + {children} + + ); +}; diff --git a/src/components/Filter/components/Filter/components/DrawerTransition/types.ts b/src/components/Filter/components/Filter/components/DrawerTransition/types.ts new file mode 100644 index 00000000..f32305ec --- /dev/null +++ b/src/components/Filter/components/Filter/components/DrawerTransition/types.ts @@ -0,0 +1,7 @@ +import { PopperPlacementType, SlideProps } from "@mui/material"; +import { Ref } from "react"; + +export interface DrawerTransitionProps extends SlideProps { + placement?: PopperPlacementType; + ref?: Ref; +} diff --git a/src/components/Filter/components/Filter/components/MenuTransition/constants.ts b/src/components/Filter/components/Filter/components/MenuTransition/constants.ts new file mode 100644 index 00000000..b15c233f --- /dev/null +++ b/src/components/Filter/components/Filter/components/MenuTransition/constants.ts @@ -0,0 +1,11 @@ +import { PopperPlacementType } from "@mui/material"; +import { CSSProperties } from "react"; +import { POPPER_PROPS } from "../../../../../../styles/common/mui/popper"; + +export const PLACEMENT_TRANSFORM_ORIGIN: Partial< + Record +> = { + [POPPER_PROPS.PLACEMENT.BOTTOM_START]: "0 0 0", + [POPPER_PROPS.PLACEMENT.RIGHT]: "0 50% 0", + [POPPER_PROPS.PLACEMENT.TOP_START]: "0 100% 0", +}; diff --git a/src/components/Filter/components/Filter/components/MenuTransition/menuTransition.tsx b/src/components/Filter/components/Filter/components/MenuTransition/menuTransition.tsx new file mode 100644 index 00000000..3acacadc --- /dev/null +++ b/src/components/Filter/components/Filter/components/MenuTransition/menuTransition.tsx @@ -0,0 +1,31 @@ +import { Grow } from "@mui/material"; +import { JSX } from "react"; +import { POPPER_PROPS } from "../../../../../../styles/common/mui/popper"; +import { PLACEMENT_TRANSFORM_ORIGIN } from "./constants"; +import { MenuTransitionProps } from "./types"; + +/** + * Grow transition with a placement-driven transform origin. + * @param props - Component props. + * @param props.placement - Popper placement, drives the transform origin. + * @param props.ref - Forwarded ref. + * @param props.style - Style merged with the placement-derived transform origin. + * @returns Grow transition element. + */ +export const MenuTransition = ({ + placement = POPPER_PROPS.PLACEMENT.BOTTOM_START, + ref, + style, + ...props +}: MenuTransitionProps): JSX.Element => { + return ( + + ); +}; diff --git a/src/components/Filter/components/Filter/components/MenuTransition/types.ts b/src/components/Filter/components/Filter/components/MenuTransition/types.ts new file mode 100644 index 00000000..22ab7148 --- /dev/null +++ b/src/components/Filter/components/Filter/components/MenuTransition/types.ts @@ -0,0 +1,7 @@ +import { GrowProps, PopperPlacementType } from "@mui/material"; +import { Ref } from "react"; + +export interface MenuTransitionProps extends GrowProps { + placement?: PopperPlacementType; + ref?: Ref; +} diff --git a/src/components/Filter/components/Filter/components/Popper/constants.ts b/src/components/Filter/components/Filter/components/Popper/constants.ts new file mode 100644 index 00000000..eeb30eb0 --- /dev/null +++ b/src/components/Filter/components/Filter/components/Popper/constants.ts @@ -0,0 +1,22 @@ +import { PopperProps } from "@mui/material"; +import { POPPER_PROPS as MUI_POPPER_PROPS } from "../../../../../../styles/common/mui/popper"; + +export const POPPER_PROPS: Omit = { + placement: MUI_POPPER_PROPS.PLACEMENT.BOTTOM_START, + popperOptions: { + modifiers: [ + { + name: "flip", + options: { + fallbackPlacements: [ + MUI_POPPER_PROPS.PLACEMENT.TOP_START, + MUI_POPPER_PROPS.PLACEMENT.RIGHT, + ], + }, + }, + { name: "offset", options: { offset: [0, 4] } }, + ], + }, + role: "dialog", + transition: true, +}; diff --git a/src/components/Filter/components/Filter/filter.styles.ts b/src/components/Filter/components/Filter/filter.styles.ts index a503433d..b700a56c 100644 --- a/src/components/Filter/components/Filter/filter.styles.ts +++ b/src/components/Filter/components/Filter/filter.styles.ts @@ -1,26 +1,34 @@ import { css } from "@emotion/react"; import styled from "@emotion/styled"; -import { Popover } from "@mui/material"; +import { Popper } from "@mui/material"; import { PALETTE } from "../../../../styles/common/constants/palette"; import { SURFACE_TYPE } from "../surfaces/types"; -import { FilterProps } from "./filter"; +import { FilterProps } from "./types"; -export const StyledPopover = styled(Popover, { +export const StyledPopper = styled(Popper, { shouldForwardProp: (prop) => prop !== "surfaceType", })>` - .MuiPaper-menu { - margin: 4px 0; + z-index: 1300; + + .MuiPaper-root { + overflow: hidden; + overscroll-behavior: none; } ${({ surfaceType }) => surfaceType === SURFACE_TYPE.DRAWER && css` + inset: 0 auto 0 0 !important; // required to override Popper's default positioning for correct placement within the drawer. + transform: none !important; // required to override Popper's transform for correct positioning within the drawer. + .MuiPaper-root { background-color: ${PALETTE.SMOKE_LIGHT}; + border: none; + border-radius: 0; + box-shadow: none; height: 100%; margin: 0; max-height: 100%; - overflow: visible; // required; allows backdrop button to render outside of drawer container. } `} `; diff --git a/src/components/Filter/components/Filter/filter.tsx b/src/components/Filter/components/Filter/filter.tsx index ffbb5ea1..6faf1398 100644 --- a/src/components/Filter/components/Filter/filter.tsx +++ b/src/components/Filter/components/Filter/filter.tsx @@ -1,17 +1,20 @@ -import { Grow, PopoverPosition, PopoverProps } from "@mui/material"; -import { JSX, MouseEvent, ReactNode, useState } from "react"; +import { Paper } from "@mui/material"; +import { JSX } from "react"; import { isRangeCategoryView } from "../../../../common/categories/views/range/typeGuards"; -import { CategoryView } from "../../../../common/categories/views/types"; -import { TrackFilterOpenedFunction } from "../../../../config/entities"; -import { OnFilterFn } from "../../../../hooks/useCategoryFilter"; +import { PAPER_PROPS } from "../../../../styles/common/mui/paper"; import { TEST_IDS } from "../../../../tests/testIds"; +import { PopperProvider } from "../../../common/Popper/provider/provider"; import { FilterLabel } from "../FilterLabel/filterLabel"; import { FilterMenu } from "../FilterMenu/filterMenu"; import { FilterRange } from "../FilterRange/filterRange"; import { IconButton } from "../surfaces/drawer/components/IconButton/iconButton"; import { SURFACE_TYPE } from "../surfaces/types"; +import { Backdrop } from "./components/Backdrop/backdrop"; import { DrawerTransition } from "./components/DrawerTransition/drawerTransition"; -import { StyledPopover } from "./filter.styles"; +import { MenuTransition } from "./components/MenuTransition/menuTransition"; +import { POPPER_PROPS } from "./components/Popper/constants"; +import { StyledPopper } from "./filter.styles"; +import { FilterProps } from "./types"; /** * Filter component. @@ -19,24 +22,6 @@ import { StyledPopover } from "./filter.styles"; * TODO(cc) tests: add tests for selected values (rending of tags) for select and range categories. */ -const DEFAULT_POSITION: PopoverPosition = { left: 0, top: 0 }; -const DEFAULT_SLOT_PROPS: PopoverProps["slotProps"] = { - paper: { variant: "menu" }, -}; -const DRAWER_SLOT_PROPS: PopoverProps["slotProps"] = { - paper: { elevation: 0 }, -}; - -export interface FilterProps { - categorySection?: string; - categoryView: CategoryView; - closeAncestor?: () => void; - onFilter: OnFilterFn; - surfaceType: SURFACE_TYPE; - tags?: ReactNode; // e.g. filter tags - trackFilterOpened?: TrackFilterOpenedFunction; -} - export const Filter = ({ categorySection, categoryView, @@ -46,97 +31,92 @@ export const Filter = ({ tags, trackFilterOpened, }: FilterProps): JSX.Element => { - const [isOpen, setIsOpen] = useState(false); - const [position, setPosition] = useState(DEFAULT_POSITION); const isDrawer = surfaceType === SURFACE_TYPE.DRAWER; - const anchorPosition = isDrawer ? DEFAULT_POSITION : position; - const slotProps = isDrawer ? DRAWER_SLOT_PROPS : DEFAULT_SLOT_PROPS; - const TransitionComponent = isDrawer ? DrawerTransition : Grow; - const transitionDuration = isOpen ? 250 : 300; - const TransitionDuration = isDrawer ? transitionDuration : undefined; const isRangeView = isRangeCategoryView(categoryView); - - /** - * Closes filter popover. - */ - const onCloseFilter = (): void => { - setIsOpen(false); - }; - - /** - * Closes filter and all open ancestors e.g. filter drawer. - */ - const onCloseFilters = (): void => { - closeAncestor?.(); - onCloseFilter(); - }; - - /** - * Opens filter popover and sets popover position. - * @param event - Mouse event interaction with filter target. - */ - const onOpenFilter = (event: MouseEvent): void => { - // Grab the filter target size and position and calculate the popover position. - const targetDOMRect = event.currentTarget.getBoundingClientRect(); - const popoverLeftPos = targetDOMRect.x; - const popoverTopPos = targetDOMRect.y + targetDOMRect.height - 1; - // Set popover position and open state. - setPosition({ left: popoverLeftPos, top: popoverTopPos }); - setIsOpen(true); - trackFilterOpened?.({ category: categoryView.key }); - }; - return ( - <> - - - {isDrawer && } - {isRangeView ? ( - - ) : ( - - )} - - {tags} - + + {({ anchorEl, onClose, onOpen, open }): JSX.Element => { + const TransitionComponent = isDrawer + ? DrawerTransition + : MenuTransition; + return ( + <> + { + onOpen(e); + trackFilterOpened?.({ category: categoryView.key }); + }} + surfaceType={surfaceType} + /> + { + onClose(); + closeAncestor?.(); + }} + open={open} + /> + + {({ placement, TransitionProps }): JSX.Element => { + return ( + + + {isDrawer && ( + { + onClose(); + closeAncestor?.(); + }} + /> + )} + {isRangeView ? ( + + ) : ( + + )} + + + ); + }} + + {tags} + + ); + }} + ); }; diff --git a/src/components/Filter/components/Filter/hooks/UseCloseOnEscape/hook.ts b/src/components/Filter/components/Filter/hooks/UseCloseOnEscape/hook.ts new file mode 100644 index 00000000..342158ae --- /dev/null +++ b/src/components/Filter/components/Filter/hooks/UseCloseOnEscape/hook.ts @@ -0,0 +1,29 @@ +import { useEffect } from "react"; +import { UseCloseOnEscapeProps } from "./types"; + +/** + * Closes the popper, and any ancestor drawer, when the Escape key is pressed. + * @param props - Hook props. + * @param props.onClose - Function to call when the Escape key is pressed. + * @param props.open - Whether the popper is open. + */ +export const useCloseOnEscape = ({ + onClose, + open, +}: UseCloseOnEscapeProps): void => { + useEffect(() => { + if (!open) return; + + const onKeyDown = (e: KeyboardEvent): void => { + if (e.key === "Escape") { + e.stopPropagation(); + onClose(); + } + }; + + document.addEventListener("keydown", onKeyDown, true); + return (): void => { + document.removeEventListener("keydown", onKeyDown, true); + }; + }, [onClose, open]); +}; diff --git a/src/components/Filter/components/Filter/hooks/UseCloseOnEscape/types.ts b/src/components/Filter/components/Filter/hooks/UseCloseOnEscape/types.ts new file mode 100644 index 00000000..5315bae3 --- /dev/null +++ b/src/components/Filter/components/Filter/hooks/UseCloseOnEscape/types.ts @@ -0,0 +1,4 @@ +export interface UseCloseOnEscapeProps { + onClose: () => void; + open: boolean; +} diff --git a/src/components/Filter/components/Filter/types.ts b/src/components/Filter/components/Filter/types.ts new file mode 100644 index 00000000..26e1c259 --- /dev/null +++ b/src/components/Filter/components/Filter/types.ts @@ -0,0 +1,15 @@ +import { ReactNode } from "react"; +import { CategoryView } from "../../../../common/categories/views/types"; +import { TrackFilterOpenedFunction } from "../../../../config/entities"; +import { OnFilterFn } from "../../../../hooks/useCategoryFilter"; +import { SURFACE_TYPE } from "../surfaces/types"; + +export interface FilterProps { + categorySection?: string; + categoryView: CategoryView; + closeAncestor?: () => void; + onFilter: OnFilterFn; + surfaceType: SURFACE_TYPE; + tags?: ReactNode; // e.g. filter tags + trackFilterOpened?: TrackFilterOpenedFunction; +} diff --git a/src/components/Filter/components/FilterMenu/filterMenu.styles.ts b/src/components/Filter/components/FilterMenu/filterMenu.styles.ts index 1557dd06..2278d9b4 100644 --- a/src/components/Filter/components/FilterMenu/filterMenu.styles.ts +++ b/src/components/Filter/components/FilterMenu/filterMenu.styles.ts @@ -1,6 +1,6 @@ import { css } from "@emotion/react"; import styled from "@emotion/styled"; -import { FilterProps } from "../Filter/filter"; +import { FilterProps } from "../Filter/types"; import { SURFACE_TYPE } from "../surfaces/types"; interface Props { diff --git a/src/components/Filter/components/FilterRange/filterRange.styles.ts b/src/components/Filter/components/FilterRange/filterRange.styles.ts index 2b89d0de..8c78bbdf 100644 --- a/src/components/Filter/components/FilterRange/filterRange.styles.ts +++ b/src/components/Filter/components/FilterRange/filterRange.styles.ts @@ -99,23 +99,21 @@ export const StyledForm = styled("form")>` ${({ surfaceType }) => surfaceType === SURFACE_TYPE.DRAWER && css` - { - padding: 0 16px; - width: 312px; - - .MuiGrid-root { - gap: 16px 0; - grid-template-rows: auto auto; - margin: 16px 0; - - .MuiFormControl-root { - grid-row: unset; - grid-template-rows: unset; - } + padding: 0 16px; + width: 312px; - .MuiDivider-root { - display: none; - } + .MuiGrid-root { + gap: 16px 0; + grid-template-rows: auto auto; + margin: 16px 0; + + .MuiFormControl-root { + grid-row: unset; + grid-template-rows: unset; + } + + .MuiDivider-root { + display: none; } } `} diff --git a/src/components/Filter/components/Filters/stories/filters.stories.tsx b/src/components/Filter/components/Filters/stories/filters.stories.tsx index 8b193118..01fe108f 100644 --- a/src/components/Filter/components/Filters/stories/filters.stories.tsx +++ b/src/components/Filter/components/Filters/stories/filters.stories.tsx @@ -8,11 +8,23 @@ const meta: Meta = { component: Filters, decorators: [ (Story): JSX.Element => ( - - + + + + ), ], + parameters: { + layout: "fullscreen", + }, }; export default meta; diff --git a/src/components/Filter/components/VariableSizeList/VariableSizeList.tsx b/src/components/Filter/components/VariableSizeList/VariableSizeList.tsx index 6b9d2073..b779be5e 100644 --- a/src/components/Filter/components/VariableSizeList/VariableSizeList.tsx +++ b/src/components/Filter/components/VariableSizeList/VariableSizeList.tsx @@ -120,6 +120,7 @@ export const VariableSizeList = ({ onItemsRendered={(): void => listRef.current?.resetAfterIndex(0)} // Facilitates correct positioning of list items when list scrolls. overscanCount={overscanCount} ref={listRef} + style={{ overscrollBehavior: "none" }} width={width} > {renderListItem} diff --git a/src/components/Layout/components/Header/components/Content/components/Actions/components/Authentication/components/AuthenticationMenu/constants.ts b/src/components/Layout/components/Header/components/Content/components/Actions/components/Authentication/components/AuthenticationMenu/constants.ts index f9885ef1..90e2e844 100644 --- a/src/components/Layout/components/Header/components/Content/components/Actions/components/Authentication/components/AuthenticationMenu/constants.ts +++ b/src/components/Layout/components/Header/components/Content/components/Actions/components/Authentication/components/AuthenticationMenu/constants.ts @@ -1,5 +1,5 @@ import { MenuProps } from "@mui/material"; -import { VARIANT } from "../../../../../../../../../../../../styles/common/mui/paper"; +import { PAPER_PROPS } from "../../../../../../../../../../../../styles/common/mui/paper"; import { POPOVER_ORIGIN_HORIZONTAL, POPOVER_ORIGIN_VERTICAL, @@ -11,7 +11,7 @@ export const MENU_PROPS: Partial = { vertical: POPOVER_ORIGIN_VERTICAL.BOTTOM, }, autoFocus: false, - slotProps: { paper: { variant: VARIANT.MENU } }, + slotProps: { paper: { variant: PAPER_PROPS.VARIANT.MENU } }, transformOrigin: { horizontal: POPOVER_ORIGIN_HORIZONTAL.RIGHT, vertical: POPOVER_ORIGIN_VERTICAL.TOP, diff --git a/src/components/Layout/components/Sidebar/components/SidebarDrawer/sidebarDrawer.tsx b/src/components/Layout/components/Sidebar/components/SidebarDrawer/sidebarDrawer.tsx index ac6613ca..28e8d8b5 100644 --- a/src/components/Layout/components/Sidebar/components/SidebarDrawer/sidebarDrawer.tsx +++ b/src/components/Layout/components/Sidebar/components/SidebarDrawer/sidebarDrawer.tsx @@ -33,7 +33,6 @@ export const SidebarDrawer = ({ open={open} slotProps={DRAWER_SLOT_PROPS} TransitionComponent={DrawerTransition} - transitionDuration={open ? 250 : 300} > {children} diff --git a/src/components/common/Popper/provider/context.ts b/src/components/common/Popper/provider/context.ts new file mode 100644 index 00000000..a691e343 --- /dev/null +++ b/src/components/common/Popper/provider/context.ts @@ -0,0 +1,9 @@ +import { createContext } from "react"; +import { PopperContextProps } from "./types"; + +export const PopperContext = createContext({ + anchorEl: null, + onClose: () => {}, + onOpen: () => {}, + open: false, +}); diff --git a/src/components/common/Popper/provider/hook.ts b/src/components/common/Popper/provider/hook.ts new file mode 100644 index 00000000..c9943180 --- /dev/null +++ b/src/components/common/Popper/provider/hook.ts @@ -0,0 +1,11 @@ +import { useContext } from "react"; +import { PopperContext } from "./context"; +import { PopperContextProps } from "./types"; + +/** + * Returns popper context. + * @returns popper context. + */ +export const usePopper = (): PopperContextProps => { + return useContext(PopperContext); +}; diff --git a/src/components/common/Popper/provider/provider.tsx b/src/components/common/Popper/provider/provider.tsx new file mode 100644 index 00000000..5295ed9f --- /dev/null +++ b/src/components/common/Popper/provider/provider.tsx @@ -0,0 +1,24 @@ +import { JSX, MouseEvent, useCallback, useState } from "react"; +import { PopperContext } from "./context"; +import { PopperProviderProps } from "./types"; + +export function PopperProvider({ children }: PopperProviderProps): JSX.Element { + const [anchorEl, setAnchorEl] = useState(null); + + const open = Boolean(anchorEl); + + const onClose = useCallback(() => setAnchorEl(null), []); + + const onOpen = useCallback( + (event: MouseEvent) => setAnchorEl(event.currentTarget), + [], + ); + + return ( + + {typeof children === "function" + ? children({ anchorEl, onClose, onOpen, open }) + : children} + + ); +} diff --git a/src/components/common/Popper/provider/types.ts b/src/components/common/Popper/provider/types.ts new file mode 100644 index 00000000..6d9df5f3 --- /dev/null +++ b/src/components/common/Popper/provider/types.ts @@ -0,0 +1,11 @@ +import { PopperProps } from "@mui/material"; +import { MouseEvent, ReactNode } from "react"; + +export type PopperContextProps = Pick & { + onClose: () => void; + onOpen: (e: MouseEvent) => void; +}; + +export type PopperProviderProps = { + children: ReactNode | ((props: PopperContextProps) => ReactNode); +}; diff --git a/src/styles/common/mui/paper.ts b/src/styles/common/mui/paper.ts index 86f7c29b..3897d8ab 100644 --- a/src/styles/common/mui/paper.ts +++ b/src/styles/common/mui/paper.ts @@ -1,10 +1,18 @@ import { PaperProps } from "@mui/material"; -export const VARIANT: Record = { +type PaperPropsOptions = { + VARIANT: typeof VARIANT; +}; + +const VARIANT = { ELEVATION: "elevation", FOOTER: "footer", MENU: "menu", OUTLINED: "outlined", PANEL: "panel", SEARCH_BAR: "searchbar", +} as const satisfies Record; + +export const PAPER_PROPS: PaperPropsOptions = { + VARIANT, }; diff --git a/src/styles/common/mui/popper.ts b/src/styles/common/mui/popper.ts new file mode 100644 index 00000000..b335d626 --- /dev/null +++ b/src/styles/common/mui/popper.ts @@ -0,0 +1,27 @@ +import { PopperProps } from "@mui/material"; + +type PopperPropsOptions = { + PLACEMENT: typeof PLACEMENT; +}; + +const PLACEMENT = { + AUTO: "auto", + AUTO_END: "auto-end", + AUTO_START: "auto-start", + BOTTOM: "bottom", + BOTTOM_END: "bottom-end", + BOTTOM_START: "bottom-start", + LEFT: "left", + LEFT_END: "left-end", + LEFT_START: "left-start", + RIGHT: "right", + RIGHT_END: "right-end", + RIGHT_START: "right-start", + TOP: "top", + TOP_END: "top-end", + TOP_START: "top-start", +} as const satisfies Record; + +export const POPPER_PROPS: PopperPropsOptions = { + PLACEMENT, +};