跳转到内容

Drawer

从屏幕边缘滑入的面板。用于表单、详情或任务面板。

import { Drawer } from 'asterui'

基础抽屉

从右侧滑入的简单抽屉。

import { Drawer, Button } from 'asterui'
import { useState } from 'react'

function App() {
  const [open, setOpen] = useState(false)
  
  return (
      <Button color="primary" onClick={() => setOpen(true)}>
        Open Drawer
      </Button>
      <Drawer
        open={open}
        onClose={() => setOpen(false)}
        title="Basic Drawer"
      >
        <p>Drawer content goes here.</p>
      </Drawer>
    )
}

export default App

位置

抽屉可以从任何方向滑入。

import { Drawer, Button, Space } from 'asterui'
import { useState } from 'react'

function App() {
  const [placement, setPlacement] = useState<'left' | 'right' | 'top' | 'bottom'>('right')
  const [open, setOpen] = useState(false)
  
  const showDrawer = (p: typeof placement) => {
    setPlacement(p)
    setOpen(true)
  }
  
  return (
      <Space direction="horizontal" size="sm" wrap>
        <Button onClick={() => showDrawer('left')}>Left</Button>
        <Button onClick={() => showDrawer('right')}>Right</Button>
        <Button onClick={() => showDrawer('top')}>Top</Button>
        <Button onClick={() => showDrawer('bottom')}>Bottom</Button>
      </Space>
      <Drawer
        open={open}
        onClose={() => setOpen(false)}
        placement={placement}
        title={`${placement.charAt(0).toUpperCase() + placement.slice(1)} Drawer`}
      >
        <p>This drawer slides in from the {placement}.</p>
      </Drawer>
    )
}

export default App

带页脚

页脚中带操作按钮的抽屉。

import { Drawer, Button, Space } from 'asterui'
import { useState } from 'react'

function App() {
  const [open, setOpen] = useState(false)
  
  return (
      <Button color="primary" onClick={() => setOpen(true)}>
        Open Drawer
      </Button>
      <Drawer
        open={open}
        onClose={() => setOpen(false)}
        title="Edit Profile"
        footer={
          <Space direction="horizontal" size="sm">
            <Button onClick={() => setOpen(false)}>Cancel</Button>
            <Button color="primary" onClick={() => setOpen(false)}>
              Save
            </Button>
          </Space>
        }
      >
        <p>Form content would go here...</p>
      </Drawer>
    )
}

export default App

额外头部内容

在头部带额外操作的抽屉。

import { Drawer, Button, Space } from 'asterui'
import { useState } from 'react'

function App() {
  const [open, setOpen] = useState(false)
  
  return (
      <Button color="primary" onClick={() => setOpen(true)}>
        Open Drawer
      </Button>
      <Drawer
        open={open}
        onClose={() => setOpen(false)}
        title="User Details"
        extra={
          <Space size="xs">
            <Button size="sm" variant="ghost">Edit</Button>
            <Button size="sm" variant="ghost">Delete</Button>
          </Space>
        }
      >
        <p>User information displayed here.</p>
      </Drawer>
    )
}

export default App

预设尺寸

默认(378px)和大(736px)预设尺寸。

import { Drawer, Button, Space } from 'asterui'
import { useState } from 'react'

function App() {
  const [size, setSize] = useState<'default' | 'large'>('default')
  const [open, setOpen] = useState(false)
  
  const showDrawer = (s: typeof size) => {
    setSize(s)
    setOpen(true)
  }
  
  return (
      <Space direction="horizontal" size="sm">
        <Button onClick={() => showDrawer('default')}>Default (378px)</Button>
        <Button onClick={() => showDrawer('large')}>Large (736px)</Button>
      </Space>
      <Drawer
        open={open}
        onClose={() => setOpen(false)}
        title={`${size.charAt(0).toUpperCase() + size.slice(1)} Drawer`}
        size={size}
      >
        <p>This drawer uses the {size} preset size.</p>
      </Drawer>
    )
}

export default App

加载状态

带骨架加载状态的抽屉。

import { Drawer, Button } from 'asterui'
import { useState, useEffect } from 'react'

function App() {
  const [open, setOpen] = useState(false)
  const [loading, setLoading] = useState(true)
  
  useEffect(() => {
    if (open) {
      setLoading(true)
      const timer = setTimeout(() => setLoading(false), 1500)
      return () => clearTimeout(timer)
    }
  }, [open])
  
  return (
      <Button color="primary" onClick={() => setOpen(true)}>
        Load Data
      </Button>
      <Drawer
        open={open}
        onClose={() => setOpen(false)}
        title="User Profile"
        loading={loading}
      >
        <div className="space-y-4">
          <p><strong>Name:</strong> John Doe</p>
          <p><strong>Email:</strong> john@example.com</p>
          <p><strong>Role:</strong> Administrator</p>
        </div>
      </Drawer>
    )
}

export default App

嵌套抽屉

带推动行为的多个抽屉。

import { Drawer, Button } from 'asterui'
import { useState } from 'react'

function App() {
  const [open1, setOpen1] = useState(false)
  const [open2, setOpen2] = useState(false)
  
  return (
      <Button color="primary" onClick={() => setOpen1(true)}>
        Open First Drawer
      </Button>
      <Drawer
        open={open1}
        onClose={() => setOpen1(false)}
        title="First Drawer"
        push={{ distance: 180 }}
      >
        <p>This is the first drawer.</p>
        <Button color="secondary" onClick={() => setOpen2(true)}>
          Open Second Drawer
        </Button>
        <Drawer
          open={open2}
          onClose={() => setOpen2(false)}
          title="Second Drawer"
          width={400}
        >
          <p>This is a nested drawer.</p>
          <p>Notice how the first drawer pushed back.</p>
        </Drawer>
      </Drawer>
    )
}

export default App

无遮罩

没有背景遮罩的抽屉。

import { Drawer, Button } from 'asterui'
import { useState } from 'react'

function App() {
  const [open, setOpen] = useState(false)
  
  return (
      <Button color="primary" onClick={() => setOpen(true)}>
        Open Drawer
      </Button>
      <Drawer
        open={open}
        onClose={() => setOpen(false)}
        title="No Mask Drawer"
        mask={false}
      >
        <p>This drawer has no backdrop overlay.</p>
        <p>You can still interact with the page behind it.</p>
      </Drawer>
    )
}

export default App
属性描述类型默认值
children抽屉内容React.ReactNode-
open受控的打开状态booleanfalse
onClose关闭处理器(e?: React.MouseEvent | React.KeyboardEvent) => void-
afterOpenChange打开/关闭动画完成后的回调(open: boolean) => void-
title抽屉标题React.ReactNode-
placement抽屉位置'left' | 'right' | 'top' | 'bottom''right'
size预设尺寸(378px 或 736px)或自定义数字'default' | 'large' | number'default'
width自定义宽度(覆盖左/右的 size)string | number-
height自定义高度(覆盖上/下的 size)string | number-
closable显示关闭按钮booleantrue
mask显示遮罩层booleantrue
maskClosable点击遮罩层关闭booleantrue
keyboardESC 键关闭booleantrue
footer页脚内容React.ReactNode-
extra头部额外内容(右侧)React.ReactNode-
loading显示加载骨架booleanfalse
destroyOnClose关闭时销毁内容booleanfalse
forceRender预渲染内容(关闭时保留在 DOM 中)booleanfalse
push嵌套抽屉推动行为boolean | { distance: number }{ distance: 180 }
zIndex抽屉的 z-indexnumber1000
className抽屉面板的 CSS 类名string-