import { Button, CloseButton, Drawer, Portal } from "@chakra-ui/react"
const Demo = () => {
return (
<Drawer.Root>
<Drawer.Trigger asChild>
<Button variant="outline" size="sm">
Open Drawer
</Button>
</Drawer.Trigger>
<Portal>
<Drawer.Backdrop />
<Drawer.Positioner>
<Drawer.Content>
<Drawer.Header>
<Drawer.Title>Drawer Title</Drawer.Title>
</Drawer.Header>
<Drawer.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</Drawer.Body>
<Drawer.Footer>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</Drawer.Footer>
<Drawer.CloseTrigger asChild>
<CloseButton size="sm" />
</Drawer.CloseTrigger>
</Drawer.Content>
</Drawer.Positioner>
</Portal>
</Drawer.Root>
)
}
用法
import { Drawer } from "@chakra-ui/react"
<Drawer.Root>
<Drawer.Backdrop />
<Drawer.Trigger />
<Drawer.Positioner>
<Drawer.Content>
<Drawer.CloseTrigger />
<Drawer.Header>
<Drawer.Title />
</Drawer.Header>
<Drawer.Body />
<Drawer.Footer />
</Drawer.Content>
</Drawer.Positioner>
</Drawer.Root>
示例
受控
使用 open
和 onOpenChange
props 来控制抽屉组件。
"use client"
import { Button, CloseButton, Drawer, Portal } from "@chakra-ui/react"
import { useState } from "react"
const Demo = () => {
const [open, setOpen] = useState(false)
return (
<Drawer.Root open={open} onOpenChange={(e) => setOpen(e.open)}>
<Drawer.Trigger asChild>
<Button variant="outline" size="sm">
Open Drawer
</Button>
</Drawer.Trigger>
<Portal>
<Drawer.Backdrop />
<Drawer.Positioner>
<Drawer.Content>
<Drawer.Header>
<Drawer.Title>Drawer Title</Drawer.Title>
</Drawer.Header>
<Drawer.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</Drawer.Body>
<Drawer.Footer>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</Drawer.Footer>
<Drawer.CloseTrigger asChild>
<CloseButton size="sm" />
</Drawer.CloseTrigger>
</Drawer.Content>
</Drawer.Positioner>
</Portal>
</Drawer.Root>
)
}
尺寸
使用 size
prop 来改变抽屉组件的尺寸。
import {
Button,
CloseButton,
Drawer,
For,
HStack,
Kbd,
Portal,
} from "@chakra-ui/react"
const Demo = () => {
return (
<HStack wrap="wrap">
<For each={["xs", "sm", "md", "lg", "xl", "full"]}>
{(size) => (
<Drawer.Root key={size} size={size}>
<Drawer.Trigger asChild>
<Button variant="outline" size="sm">
Open ({size})
</Button>
</Drawer.Trigger>
<Portal>
<Drawer.Backdrop />
<Drawer.Positioner>
<Drawer.Content>
<Drawer.Header>
<Drawer.Title>Drawer Title</Drawer.Title>
</Drawer.Header>
<Drawer.Body>
Press the <Kbd>esc</Kbd> key to close the drawer.
</Drawer.Body>
<Drawer.Footer>
<Drawer.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Drawer.ActionTrigger>
<Button>Save</Button>
</Drawer.Footer>
<Drawer.CloseTrigger asChild>
<CloseButton size="sm" />
</Drawer.CloseTrigger>
</Drawer.Content>
</Drawer.Positioner>
</Portal>
</Drawer.Root>
)}
</For>
</HStack>
)
}
上下文
使用 DrawerContext
组件可以从抽屉外部访问抽屉的状态和方法。
"use client"
import { Button, CloseButton, Drawer, Portal } from "@chakra-ui/react"
const Demo = () => {
return (
<Drawer.Root>
<Drawer.Trigger asChild>
<Button variant="outline" size="sm">
Open Drawer
</Button>
</Drawer.Trigger>
<Portal>
<Drawer.Backdrop />
<Drawer.Positioner>
<Drawer.Content>
<Drawer.Context>
{(store) => (
<Drawer.Body pt="6" spaceY="3">
<p>Drawer is open: {store.open ? "true" : "false"}</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
do eiusmod tempor incididunt ut labore et dolore magna
aliqua.
</p>
<button onClick={() => store.setOpen(false)}>Close</button>
</Drawer.Body>
)}
</Drawer.Context>
<Drawer.CloseTrigger asChild>
<CloseButton size="sm" />
</Drawer.CloseTrigger>
</Drawer.Content>
</Drawer.Positioner>
</Portal>
</Drawer.Root>
)
}
偏移
将 offset
prop 传递给 DrawerContent
以改变抽屉组件的偏移量。
import { Button, CloseButton, Drawer, Portal } from "@chakra-ui/react"
const Demo = () => {
return (
<Drawer.Root>
<Drawer.Trigger asChild>
<Button variant="outline" size="sm">
Open Drawer
</Button>
</Drawer.Trigger>
<Portal>
<Drawer.Backdrop />
<Drawer.Positioner padding="4">
<Drawer.Content rounded="md">
<Drawer.Header>
<Drawer.Title>Drawer Title</Drawer.Title>
</Drawer.Header>
<Drawer.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</Drawer.Body>
<Drawer.Footer>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</Drawer.Footer>
<Drawer.CloseTrigger asChild>
<CloseButton size="sm" />
</Drawer.CloseTrigger>
</Drawer.Content>
</Drawer.Positioner>
</Portal>
</Drawer.Root>
)
}
放置
使用 placement
prop 来改变抽屉组件的放置位置。
import {
Button,
CloseButton,
Drawer,
For,
HStack,
Portal,
} from "@chakra-ui/react"
const Demo = () => {
return (
<HStack wrap="wrap">
<For each={["bottom", "top", "start", "end"]}>
{(placement) => (
<Drawer.Root key={placement} placement={placement}>
<Drawer.Trigger asChild>
<Button variant="outline" size="sm">
Open ({placement})
</Button>
</Drawer.Trigger>
<Portal>
<Drawer.Backdrop />
<Drawer.Positioner>
<Drawer.Content
roundedTop={placement === "bottom" ? "l3" : undefined}
roundedBottom={placement === "top" ? "l3" : undefined}
>
<Drawer.Header>
<Drawer.Title>Drawer Title</Drawer.Title>
</Drawer.Header>
<Drawer.Body>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
do eiusmod tempor incididunt ut labore et dolore magna
aliqua.
</Drawer.Body>
<Drawer.Footer>
<Drawer.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Drawer.ActionTrigger>
<Button>Save</Button>
</Drawer.Footer>
<Drawer.CloseTrigger asChild>
<CloseButton size="sm" />
</Drawer.CloseTrigger>
</Drawer.Content>
</Drawer.Positioner>
</Portal>
</Drawer.Root>
)}
</For>
</HStack>
)
}
初始焦点
使用 initialFocusEl
prop 来设置抽屉组件的初始焦点。
"use client"
import {
Button,
CloseButton,
Drawer,
Input,
Portal,
Stack,
} from "@chakra-ui/react"
import { useRef } from "react"
const Demo = () => {
const ref = useRef<HTMLInputElement>(null)
return (
<Drawer.Root initialFocusEl={() => ref.current}>
<Drawer.Trigger asChild>
<Button variant="outline" size="sm">
Open Drawer
</Button>
</Drawer.Trigger>
<Portal>
<Drawer.Backdrop />
<Drawer.Positioner>
<Drawer.Content>
<Drawer.Header>
<Drawer.Title>Drawer Title</Drawer.Title>
</Drawer.Header>
<Drawer.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
<Stack mt="5">
<Input defaultValue="Naruto" placeholder="First name" />
<Input ref={ref} placeholder="Email" />
</Stack>
</Drawer.Body>
<Drawer.Footer>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</Drawer.Footer>
<Drawer.CloseTrigger asChild>
<CloseButton size="sm" />
</Drawer.CloseTrigger>
</Drawer.Content>
</Drawer.Positioner>
</Portal>
</Drawer.Root>
)
}
自定义容器
以下是一个如何在自定义容器中渲染抽屉组件的示例。
考虑将 closeOnInteractOutside
设置为 false
,以防止抽屉在外部交互时关闭。
在此处渲染抽屉
"use client"
import {
Button,
CloseButton,
Drawer,
Portal,
Stack,
type StackProps,
Text,
} from "@chakra-ui/react"
import { forwardRef, useRef } from "react"
const DrawerContainer = forwardRef<HTMLDivElement, StackProps>(
function DrawerContainer(props, ref) {
return (
<Stack
pos="relative"
overflow="hidden"
align="flex-start"
p="8"
minH="400px"
layerStyle="fill.subtle"
outline="2px solid gray"
ref={ref}
{...props}
/>
)
},
)
const Demo = () => {
const portalRef = useRef<HTMLDivElement | null>(null)
return (
<Drawer.Root closeOnInteractOutside={false}>
<DrawerContainer ref={portalRef}>
<Text>Render drawer here</Text>
<Drawer.Trigger asChild>
<Button variant="outline" size="sm" bg="bg">
Open Drawer
</Button>
</Drawer.Trigger>
</DrawerContainer>
<Portal container={portalRef}>
<Drawer.Backdrop pos="absolute" boxSize="full" />
<Drawer.Positioner pos="absolute" boxSize="full">
<Drawer.Content>
<Drawer.Header>
<Drawer.Title>Drawer Title</Drawer.Title>
<Drawer.CloseTrigger asChild>
<CloseButton size="sm" />
</Drawer.CloseTrigger>
</Drawer.Header>
<Drawer.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</Drawer.Body>
<Drawer.Footer>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</Drawer.Footer>
</Drawer.Content>
</Drawer.Positioner>
</Portal>
</Drawer.Root>
)
}
头部动作
以下是一个在抽屉组件头部渲染动作的示例。
import {
Button,
ButtonGroup,
CloseButton,
Drawer,
Portal,
} from "@chakra-ui/react"
const Demo = () => {
return (
<Drawer.Root size="md">
<Drawer.Trigger asChild>
<Button variant="outline" size="sm">
Open Drawer
</Button>
</Drawer.Trigger>
<Portal>
<Drawer.Backdrop />
<Drawer.Positioner>
<Drawer.Content>
<Drawer.Header>
<Drawer.CloseTrigger asChild pos="initial">
<CloseButton />
</Drawer.CloseTrigger>
<Drawer.Title flex="1">Drawer Title</Drawer.Title>
<ButtonGroup>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</ButtonGroup>
</Drawer.Header>
<Drawer.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</Drawer.Body>
</Drawer.Content>
</Drawer.Positioner>
</Portal>
</Drawer.Root>
)
}
Props
根
Prop | 默认 | 类型 |
---|---|---|
colorPalette | 'gray' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' 组件的颜色调色板 |
size | 'xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full' 组件的尺寸 |
placement | 'end' | 'start' | 'end' | 'top' | 'bottom' 组件的放置位置 |
contained | 'true' | 'false' 组件的包含状态 | |
as | React.ElementType 要渲染的底层元素。 | |
asChild | ||
unstyled | boolean 是否移除组件的样式。 |