> Leaf UI 0.6.0 · Package: @ifhover/leaf-ui · Source: b30c3d3a8fa9c5e15d0d0522cebfbd33f60c6b06
> Browser documentation: https://ifhover.github.io/leaf-ui/v/0.6.0/components/drawer.html

> For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/v/0.6.0/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/v/0.6.0/llms-full.txt.

# Drawer 抽屉

从页面边缘展开内容，查看详情或完成操作。

## 基础用法


leftrighttopbottom

basic.tsx

复制代码

```tsx lineNumbers file="../../src/examples/drawer/basic.tsx"
import { Button, Drawer, Flex, Form, FormField, Input, Select, Space } from '@ifhover/leaf-ui';

import { useState } from 'react';

export function DrawerBasic() {
  const [placement, setPlacement] = useState<'left' | 'right' | 'top' | 'bottom'>('right');
  const [open, setOpen] = useState(false);
  return (
    <Space direction="vertical" align="stretch">
      <Flex gap="md" align="center" wrap justify="center">
        {(['left', 'right', 'top', 'bottom'] as const).map((side) => (
          <Button
            key={side}
            variant="outline"
            onClick={() => {
              setPlacement(side);
              setOpen(true);
            }}
          >
            {side}
          </Button>
        ))}
      </Flex>
      <Drawer
        open={open}
        placement={placement}
        title="项目设置"
        onClose={() => setOpen(false)}
        footer={
          <>
            <Button variant="outline" onClick={() => setOpen(false)}>
              取消
            </Button>
            <Button type="submit" form="drawer-project">
              保存
            </Button>
          </>
        }
      >
        <Form
          id="drawer-project"
          onSubmit={(event) => {
            event.preventDefault();
            setOpen(false);
          }}
        >
          <FormField label="项目名称" required>
            <Input name="name" defaultValue="Leaf Garden" />
          </FormField>
          <FormField label="项目类型">
            <Select
              name="type"
              defaultValue="design"
              options={[
                { value: 'design', label: '设计项目' },
                { value: 'development', label: '开发项目' },
              ]}
            />
          </FormField>
        </Form>
      </Drawer>
    </Space>
  );
}
```

展开代码

## 调整宽度与嵌套推移


可调整宽度的工作区

capabilities.tsx

复制代码

```tsx lineNumbers file="../../src/examples/drawer/capabilities.tsx"
import { Button, Drawer, Input, Space } from '@ifhover/leaf-ui';

import { useState } from 'react';

export function Capabilities() {
  const [open, setOpen] = useState(false),
    [child, setChild] = useState(false);
  return (
    <>
      <Button onClick={() => setOpen(true)}>
        {'可调整宽度的工作区'}
      </Button>
      <Drawer
        title={'工作区'}
        open={open}
        onClose={() => setOpen(false)}
        resizable
        minSize={260}
        maxSize={640}
      >
        <Space direction="vertical">
          <Input aria-label="Project" />
          <Button onClick={() => setChild(true)}>{'查看详情'}</Button>
        </Space>
        <Drawer
          open={child}
          onClose={() => setChild(false)}
          title={'详情'}
          width={300}
          push={120}
        >
          Details
        </Drawer>
      </Drawer>
    </>
  );
}
```

展开代码

## 通知偏好

标题、内容与底部操作分区，适合较长的设置流程。


通知偏好

sections.tsx

复制代码

```tsx lineNumbers file="../../src/examples/drawer/sections.tsx"
import { Alert, Button, Drawer, RadioGroup, Space } from '@ifhover/leaf-ui';

import { Bell } from 'lucide-react';

import { useState } from 'react';

export function DrawerSections() {
  
  const [open, setOpen] = useState(false);
  const [frequency, setFrequency] = useState('weekly');
  return (
    <>
      <Button variant="outline" startIcon={<Bell />} onClick={() => setOpen(true)}>
        {'通知偏好'}
      </Button>
      <Drawer
        open={open}
        width={440}
        title={'通知偏好'}
        description={'选择适合你的更新频率。'}
        icon={<Bell />}
        onClose={() => setOpen(false)}
        footer={
          <>
            <Button variant="outline" onClick={() => setOpen(false)}>
              {'取消'}
            </Button>
            <Button onClick={() => setOpen(false)}>{'保存'}</Button>
          </>
        }
      >
        <Space direction="vertical" align="stretch" size={20}>
          <RadioGroup
            variant="list"
            label={'活动摘要'}
            value={frequency}
            onChange={(event) => setFrequency(event.target.value)}
            options={[
              {
                value: 'daily',
                label: '每日',
                description: '每天汇总团队动态',
              },
              {
                value: 'weekly',
                label: '每周',
                description: '每周一接收一份摘要',
              },
              {
                value: 'off',
                label: '关闭摘要',
                description: '仅接收重要提醒',
              },
            ]}
          />
          <Alert
            type="info"
            title={'重要提醒始终发送'}
            description={'安全事件和需要你处理的事项不会被关闭。'}
          />
        </Space>
      </Drawer>
    </>
  );
}
```

