Skip to content

Commit

Permalink
feat(Sheet): add Sheet component
Browse files Browse the repository at this point in the history
  • Loading branch information
arturbien authored May 9, 2024
1 parent 97d2695 commit bcbe48e
Show file tree
Hide file tree
Showing 7 changed files with 680 additions and 1 deletion.
399 changes: 399 additions & 0 deletions packages/frosted-ui/.storybook/stories/components/sheet.stories.tsx

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/frosted-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@
"input-otp": "^1.1.0",
"react-aria-components": "1.1.1",
"tailwindcss": "^3.3.5",
"tslib": "^2.6.2"
"tslib": "^2.6.2",
"vaul": "^0.9.1"
},
"peerDependencies": {
"@types/react": "*",
Expand Down
1 change: 1 addition & 0 deletions packages/frosted-ui/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export * from './hover-card.props';
export * as Accordion from './lab/accordion';
export * as Popover from './popover';
export * from './popover.props';
export * as Sheet from './sheet';
export * from './stacked-horizontal-bar-chart';
export * from './tooltip';
export * from './tooltip.props';
Expand Down
77 changes: 77 additions & 0 deletions packages/frosted-ui/src/components/sheet.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
.fui-SheetOverlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.8);
}

.fui-SheetContent {
--sheet-content-padding: 20px;
--inset-padding: var(--sheet-content-padding);
--sheet-border-color: var(--gray-a3);

position: fixed;
left: 0;
right: 0;
bottom: 0;
max-height: calc(100% - 48px);
z-index: 50;
/* margin-top: 96px; */
display: flex;
flex-direction: column;
height: auto;
border-top-left-radius: 24px;
border-top-right-radius: 24px;
border: 1px solid var(--sheet-border-color);
background-color: var(--color-panel-solid);
}
.fui-SheetContent[vaul-drawer][vaul-drawer-direction='bottom']::after {
border-left: 1px solid var(--sheet-border-color);
border-right: 1px solid var(--sheet-border-color);
left: -1px;
right: -1px;
}
.fui-SheetBody {
padding: var(--inset-padding);
}
.fui-SheetContentHandle {
margin-left: auto;
margin-right: auto;
margin-top: 16px;
margin-bottom: 12px;
height: 5px;
width: 40px;
border-radius: 999px;
background-color: var(--gray-a4);
}

.fui-SheetHeader {
display: grid;
padding: 0 var(--inset-padding) var(--inset-padding) var(--inset-padding);
gap: 12px;
}

.fui-SheetTitle {
font-size: 20px;
font-weight: 600;
color: var(--color-text-primary);
color: blue;
}
.fui-SheetDescription {
color: green;
}

.fui-SheetContentHandle,
.fui-SheetHeader,
.fui-SheetBody {
min-height: 0;
}
.fui-SheetContentHandle,
.fui-SheetHeader {
flex-shrink: 0;
}
.fui-SheetBody {
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
}
183 changes: 183 additions & 0 deletions packages/frosted-ui/src/components/sheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
'use client';

import * as React from 'react';
import { Drawer as DrawerPrimitive } from 'vaul';

import classNames from 'classnames';
import { ExtractPropsForTag } from '../helpers';
import { Theme } from '../theme';
import { Heading } from './heading';
import { Text } from './text';

type SheetRootProps = Omit<
React.ComponentProps<typeof DrawerPrimitive.Root>,
| 'shouldScaleBackground'
| 'direction'
// TODO: add support for snap points
| 'fadeFromIndex'
| 'snapPoints'
| 'activeSnapPoint'
>;

const SheetRoot = ({ ...props }: SheetRootProps) => (
<DrawerPrimitive.Root {...props} />
);
SheetRoot.displayName = 'SheetRoot';

type SheetTriggerElement = React.ElementRef<typeof DrawerPrimitive.Trigger>;
interface SheetTriggerProps
extends Omit<
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Trigger>,
'asChild'
> {}
const SheetTrigger = React.forwardRef<SheetTriggerElement, SheetTriggerProps>(
(props, forwardedRef) => (
<DrawerPrimitive.Trigger {...props} ref={forwardedRef} asChild />
),
);
SheetTrigger.displayName = 'SheetTrigger';

type SheetCloseElement = React.ElementRef<typeof DrawerPrimitive.Close>;
interface SheetCloseProps
extends Omit<
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Close>,
'asChild'
> {}
const SheetClose = React.forwardRef<SheetCloseElement, SheetCloseProps>(
(props, forwardedRef) => (
<DrawerPrimitive.Close {...props} ref={forwardedRef} asChild />
),
);
SheetClose.displayName = 'SheetClose';

