Skip to content

Commit

Permalink
feat: improve BottomSheet API and types
Browse files Browse the repository at this point in the history
  • Loading branch information
haideralsh committed Nov 12, 2024
1 parent f63272a commit 3ca4722
Show file tree
Hide file tree
Showing 8 changed files with 387 additions and 189 deletions.
62 changes: 0 additions & 62 deletions src/BottomSheet/BottomSheet.parts.story.tsx

This file was deleted.

141 changes: 44 additions & 97 deletions src/BottomSheet/BottomSheet.parts.tsx
Original file line number Diff line number Diff line change
@@ -1,97 +1,9 @@
import { DialogContentProps, DialogOverlayProps } from "@reach/dialog";
import { AnimatePresence, AnimatePresenceProps } from "framer-motion";
import React from "react";
import { DialogContent as ReachDialogContent, DialogOverlay as ReachDialogOverlay } from "@reach/dialog";
import styled from "styled-components";
import { transparentize } from "polished";
import { motion, AnimatePresence, PanInfo } from "framer-motion";
import { Heading2, Text } from "../Type";

const Overlay = styled(motion(ReachDialogOverlay))(({ theme }) => ({
position: "fixed",
inset: 0,
display: "flex",
alignItems: "flex-end",
justifyContent: "center",
backgroundColor: transparentize(0.5, theme.colors.blackBlue),
}));

const Sheet = styled(motion(ReachDialogContent))(({ theme }) => ({
":focus": {
outline: "none",
},
inset: 0,
backgroundColor: theme.colors.white,
borderTopLeftRadius: theme.radii.large,
borderTopRightRadius: theme.radii.large,
height: "auto",
padding: 0,
"*": {
boxSizing: "border-box",
WebkitTapHighlightColor: "transparent",
},
color: theme.colors.black,
fontSize: theme.fontSizes.medium,
lineHeight: theme.lineHeights.base,
WebkitFontSmoothing: "antialiased",
WebkitTapHighlightColor: "transparent",
MozOsxFontSmoothing: "grayscale",

position: "relative",
overflow: "hidden",
display: "flex",
flexDirection: "column",
background: "white",
width: "100%",
maxHeight: `calc(100dvh - ${theme.space.x7})`,
boxShadow: theme.shadows.large,

[`@media (min-width: ${theme.breakpoints.small})`]: {
maxWidth: `calc(100% - ${theme.space.x8})`,
maxHeight: "85.4dvh", // Golden Ratio
},
}));

const ContentContainer = styled.div((_) => ({
overflowY: "auto",
flex: 1,
WebkitOverflowScrolling: "touch",
scrollbarWidth: "none",

"&::-webkit-scrollbar": {
display: "none",
},
}));

const Footer = styled.div(({ theme }) => ({
position: "sticky",
bottom: 0,
marginLeft: theme.space.x1,
marginRight: theme.space.x1,
padding: theme.space.x2,
background: transparentize(0.4, theme.colors.white),
backdropFilter: "blur(8px)",
borderTop: "1px solid",
borderTopColor: theme.colors.lightGrey,
marginTop: "auto",
}));

const Header = styled.div(({ theme }) => ({
textAlign: "center",
paddingTop: theme.space.x3,
paddingLeft: theme.space.x3,
paddingRight: theme.space.x3,
paddingBottom: theme.space.none,
}));

const Title = styled(Heading2)(({ theme }) => ({
marginBottom: theme.space.x1,
}));

const HelpText = styled(Text)(({ theme }) => ({
color: theme.colors.midGrey,
"&, *": {
fontSize: theme.fontSizes.small,
},
}));
import { HeightProps, LayoutProps, MaxHeightProps, MaxWidthProps, SpaceProps, WidthProps } from "styled-system";
import { Overlay, Sheet, ContentContainer, Footer, Header, Title, HelpText } from "./BottomSheet.styled";
import { BottomSheetProvider, useBottomSheet } from "./BottomSheetProvider";

const overlayVariants = {
hidden: { opacity: 0 },
Expand All @@ -108,11 +20,31 @@ const transition = {
ease: [0.32, 0.72, 0, 1],
};

function Root({ isOpen, onClose, children }) {
return <AnimatePresence>{isOpen && children}</AnimatePresence>;
interface RootProps extends AnimatePresenceProps {
isOpen: boolean;
onClose: () => void;
children: React.ReactNode;
}

function OverlayPart({ closeOnClick, onClose, isOpen, children }) {
function Root({ isOpen, onClose, children, ...props }: RootProps) {
return (
<AnimatePresence {...props}>
{isOpen && (
<BottomSheetProvider isOpen={isOpen} onClose={onClose}>
{children}
</BottomSheetProvider>
)}
</AnimatePresence>
);
}

interface OverlayPartProps extends DialogOverlayProps {
closeOnClick?: boolean;
}

function OverlayPart({ closeOnClick, children, ...props }: OverlayPartProps) {
const { onClose, isOpen } = useBottomSheet();

return (
<Overlay
variants={overlayVariants}
Expand All @@ -122,25 +54,40 @@ function OverlayPart({ closeOnClick, onClose, isOpen, children }) {
transition={transition}
onClick={closeOnClick ? onClose : undefined}
isOpen={isOpen}
{...props}
>
{children}
</Overlay>
);
}

function SheetPart({ children, onClose }) {
interface SheetPartProps
extends DialogContentProps,
WidthProps,
MaxWidthProps,
HeightProps,
MaxHeightProps,
SpaceProps,
LayoutProps {
children: React.ReactNode;
"aria-label": string;
}

function SheetPart({ children, ...props }: SheetPartProps) {
function handleSheetClick(e: React.MouseEvent<HTMLDivElement, MouseEvent>) {
e.stopPropagation();
}

return (
<Sheet
aria-label={props["aria-label"]}
variants={sheetVariants}
initial="hidden"
animate="visible"
exit="hidden"
transition={transition}
onClick={handleSheetClick}
{...props}
>
{children}
</Sheet>
Expand Down
Loading

0 comments on commit 3ca4722

Please sign in to comment.