展开代码

## Drawer API

| 属性               | 类型                                                                         | 默认值       | 说明                                |
| ---------------- | -------------------------------------------------------------------------- | --------- | --------------------------------- |
| `initialFocus`   | `RefObject<HTMLElement \| null> \| (() => HTMLElement \| null)`            | —         | 指定打开后的初始焦点。                       |
| `returnFocus`    | `boolean \| RefObject<HTMLElement \| null> \| (() => HTMLElement \| null)` | —         | 关闭后返回原焦点；也可指定目标或设为 false。         |
| `open`           | `boolean`                                                                  | 必填        | 必需。是否展开                           |
| `title`          | `ReactNode`                                                                | —         | 标题                                |
| `description`    | `ReactNode`                                                                | —         | 补充说明。                             |
| `icon`           | `ReactNode`                                                                | —         | 标题左侧的装饰图标。                        |
| `divided`        | `boolean`                                                                  | `true`    | 用浅分隔线划分标题、内容和底部操作区。               |
| `footer`         | `ReactNode`                                                                | —         | 底部内容                              |
| `extra`          | `ReactNode`                                                                | —         | 标题旁的操作内容                          |
| `placement`      | `'left' \| 'right' \| 'top' \| 'bottom'`                                   | `'right'` | 展开方向                              |
| `width`          | `number \| string`                                                         | `380`     | 左右抽屉宽度                            |
| `height`         | `number \| string`                                                         | `300`     | 上下抽屉高度                            |
| `closable`       | `boolean`                                                                  | `true`    | 关闭按钮 / 点击遮罩 / Escape 关闭           |
| `maskClosable`   | `boolean`                                                                  | `true`    | 关闭按钮 / 点击遮罩 / Escape 关闭           |
| `keyboard`       | `boolean`                                                                  | `true`    | 关闭按钮 / 点击遮罩 / Escape 关闭           |
| `onClose`        | `() => void`                                                               | —         | 请求关闭，由应用更新 open                   |
| `afterClose`     | `() => void`                                                               | —         | 关闭过渡结束后触发                         |
| `forceRender`    | `boolean`                                                                  | `false`   | 打开前也挂载内容，关闭时保持隐藏。                 |
| `destroyOnClose` | `boolean`                                                                  | `false`   | 关闭过渡完成后卸载内容；默认保留。                 |
| `preserve`       | `boolean`                                                                  | —         | 显式控制关闭后是否保留内容，优先于 destroyOnClose。 |
| `container`      | `Element \| DocumentFragment \| (() => Element \| DocumentFragment)`       | —         | 自定义挂载或滚动容器。                       |
| `push`           | `boolean \| number`                                                        | `false`   | 打开嵌套抽屉时推动父弹层，可指定距离。               |
| `resizable`      | `boolean`                                                                  | `false`   | 允许拖动和使用方向键调整大小。                   |
| `minSize`        | `number`                                                                   | `240`     | 最小尺寸，单位为像素。                       |
| `maxSize`        | `number`                                                                   | `900`     | 最大尺寸，单位为像素。                       |
| `onResize`       | `(size: number) => void`                                                   | —         | 大小改变时调用。                          |

## 类型

定义组件属性或组装列表时可导入相关类型。

```ts
import type { DrawerProps } from '@ifhover/leaf-ui';
```

## 使用说明

通过 footer 放置取消、提交等操作；表单提交按钮可使用 form 属性关联抽屉内的表单。标题为空时请使用 aria-label 提供名称。支持嵌套弹窗和抽屉，关闭后焦点会回到打开位置。

## 外观与丰富内容

`description` 与 `icon` 用于说明当前任务。默认标题和底部操作有浅分隔线，底部使用淡灰辅助面；`divided={false}` 使用留白分区。
