diff --git a/src/components/Backdrop/Backdrop.tsx b/src/components/Backdrop/Backdrop.tsx index 36b3cd5..bd83f1d 100644 --- a/src/components/Backdrop/Backdrop.tsx +++ b/src/components/Backdrop/Backdrop.tsx @@ -21,9 +21,17 @@ type Props = { * Default: true */ removeScroll?: boolean; + + className?: string; }; -export function Backdrop({ open, onClose, style, removeScroll = true }: Props) { +export function Backdrop({ + open, + onClose, + style, + className = "", + removeScroll = true, +}: Props) { const attr = attributes({ "aria-expanded": open }); useEffect(() => { @@ -33,6 +41,11 @@ export function Backdrop({ open, onClose, style, removeScroll = true }: Props) { }, [open, removeScroll]); return ( -
+
); } diff --git a/src/components/Sheets/Sheets.tsx b/src/components/Sheets/Sheets.tsx new file mode 100644 index 0000000..f927eef --- /dev/null +++ b/src/components/Sheets/Sheets.tsx @@ -0,0 +1,24 @@ +import { ReactElement } from "react"; +import { Backdrop } from "../Backdrop/Backdrop"; +import "./sheets.css"; +import { attributes } from "../../utils/attributes"; + +type Props = { + open: boolean; + onClose: () => void; + children: ReactElement; +}; + +export function Sheets({ open, onClose, children }: Props) { + const attr = attributes({ "aria-expanded": open }); + + return ( +
+ + +
+ {children} +
+
+ ); +} diff --git a/src/components/Sheets/sheets.css b/src/components/Sheets/sheets.css new file mode 100644 index 0000000..49bc2ea --- /dev/null +++ b/src/components/Sheets/sheets.css @@ -0,0 +1,48 @@ +.sheets { + position: fixed; + transition: transform 0.25s; + background-color: var(--codex-background-secondary); + z-index: 2; + justify-content: space-between; +} + +.sheets-container { + position: relative; +} + +.sheets-backdrop { + z-index: 2; +} + +@media (min-width: 1000px) { + .sheets { + width: 300px; + height: 100%; + bottom: 0; + top: 0; + transform: translatex(300px); + right: 0; + } + + .sheets[aria-expanded] { + transform: translatex(0); + z-index: 10; + } +} + +@media (max-width: 999px) { + .sheets { + width: 100%; + height: auto; + bottom: 0; + top: auto; + transform: translatey(1000px); + left: 0; + padding-bottom: 1.5rem; + } + + .sheets[aria-expanded] { + transform: translatey(0); + z-index: 10; + } +} diff --git a/src/index.ts b/src/index.ts index 1800eea..95742f6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,4 +32,5 @@ export { NetworkIndicator } from "./components/NetworkIndicator/NetworkIndicator export { Tooltip } from "./components/Tooltip/Tooltip"; export { Collapse } from "./components/Collapse/Collapse"; export { Placeholder } from "./components/Placeholder/Placeholder"; +export { Sheets } from "./components/Sheets/Sheets"; export { Tabs } from "./components/Tabs/Tabs"; diff --git a/stories/Sheets.stories.tsx b/stories/Sheets.stories.tsx new file mode 100644 index 0000000..d79d1f1 --- /dev/null +++ b/stories/Sheets.stories.tsx @@ -0,0 +1,53 @@ +import type { Meta } from "@storybook/react"; +import { useState } from "react"; +import { Sheets } from "../src/components/Sheets/Sheets"; +import { fn } from "@storybook/test"; + +const meta = { + title: "Overlays/Sheets", + component: Sheets, + parameters: { + layout: "centered", + inlineStories: false, + }, + tags: ["autodocs"], + argTypes: {}, + args: { + onClose: fn(), + }, +} satisfies Meta; + +export default meta; + +const DefaultTemplate = (props: { onClose: () => void }) => { + const [open, setOpen] = useState(false); + + const onClick = () => setOpen(true); + + const onClose = () => { + props.onClose(); + setOpen(false); + }; + + return ( +
+ + + +
+ Hello world +
+
+
+ ); +}; + +export const Default = DefaultTemplate.bind({});