const SheetPortal = DrawerPrimitive.Portal;
SheetPortal.displayName = 'SheetPortal';

type SheetOverlayElement = React.ElementRef<typeof DrawerPrimitive.Overlay>;
interface SheetOverlayProps
extends React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay> {}

const SheetOverlay = React.forwardRef<SheetOverlayElement, SheetOverlayProps>(
({ className, ...props }, forwardedRef) => (
<DrawerPrimitive.Overlay
ref={forwardedRef}
className={classNames('fui-SheetOverlay', className)}
{...props}
/>
),
);
SheetOverlay.displayName = 'SheetOverlay';

type SheetContentElement = React.ElementRef<typeof DrawerPrimitive.Content>;
interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content> {}

const SheetContent = React.forwardRef<SheetContentElement, SheetContentProps>(
({ className, children, ...props }, forwardedRef) => (
<SheetPortal>
<Theme asChild>
<SheetOverlay />
</Theme>
<Theme asChild>
<DrawerPrimitive.Content
ref={forwardedRef}
className={classNames('fui-SheetContent', className)}
{...props}
>
<div className="fui-SheetContentHandle" />
{children}
</DrawerPrimitive.Content>
</Theme>
</SheetPortal>
),
);
SheetContent.displayName = 'SheetContent';

type SheetHeaderElement = React.ElementRef<'div'>;
type SheetHeaderProps = React.ComponentPropsWithoutRef<'div'>;
const SheetHeader = React.forwardRef<SheetHeaderElement, SheetHeaderProps>(
({ children, className, ...props }, forwardedRef) => (
<div
className={classNames('fui-SheetHeader', className)}
{...props}
ref={forwardedRef}
>
{children}
</div>
),
);
SheetHeader.displayName = 'SheetHeader';

type SheetBodyElement = React.ElementRef<'div'>;
type SheetBodyProps = React.ComponentPropsWithoutRef<'div'>;
const SheetBody = React.forwardRef<SheetBodyElement, SheetBodyProps>(
({ children, className, ...props }, forwardedRef) => (
<div
className={classNames('fui-SheetBody', className)}
{...props}
ref={forwardedRef}
>
{children}
</div>
),
);
SheetBody.displayName = 'SheetBody';

const SheetFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div className={classNames('fui-SheetFooter', className)} {...props} />
);
SheetFooter.displayName = 'SheetFooter';

type SheetTitleElement = React.ElementRef<typeof Heading>;
type SheetTitleProps = React.ComponentPropsWithoutRef<typeof Heading>;

const SheetTitle = React.forwardRef<SheetTitleElement, SheetTitleProps>(
({ size = '5', weight = 'bold', ...props }, forwardedRef) => {
return (
<DrawerPrimitive.Title asChild>
<Heading weight={weight} size={size} {...props} ref={forwardedRef} />
</DrawerPrimitive.Title>
);
},
);
SheetTitle.displayName = 'SheetTitle';

type SheetDescriptionElement = HTMLParagraphElement;
type SheetDescriptionProps = ExtractPropsForTag<typeof Text, 'p'>;

const SheetDescription = React.forwardRef<
SheetDescriptionElement,
SheetDescriptionProps
>(({ size = '3', weight = 'regular', ...props }, forwardedRef) => {
return (
<DrawerPrimitive.Description asChild>
<Text as="p" size={size} weight={weight} {...props} ref={forwardedRef} />
</DrawerPrimitive.Description>
);
});
SheetDescription.displayName = 'SheetDescription';

export {
SheetBody as Body,
SheetClose as Close,
SheetContent as Content,
SheetDescription as Description,
SheetHeader as Header,
SheetRoot as Root,
SheetTitle as Title,
SheetTrigger as Trigger,
};

export {
SheetBodyProps as BodyProps,
SheetCloseProps as CloseProps,
SheetContentProps as ContentProps,
SheetDescriptionProps as DescriptionProps,
SheetHeaderProps as HeaderProps,
SheetRootProps as RootProps,
SheetTitleProps as TitleProps,
SheetTriggerProps as TriggerProps,
};
1 change: 1 addition & 0 deletions packages/frosted-ui/src/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
@import '../components/data-list.css';
@import '../components/dialog.css';
@import '../components/drawer.css';
@import '../components/sheet.css';
@import '../components/dropdown-menu.css';
@import '../components/em.css';
@import '../components/filter-chip.css';
Expand Down
17 changes: 17 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit bcbe48e

Please sign in to comment.