Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions apps/www/src/app/examples/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
DataTable,
DatePicker,
Dialog,
Drawer,
EmptyState,
Flex,
IconButton,
Expand All @@ -21,7 +22,6 @@ import {
ScrollArea,
Search,
Select,
Sheet,
Sidebar,
Spinner,
Text,
Expand All @@ -40,7 +40,7 @@ import React, { useState } from 'react';
const Page = () => {
const [dialogOpen, setDialogOpen] = useState(false);
const [nestedDialogOpen, setNestedDialogOpen] = useState(false);
const [dialogSheetOpen, setDialogSheetOpen] = useState(false);
const [dialogDrawerOpen, setDialogDrawerOpen] = useState(false);
const [search1, setSearch1] = useState('');
const [search2, setSearch2] = useState('');
const [search3, setSearch3] = useState('');
Expand Down Expand Up @@ -1536,9 +1536,9 @@ const Page = () => {
</Button>
<Button
variant='outline'
onClick={() => setDialogSheetOpen(true)}
onClick={() => setDialogDrawerOpen(true)}
>
Open Sheet
Open Drawer
</Button>
<Menu>
<Menu.Trigger render={<Button variant='outline' />}>
Expand Down Expand Up @@ -1584,10 +1584,14 @@ const Page = () => {
</Dialog.Content>
</Dialog>

<Sheet open={dialogSheetOpen} onOpenChange={setDialogSheetOpen}>
<Sheet.Content side='right' close>
<Sheet.Title>Sheet Title</Sheet.Title>
<Text>This is the sheet content. </Text>
<Drawer
open={dialogDrawerOpen}
onOpenChange={setDialogDrawerOpen}
side='right'
>
<Drawer.Content side='right'>
<Drawer.Title>Drawer Title</Drawer.Title>
<Text>This is the drawer content. </Text>
<Flex direction='column' gap={4} style={{ marginTop: '16px' }}>
<Text size='small'>Team Members:</Text>
<AvatarGroup>
Expand Down Expand Up @@ -1708,8 +1712,8 @@ const Page = () => {
value={inputValue}
onChange={e => setInputValue(e.target.value)}
/>
</Sheet.Content>
</Sheet>
</Drawer.Content>
</Drawer>

<Dialog open={nestedDialogOpen} onOpenChange={setNestedDialogOpen}>
<Dialog.Content width='500px'>
Expand Down
49 changes: 49 additions & 0 deletions apps/www/src/components/playground/drawer-examples.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use client';

import { Button, Drawer, Flex } from '@raystack/apsara';
import PlaygroundLayout from './playground-layout';

export function DrawerExamples() {
return (
<PlaygroundLayout title='Drawer'>
<Flex gap='medium' wrap='wrap'>
<Drawer side='top'>
<Drawer.Trigger asChild>
<Button>Top Drawer</Button>
</Drawer.Trigger>
<Drawer.Content side='top'>
<Drawer.Title>Top Drawer</Drawer.Title>
<Drawer.Description>Slides in from the Top</Drawer.Description>
</Drawer.Content>
</Drawer>
<Drawer side='right'>
<Drawer.Trigger asChild>
<Button>Right Drawer</Button>
</Drawer.Trigger>
<Drawer.Content side='right'>
<Drawer.Title>Right Drawer</Drawer.Title>
<Drawer.Description>Slides in from the Right</Drawer.Description>
</Drawer.Content>
</Drawer>
<Drawer side='left'>
<Drawer.Trigger asChild>
<Button>Left Drawer</Button>
</Drawer.Trigger>
<Drawer.Content side='left'>
<Drawer.Title>Left Drawer</Drawer.Title>
<Drawer.Description>Slides in from the Left</Drawer.Description>
</Drawer.Content>
</Drawer>
<Drawer side='bottom'>
<Drawer.Trigger asChild>
<Button>Bottom Drawer</Button>
</Drawer.Trigger>
<Drawer.Content side='bottom'>
<Drawer.Title>Bottom Drawer</Drawer.Title>
<Drawer.Description>Slides in from the Bottom</Drawer.Description>
</Drawer.Content>
</Drawer>
</Flex>
</PlaygroundLayout>
);
}
2 changes: 1 addition & 1 deletion apps/www/src/components/playground/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export * from './command-examples';
export * from './container-examples';
export * from './data-table-examples';
export * from './dialog-examples';
export * from './drawer-examples';
export * from './empty-state-examples';
export * from './filter-chip-examples';
export * from './flex-examples';
Expand All @@ -31,7 +32,6 @@ export * from './radio-examples';
export * from './search-examples';
export * from './select-examples';
export * from './separator-examples';
export * from './sheet-examples';
export * from './sidebar-examples';
export * from './skeleton-examples';
export * from './slider-examples';
Expand Down
49 changes: 0 additions & 49 deletions apps/www/src/components/playground/sheet-examples.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion apps/www/src/content/docs/(overview)/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Apsara provides over 50 components organized by function:
| **Navigation** | Navbar, Sidebar, Breadcrumb, Tabs, Link |
| **Data Display** | DataTable, Table, List, Avatar, Badge, Chip, Indicator |
| **Forms** | Button, InputField, TextArea, Select, Combobox, Checkbox, Radio, Switch, Slider, ColorPicker, Calendar |
| **Feedback** | Dialog, Sheet, Popover, Tooltip, Toast, Callout, EmptyState, Skeleton, Spinner |
| **Feedback** | Dialog, Drawer, Popover, Tooltip, Toast, Callout, EmptyState, Skeleton, Spinner |
| **Utilities** | Command, Search, CopyButton, CodeBlock, ScrollArea |

## Theming
Expand Down
109 changes: 109 additions & 0 deletions apps/www/src/content/docs/components/drawer/demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
'use client';

import { getPropsString } from '@/lib/utils';

export const getCode = (props: Record<string, unknown>) => {
return `
<Drawer${getPropsString(props)}>
<Drawer.Trigger>
<Button>Drawer</Button>
</Drawer.Trigger>
<Drawer.Content${getPropsString(props)}>
<Drawer.Header>
<Drawer.Title>Drawer</Drawer.Title>
<Drawer.Description>A simple drawer</Drawer.Description>
</Drawer.Header>
<Drawer.Body>Content goes here</Drawer.Body>
</Drawer.Content>
</Drawer>`;
};

export const playground = {
type: 'playground',
controls: {
side: {
type: 'select',
options: ['top', 'right', 'bottom', 'left'],
defaultValue: 'right'
},
showCloseButton: {
type: 'checkbox',
defaultValue: true
}
},
getCode
};

export const basicDemo = {
type: 'code',
code: `
<Drawer side="right">
<Drawer.Trigger>
<Button>Open Drawer</Button>
</Drawer.Trigger>
<Drawer.Content>
<Drawer.Header>
<Drawer.Title>Drawer Title</Drawer.Title>
<Drawer.Description>Drawer description goes here</Drawer.Description>
</Drawer.Header>
<Drawer.Body>
<span>Main content of the drawer</span>
</Drawer.Body>
</Drawer.Content>
</Drawer>`
};

export const positionDemo = {
type: 'code',
code: `
<Flex gap="medium">
<Drawer side="top">
<Drawer.Trigger>
<Button>Top Drawer</Button>
</Drawer.Trigger>
<Drawer.Content side="top">
<Drawer.Header>
<Drawer.Title>Top Drawer</Drawer.Title>
<Drawer.Description>Slides in from the Top</Drawer.Description>
</Drawer.Header>
<Drawer.Body>Content here</Drawer.Body>
</Drawer.Content>
</Drawer>
<Drawer side="right">
<Drawer.Trigger>
<Button>Right Drawer</Button>
</Drawer.Trigger>
<Drawer.Content side="right">
<Drawer.Header>
<Drawer.Title>Right Drawer</Drawer.Title>
<Drawer.Description>Slides in from the Right</Drawer.Description>
</Drawer.Header>
<Drawer.Body>Content here</Drawer.Body>
</Drawer.Content>
</Drawer>
<Drawer side="left">
<Drawer.Trigger>
<Button>Left Drawer</Button>
</Drawer.Trigger>
<Drawer.Content side="left">
<Drawer.Header>
<Drawer.Title>Left Drawer</Drawer.Title>
<Drawer.Description>Slides in from the Left</Drawer.Description>
</Drawer.Header>
<Drawer.Body>Content here</Drawer.Body>
</Drawer.Content>
</Drawer>
<Drawer side="bottom">
<Drawer.Trigger>
<Button>Bottom Drawer</Button>
</Drawer.Trigger>
<Drawer.Content side="bottom">
<Drawer.Header>
<Drawer.Title>Bottom Drawer</Drawer.Title>
<Drawer.Description>Slides in from the Bottom</Drawer.Description>
</Drawer.Header>
<Drawer.Body>Content here</Drawer.Body>
</Drawer.Content>
</Drawer>
</Flex>`
};
83 changes: 83 additions & 0 deletions apps/www/src/content/docs/components/drawer/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: Drawer
description: A panel that slides in from the edge of the screen with swipe-to-dismiss gestures.
source: packages/raystack/components/drawer
---

import { playground, basicDemo, positionDemo } from "./demo.ts";

<Demo data={playground} />

## Anatomy

Import and assemble the component:

```tsx
import { Drawer } from "@raystack/apsara";

<Drawer side="right">
<Drawer.Content>
<Drawer.Header>
<Drawer.Title />
<Drawer.Description />
</Drawer.Header>
<Drawer.Body />
<Drawer.Footer />
</Drawer.Content>
</Drawer>
```

## API Reference

### Root

Groups all parts of the drawer. The `side` prop determines both the slide direction and the swipe-to-dismiss direction.

<auto-type-table path="./props.ts" name="DrawerProps" />

### Content

Renders the drawer panel that slides in from a screen edge.

<auto-type-table path="./props.ts" name="DrawerContentProps" />

### Header

- `children`: React.ReactNode - Content to render inside the header
- `className`: string - Additional CSS class name

### Title

- Inherits all Base UI Drawer.Title props

### Description

- Inherits all Base UI Drawer.Description props

### Body

- Inherits all HTML div element props

### Footer

- Inherits all HTML div element props

## Examples

### Basic

<Demo data={basicDemo} />

### Positioning

The Drawer can slide in from different sides of the screen. Swipe-to-dismiss is automatically configured based on the `side` prop.

<Demo data={positionDemo} />

## Accessibility

- Uses `role="dialog"` with `aria-modal="true"`
- Focus is trapped within the drawer and restored on close
- Supports dismissal with Escape key and swipe gestures
- Title is announced via `aria-labelledby`

Loading