Drawer
画面の端からスライドして現れるパネル。
- ブラウザー
- Chrome 123+Firefox 121+Safari 17.5+
- ティア
- 0
- 圧縮後のサイズ
- 4.01 kB
- 強制レイアウトの上限
- 0 ms
- axe の上限
- 0
- SSR 対応
- はい
- 基盤となる要素
- elements/dialog
- 公開された契約
- テストハーネス
プレイグラウンド
Drawer
閉じた状態
スナップ位置
幅
表示する辺
import { DrawerPanel } from "@gunkin/uiify";
export default function Example() {
return (
<div className="">
<DrawerPanel
id="settings-drawer"
side="right"
trigger="Open settings"
title="Settings"
description="Adjust your preferences."
/>
</div>
);
}@layer components {
[data-uiify-drawer][data-part="content"] {
--uiify-drawer-inline-size: 32rem;
margin: 0;
inline-size: 100%;
max-inline-size: 100%;
max-block-size: 100dvh;
padding: var(--space-xl);
border: var(--border-width) solid var(--border);
background: var(--popover);
color: var(--popover-foreground);
box-shadow: var(--shadow-modal);
flex-direction: column;
gap: var(--space-md);
}
[data-uiify-drawer][data-part="content"][open] {
display: flex;
}
[data-uiify-drawer][data-size="sm"] {
--uiify-drawer-inline-size: 24rem;
}
[data-uiify-drawer][data-size="lg"] {
--uiify-drawer-inline-size: 40rem;
}
[data-uiify-drawer][data-size="full"] {
--uiify-drawer-inline-size: 100%;
}
[data-uiify-drawer][data-part="content"]::backdrop {
background: rgb(0 0 0 / 45%);
}
[data-uiify-drawer][data-backdrop="transparent"]::backdrop {
background: transparent;
}
[data-uiify-drawer][data-part="content"][data-side="bottom"] {
margin-block-start: auto;
block-size: min(var(--uiify-drawer-inline-size), 80dvh);
max-block-size: 80dvh;
border-start-start-radius: var(--radius-xl);
border-start-end-radius: var(--radius-xl);
transform: var(--uiify-drawer-transform, none);
}
[data-uiify-drawer][data-part="content"][data-side="top"] {
margin-block-end: auto;
block-size: min(var(--uiify-drawer-inline-size), 80dvh);
max-block-size: 80dvh;
border-end-start-radius: var(--radius-xl);
border-end-end-radius: var(--radius-xl);
transform: var(--uiify-drawer-transform, none);
}
[data-uiify-drawer][data-part="content"]:is([data-side="left"], [data-side="right"]) {
inline-size: min(var(--uiify-drawer-inline-size), 100%);
block-size: 100dvh;
transform: var(--uiify-drawer-transform, none);
}
[data-uiify-drawer][data-part="content"][data-side="left"] {
margin-inline-end: auto;
}
[data-uiify-drawer][data-part="content"][data-side="right"] {
margin-inline-start: auto;
border-start-end-radius: 0;
border-end-end-radius: 0;
}
:dir(rtl) [data-uiify-drawer][data-part="content"][data-side="left"] {
margin-inline: auto 0;
}
:dir(rtl) [data-uiify-drawer][data-part="content"][data-side="right"] {
margin-inline: 0 auto;
}
[data-uiify-drawer][data-part="content"][data-size="full"] {
inline-size: 100dvi;
max-inline-size: 100dvi;
block-size: 100dvh;
max-block-size: 100dvh;
}
[data-uiify-drawer] [data-part="header"] {
position: relative;
flex: none;
padding-inline-end: 2.75rem;
}
[data-uiify-drawer] [data-part="body"] {
min-block-size: 0;
overflow: auto;
overscroll-behavior: contain;
touch-action: pan-y;
}
[data-uiify-drawer] [data-part="footer"] {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: var(--space-sm);
}
[data-uiify-drawer] [data-part="close"] {
display: inline-grid;
place-items: center;
inline-size: 2.25rem;
block-size: 2.25rem;
padding: 0;
border: 0;
border-radius: 50%;
corner-shape: round;
background: var(--secondary);
color: var(--secondary-foreground);
}
[data-uiify-drawer] [data-part="header"] > [data-part="close"] {
position: absolute;
inset-block-start: 0;
inset-inline-end: 0;
}
[data-uiify-drawer] :is([data-part="grabber"], [data-part="handle"]) {
display: none;
flex: none;
block-size: 1.5rem;
touch-action: none;
}
[data-uiify-drawer] :is([data-part="grabber"], [data-part="handle"])::after {
content: "";
display: block;
inline-size: 2.25rem;
block-size: 0.25rem;
margin-block: 0.5rem 0;
margin-inline: auto;
border-radius: 999px;
background: var(--border);
}
[data-uiify-drawer][data-snap-enabled] [data-part="handle"] {
display: block;
}
@media (width < 40rem) {
[data-uiify-drawer][data-part="content"][data-side] {
inline-size: 100dvi;
max-inline-size: 100dvi;
block-size: auto;
min-block-size: 50dvh;
max-block-size: 80dvh;
margin-block: auto 0;
margin-inline: 0;
border-start-start-radius: var(--radius-xl);
border-start-end-radius: var(--radius-xl);
border-end-start-radius: 0;
border-end-end-radius: 0;
transform: var(--uiify-drawer-transform, none);
translate: 0 var(--uiify-sheet-offset, 0);
padding-block-end: calc(var(--space-xl) + env(safe-area-inset-bottom));
}
[data-uiify-drawer][data-part="content"][data-size="full"] {
block-size: 100dvh;
max-block-size: 100dvh;
border-radius: 0;
}
[data-uiify-drawer] :is([data-part="grabber"], [data-part="handle"]) {
display: block;
}
[data-uiify-drawer] [data-part="header"] {
touch-action: none;
}
[data-uiify-drawer][data-dragging] {
transition: none;
}
}
@media (prefers-reduced-motion: no-preference) {
[data-uiify-drawer][data-part="content"] {
transition:
opacity 180ms ease,
translate 220ms ease,
transform 220ms ease,
display 220ms allow-discrete,
overlay 220ms allow-discrete;
}
[data-uiify-drawer][data-part="content"]:not([open]) {
opacity: 0;
}
@starting-style {
[data-uiify-drawer][data-part="content"][open] {
opacity: 0;
}
}
}
}import { DrawerPanel } from "@gunkin/uiify";
export default function Example() {
return (
<div
className={
"[&[data-positioning=native]]:[--uiify-anchor-offset:var(--space-sm)] [&_[data-positioning=native]]:[--uiify" +
"-anchor-offset:var(--space-sm)] [&[popover]:popover-open:not([data-positioning=native])]:[margin:revert] [&" +
"_[popover]:popover-open:not([data-positioning=native])]:[margin:revert] [&_[data-uiify-drawer][data-part=tr" +
"igger]]:relative [&_[data-uiify-drawer][data-part=trigger]]:inline-flex [&_[data-uiify-drawer][data-part=tr" +
"igger]]:min-h-11 [&_[data-uiify-drawer][data-part=trigger]]:min-w-11 [&_[data-uiify-drawer][data-part=trigg" +
"er]]:items-center [&_[data-uiify-drawer][data-part=trigger]]:justify-center [&_[data-uiify-drawer][data-par" +
"t=trigger]]:rounded-full [&_[data-uiify-drawer][data-part=trigger]]:border-[length:var(--border-width)] [&_" +
"[data-uiify-drawer][data-part=trigger]]:border-solid [&_[data-uiify-drawer][data-part=trigger]]:border-tran" +
"sparent [&_[data-uiify-drawer][data-part=trigger]]:bg-foreground [&_[data-uiify-drawer][data-part=trigger]]" +
":px-5 [&_[data-uiify-drawer][data-part=trigger]]:py-0 [&_[data-uiify-drawer][data-part=trigger]]:text-backg" +
"round [&_[data-uiify-drawer][data-part=trigger]]:text-base [&_[data-uiify-drawer][data-part=trigger]]:font-" +
"medium [&_[data-uiify-drawer][data-part=trigger]]:leading-6 [&_[data-uiify-drawer][data-part=trigger]]:no-u" +
"nderline [&_[data-uiify-drawer][data-part=trigger]]:cursor-pointer [&_[data-uiify-drawer][data-part=trigger" +
"]]:[transition:var(--transition-colors)] [&_[data-uiify-drawer][data-part=content]]:[--uiify-drawer-inline-" +
"size:32rem] [&_[data-uiify-drawer][data-size=sm][data-part=content]]:[--uiify-drawer-inline-size:24rem] [&_" +
"[data-uiify-drawer][data-size=lg][data-part=content]]:[--uiify-drawer-inline-size:40rem] [&_[data-uiify-dra" +
"wer][data-size=full][data-part=content]]:[--uiify-drawer-inline-size:100%] [&_[data-uiify-drawer][data-part" +
"=content]]:m-0 [&_[data-uiify-drawer][data-part=content]]:w-full [&_[data-uiify-drawer][data-part=content]]" +
":max-w-full [&_[data-uiify-drawer][data-part=content]]:max-h-dvh [&_[data-uiify-drawer][data-part=content]]" +
":p-6 [&_[data-uiify-drawer][data-part=content]]:border [&_[data-uiify-drawer][data-part=content]]:border-bo" +
"rder [&_[data-uiify-drawer][data-part=content]]:bg-popover [&_[data-uiify-drawer][data-part=content]]:text-" +
"popover-foreground [&_[data-uiify-drawer][data-part=content]]:shadow-modal [&_[data-uiify-drawer][data-part" +
"=content]]:flex-col [&_[data-uiify-drawer][data-part=content]]:gap-md [&_[data-uiify-drawer][data-part=cont" +
"ent]]:rounded-xl [&_[data-uiify-drawer][data-part=content]]:[corner-shape:squircle] [&_[data-uiify-drawer][" +
"data-part=content]::backdrop]:[background:rgb(0_0_0_/_45%)] [&_[data-uiify-drawer][data-part=content][data-" +
"backdrop=transparent]::backdrop]:bg-transparent [&_[data-uiify-drawer][data-part=content][open]]:flex [&_[d" +
"ata-uiify-drawer][data-part=content][data-side=right]]:ms-auto [&_[data-uiify-drawer][data-part=content][da" +
"ta-side=left]]:me-auto [&_[data-uiify-drawer][data-part=content][data-side=top]]:mb-auto [&_[data-uiify-dra" +
"wer][data-part=content][data-side=bottom]]:mt-auto [&_[data-uiify-drawer][data-part=content][data-side=bott" +
"om]]:h-[min(var(--uiify-drawer-inline-size),_80dvh)] [&_[data-uiify-drawer][data-part=content][data-side=to" +
"p]]:h-[min(var(--uiify-drawer-inline-size),_80dvh)] [&_[data-uiify-drawer][data-part=content][data-side=lef" +
"t]]:w-[min(var(--uiify-drawer-inline-size),_100%)] [&_[data-uiify-drawer][data-part=content][data-side=righ" +
"t]]:w-[min(var(--uiify-drawer-inline-size),_100%)] [&_[data-uiify-drawer][data-part=content]:is([data-side=" +
"left],[data-side=right])]:[block-size:100dvh] [&_[data-uiify-drawer][data-part=content][data-side=right]]:[" +
"border-start-end-radius:0] [&_[data-uiify-drawer][data-part=content][data-side=right]]:[border-end-end-radi" +
"us:0] [&_[data-uiify-drawer][data-part=content][data-side=left]]:[border-start-start-radius:0] [&_[data-uii" +
"fy-drawer][data-part=content][data-side=left]]:[border-end-start-radius:0] [&_[data-uiify-drawer][data-part" +
"=content][data-size=full]]:[inline-size:100dvi] [&_[data-uiify-drawer][data-part=content][data-size=full]]:" +
"[block-size:100dvh] [&_[data-uiify-drawer]_[data-part=header]]:relative [&_[data-uiify-drawer]_[data-part=h" +
"eader]]:flex-none [&_[data-uiify-drawer]_[data-part=header]]:pe-11 [&_[data-uiify-drawer]_[data-part=body]]" +
":min-h-0 [&_[data-uiify-drawer]_[data-part=body]]:overflow-auto [&_[data-uiify-drawer]_[data-part=body]]:ov" +
"erscroll-contain [&_[data-uiify-drawer]_[data-part=body]]:[touch-action:pan-y] [&_[data-uiify-drawer]_[data" +
"-part=footer]]:flex [&_[data-uiify-drawer]_[data-part=footer]]:flex-wrap [&_[data-uiify-drawer]_[data-part=" +
"footer]]:justify-end [&_[data-uiify-drawer]_[data-part=footer]]:gap-sm [&_[data-uiify-drawer]_[data-part=cl" +
"ose]]:inline-grid [&_[data-uiify-drawer]_[data-part=close]]:place-items-center [&_[data-uiify-drawer]_[data" +
"-part=close]]:size-9 [&_[data-uiify-drawer]_[data-part=close]]:p-0 [&_[data-uiify-drawer]_[data-part=close]" +
"]:border-0 [&_[data-uiify-drawer]_[data-part=close]]:rounded-full [&_[data-uiify-drawer]_[data-part=close]]" +
":bg-secondary [&_[data-uiify-drawer]_[data-part=close]]:text-secondary-foreground [&_[data-uiify-drawer]_[d" +
"ata-part=close]]:cursor-pointer [&_[data-uiify-drawer]_[data-part=header]>[data-part=close]]:absolute [&_[d" +
"ata-uiify-drawer]_[data-part=header]>[data-part=close]]:[inset-block-start:0] [&_[data-uiify-drawer]_[data-" +
"part=header]>[data-part=close]]:[inset-inline-end:0] [&_[data-uiify-drawer]_:is([data-part=grabber],[data-p" +
"art=handle])]:hidden [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:flex-none [&_[data" +
"-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:[block-size:1.5rem] [&_[data-uiify-drawer]_:is(" +
"[data-part=grabber],[data-part=handle])]:[touch-action:none] [&_[data-uiify-drawer]_:is([data-part=grabber]" +
",[data-part=handle])]:after:content-[''] [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])" +
"]:after:block [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:after:w-9 [&_[data-uiify-" +
"drawer]_:is([data-part=grabber],[data-part=handle])]:after:h-1 [&_[data-uiify-drawer]_:is([data-part=grabbe" +
"r],[data-part=handle])]:after:[margin-block:0.5rem_0] [&_[data-uiify-drawer]_:is([data-part=grabber],[data-" +
"part=handle])]:after:mx-auto [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:after:roun" +
"ded-full [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:after:bg-border max-[40rem]:[&" +
"_[data-uiify-drawer][data-part=content][data-side]]:[inline-size:100dvi] max-[40rem]:[&_[data-uiify-drawer]" +
"[data-part=content][data-side]]:[block-size:auto] max-[40rem]:[&_[data-uiify-drawer][data-part=content][dat" +
"a-side]]:[min-block-size:50dvh] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[max-bloc" +
"k-size:80dvh] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[margin-block:auto_0] max-[" +
"40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[margin-inline:0] max-[40rem]:[&_[data-uiify-d" +
"rawer][data-part=content][data-side]]:[border-start-start-radius:var(--radius-xl)] max-[40rem]:[&_[data-uii" +
"fy-drawer][data-part=content][data-side]]:[border-start-end-radius:var(--radius-xl)] max-[40rem]:[&_[data-u" +
"iify-drawer][data-part=content][data-side]]:[border-end-start-radius:0] max-[40rem]:[&_[data-uiify-drawer][" +
"data-part=content][data-side]]:[border-end-end-radius:0] max-[40rem]:[&_[data-uiify-drawer][data-part=conte" +
"nt][data-side]]:[padding-block-end:calc(var(--space-xl)_+_env(safe-area-inset-bottom))] max-[40rem]:[&_[dat" +
"a-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:block max-[40rem]:[&_[data-uiify-drawer]_[data" +
"-part=header]]:[touch-action:none] [&_[data-uiify-drawer][data-part=title]]:m-0 [&_[data-uiify-drawer][data" +
"-part=title]]:text-[length:var(--text-xl)] [&_[data-uiify-drawer][data-part=description]]:m-0 [&_[data-uiif" +
"y-drawer][data-part=description]]:text-muted-foreground [&_[data-uiify-drawer][data-part=description]]:text" +
"-sm [&_[data-uiify-drawer][data-part=handle]]:mx-auto [&_[data-uiify-drawer][data-part=handle]]:h-1 [&_[dat" +
"a-uiify-drawer][data-part=handle]]:w-10 [&_[data-uiify-drawer][data-part=handle]]:rounded-full [&_[data-uii" +
"fy-drawer][data-part=handle]]:bg-muted-foreground"
}
>
<DrawerPanel
id="settings-drawer"
side="right"
trigger="Open settings"
title="Settings"
description="Adjust your preferences."
/>
</div>
);
}/* app.css */
@layer reset, ui, app, tokens, base, demo, components, utilities, theme;
@import "@gunkin/uiify/styles/reset";
@import "@gunkin/uiify/components/behavior.css";
@import "@gunkin/uiify/styles/tokens";
@import "@gunkin/uiify/styles/tailwind";
@import "tailwindcss/utilities.css";
@theme { --spacing: 0.25rem; --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; }
@source inline('[&[data-positioning=native]]:[--uiify-anchor-offset:var(--space-sm)] [&_[data-positioning=native]]:[--uiify-anchor-offset:var(--space-sm)] [&[popover]:popover-open:not([data-positioning=native])]:[margin:revert] [&_[popover]:popover-open:not([data-positioning=native])]:[margin:revert] [&_[data-uiify-drawer][data-part=trigger]]:relative [&_[data-uiify-drawer][data-part=trigger]]:inline-flex [&_[data-uiify-drawer][data-part=trigger]]:min-h-11 [&_[data-uiify-drawer][data-part=trigger]]:min-w-11 [&_[data-uiify-drawer][data-part=trigger]]:items-center [&_[data-uiify-drawer][data-part=trigger]]:justify-center [&_[data-uiify-drawer][data-part=trigger]]:rounded-full [&_[data-uiify-drawer][data-part=trigger]]:border-[length:var(--border-width)] [&_[data-uiify-drawer][data-part=trigger]]:border-solid [&_[data-uiify-drawer][data-part=trigger]]:border-transparent [&_[data-uiify-drawer][data-part=trigger]]:bg-foreground [&_[data-uiify-drawer][data-part=trigger]]:px-5 [&_[data-uiify-drawer][data-part=trigger]]:py-0 [&_[data-uiify-drawer][data-part=trigger]]:text-background [&_[data-uiify-drawer][data-part=trigger]]:text-base [&_[data-uiify-drawer][data-part=trigger]]:font-medium [&_[data-uiify-drawer][data-part=trigger]]:leading-6 [&_[data-uiify-drawer][data-part=trigger]]:no-underline [&_[data-uiify-drawer][data-part=trigger]]:cursor-pointer [&_[data-uiify-drawer][data-part=trigger]]:[transition:var(--transition-colors)] [&_[data-uiify-drawer][data-part=content]]:[--uiify-drawer-inline-size:32rem] [&_[data-uiify-drawer][data-size=sm][data-part=content]]:[--uiify-drawer-inline-size:24rem] [&_[data-uiify-drawer][data-size=lg][data-part=content]]:[--uiify-drawer-inline-size:40rem] [&_[data-uiify-drawer][data-size=full][data-part=content]]:[--uiify-drawer-inline-size:100%] [&_[data-uiify-drawer][data-part=content]]:m-0 [&_[data-uiify-drawer][data-part=content]]:w-full [&_[data-uiify-drawer][data-part=content]]:max-w-full [&_[data-uiify-drawer][data-part=content]]:max-h-dvh [&_[data-uiify-drawer][data-part=content]]:p-6 [&_[data-uiify-drawer][data-part=content]]:border [&_[data-uiify-drawer][data-part=content]]:border-border [&_[data-uiify-drawer][data-part=content]]:bg-popover [&_[data-uiify-drawer][data-part=content]]:text-popover-foreground [&_[data-uiify-drawer][data-part=content]]:shadow-modal [&_[data-uiify-drawer][data-part=content]]:flex-col [&_[data-uiify-drawer][data-part=content]]:gap-md [&_[data-uiify-drawer][data-part=content]]:rounded-xl [&_[data-uiify-drawer][data-part=content]]:[corner-shape:squircle] [&_[data-uiify-drawer][data-part=content]::backdrop]:[background:rgb(0_0_0_/_45%)] [&_[data-uiify-drawer][data-part=content][data-backdrop=transparent]::backdrop]:bg-transparent [&_[data-uiify-drawer][data-part=content][open]]:flex [&_[data-uiify-drawer][data-part=content][data-side=right]]:ms-auto [&_[data-uiify-drawer][data-part=content][data-side=left]]:me-auto [&_[data-uiify-drawer][data-part=content][data-side=top]]:mb-auto [&_[data-uiify-drawer][data-part=content][data-side=bottom]]:mt-auto [&_[data-uiify-drawer][data-part=content][data-side=bottom]]:h-[min(var(--uiify-drawer-inline-size),_80dvh)] [&_[data-uiify-drawer][data-part=content][data-side=top]]:h-[min(var(--uiify-drawer-inline-size),_80dvh)] [&_[data-uiify-drawer][data-part=content][data-side=left]]:w-[min(var(--uiify-drawer-inline-size),_100%)] [&_[data-uiify-drawer][data-part=content][data-side=right]]:w-[min(var(--uiify-drawer-inline-size),_100%)] [&_[data-uiify-drawer][data-part=content]:is([data-side=left],[data-side=right])]:[block-size:100dvh] [&_[data-uiify-drawer][data-part=content][data-side=right]]:[border-start-end-radius:0] [&_[data-uiify-drawer][data-part=content][data-side=right]]:[border-end-end-radius:0] [&_[data-uiify-drawer][data-part=content][data-side=left]]:[border-start-start-radius:0] [&_[data-uiify-drawer][data-part=content][data-side=left]]:[border-end-start-radius:0] [&_[data-uiify-drawer][data-part=content][data-size=full]]:[inline-size:100dvi] [&_[data-uiify-drawer][data-part=content][data-size=full]]:[block-size:100dvh] [&_[data-uiify-drawer]_[data-part=header]]:relative [&_[data-uiify-drawer]_[data-part=header]]:flex-none [&_[data-uiify-drawer]_[data-part=header]]:pe-11 [&_[data-uiify-drawer]_[data-part=body]]:min-h-0 [&_[data-uiify-drawer]_[data-part=body]]:overflow-auto [&_[data-uiify-drawer]_[data-part=body]]:overscroll-contain [&_[data-uiify-drawer]_[data-part=body]]:[touch-action:pan-y] [&_[data-uiify-drawer]_[data-part=footer]]:flex [&_[data-uiify-drawer]_[data-part=footer]]:flex-wrap [&_[data-uiify-drawer]_[data-part=footer]]:justify-end [&_[data-uiify-drawer]_[data-part=footer]]:gap-sm [&_[data-uiify-drawer]_[data-part=close]]:inline-grid [&_[data-uiify-drawer]_[data-part=close]]:place-items-center [&_[data-uiify-drawer]_[data-part=close]]:size-9 [&_[data-uiify-drawer]_[data-part=close]]:p-0 [&_[data-uiify-drawer]_[data-part=close]]:border-0 [&_[data-uiify-drawer]_[data-part=close]]:rounded-full [&_[data-uiify-drawer]_[data-part=close]]:bg-secondary [&_[data-uiify-drawer]_[data-part=close]]:text-secondary-foreground [&_[data-uiify-drawer]_[data-part=close]]:cursor-pointer [&_[data-uiify-drawer]_[data-part=header]>[data-part=close]]:absolute [&_[data-uiify-drawer]_[data-part=header]>[data-part=close]]:[inset-block-start:0] [&_[data-uiify-drawer]_[data-part=header]>[data-part=close]]:[inset-inline-end:0] [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:hidden [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:flex-none [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:[block-size:1.5rem] [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:[touch-action:none] [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:after:block [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:after:w-9 [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:after:h-1 [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:after:[margin-block:0.5rem_0] [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:after:mx-auto [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:after:rounded-full [&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:after:bg-border max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[inline-size:100dvi] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[block-size:auto] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[min-block-size:50dvh] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[max-block-size:80dvh] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[margin-block:auto_0] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[margin-inline:0] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[border-start-start-radius:var(--radius-xl)] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[border-start-end-radius:var(--radius-xl)] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[border-end-start-radius:0] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[border-end-end-radius:0] max-[40rem]:[&_[data-uiify-drawer][data-part=content][data-side]]:[padding-block-end:calc(var(--space-xl)_+_env(safe-area-inset-bottom))] max-[40rem]:[&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:block max-[40rem]:[&_[data-uiify-drawer]_[data-part=header]]:[touch-action:none] [&_[data-uiify-drawer][data-part=title]]:m-0 [&_[data-uiify-drawer][data-part=title]]:text-[length:var(--text-xl)] [&_[data-uiify-drawer][data-part=description]]:m-0 [&_[data-uiify-drawer][data-part=description]]:text-muted-foreground [&_[data-uiify-drawer][data-part=description]]:text-sm [&_[data-uiify-drawer][data-part=handle]]:mx-auto [&_[data-uiify-drawer][data-part=handle]]:h-1 [&_[data-uiify-drawer][data-part=handle]]:w-10 [&_[data-uiify-drawer][data-part=handle]]:rounded-full [&_[data-uiify-drawer][data-part=handle]]:bg-muted-foreground');
@source inline("[&_[data-uiify-drawer]_:is([data-part=grabber],[data-part=handle])]:after:content-['']");
@layer base { :root { --uiify-control-text: var(--text-sm); } @media (pointer: coarse) { :root { --uiify-control-text: var(--text-base); } } }
/* Authored animation and registered properties used by the Tailwind skin.
* Visual rules belong in utility recipes; only at-rule definitions live here. */
@layer components {
@keyframes uiify-presence-in {
from {
opacity: 0;
scale: var(--presence-scale);
}
}
}
@layer components {
@keyframes uiify-presence-out {
to {
opacity: 0;
scale: var(--presence-scale);
}
}
}
@property --uiify-spinner-tail {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
@property --uiify-spinner-length {
syntax: "<angle>";
inherits: false;
initial-value: 36deg;
}
@layer components {
@keyframes uiify-spinner-rotate {
to {
transform: rotate(360deg);
}
}
}
@layer components {
@keyframes uiify-spinner-orbit {
0% {
--uiify-spinner-tail: 0deg;
--uiify-spinner-length: 36deg;
}
50% {
--uiify-spinner-tail: 90deg;
--uiify-spinner-length: 324deg;
}
100% {
--uiify-spinner-tail: 360deg;
--uiify-spinner-length: 36deg;
}
}
}
@layer components {
@keyframes uiify-skeleton-pulse {
50% {
opacity: 0.45;
}
}
}
@layer components {
@keyframes uiify-skeleton-shimmer {
to {
background-position: -200% 0;
}
}
}
@layer components {
@keyframes uiify-skeleton-reveal {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}
@property --candle-body-height {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-body-top {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --candle-slot {
syntax: "<percentage>";
inherits: true;
initial-value: 100%;
}
@property --candle-wick-height {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-wick-top {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --candle-x {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-scale {
syntax: "<number>";
inherits: true;
initial-value: 1;
}
@property --line-y {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --line-prev-y {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --line-count {
syntax: "<integer>";
inherits: false;
initial-value: 1;
}
@property --line-scale {
syntax: "<number>";
inherits: true;
initial-value: 1;
}
@layer components {
@keyframes uiify-otp-input-caret-blink {
50% {
opacity: 0;
}
}
}API
DrawerPanel
| Prop | 型 | 既定値 | 説明 |
|---|---|---|---|
size | "sm" | "md" | "lg" | "full" | "md" | デスクトップでの幅。24rem、32rem、40rem、利用可能な幅。モバイルではすべてのサイズが縦方向のボトムシートになります。 |
dismiss | "any" | "closerequest" | "none" | "any" | ネイティブの終了方針。Anyは背景、Escape、モバイルでの下向きスワイプを許可します。noneには明示的な閉じるコントロールが必要です。 |
backdrop | "opaque" | "transparent" | "opaque" | 背景の見た目。モーダルのセマンティクスは変わりません。 |
footer | ReactNode | — | スクロール可能な本文に続くアクション。 |
id* | string | — | トリガーと閉じるボタンが対象とする、一意のdialog ID。ハイドレーション前にドロワーを開閉できます。 |
trigger* | ReactNode | — | ドロワーを開くボタンの内容。 |
title* | ReactNode | — | ドロワー内に描画し、そのアクセシブルな名前に使う見出し。 |
description | ReactNode | — | タイトルの下に描画し、aria-describedbyから参照する補足テキスト。 |
children | ReactNode | — | 説明と閉じるボタンの間に配置する本文。 |
side | "top" | "right" | "bottom" | "left" | "bottom" | ドロワーがスライドして現れる画面の端。 |
closeLabel | string | "Close" | 円形の閉じるアイコンのアクセシブルなラベル。 |
className | string | — | dialog要素に適用するクラス。 |
Drawer.Root (client)
| Prop | 型 | 既定値 | 説明 |
|---|---|---|---|
open | boolean | — | 制御される開閉状態。 |
defaultOpen | boolean | — | 非制御の初期開閉状態。 |
onOpenChange | DialogChangeHandler | — | 次の開閉状態と、変更の原因の詳細で呼び出します。 |
side | "top" | "right" | "bottom" | "left" | "bottom" | ドロワーがスライドして現れる画面の端。ドラッグ軸も決定します。 |
modal | boolean | true | showModal()で開き、背景の背後にあるページの残りをinertにします。 |
dismissible | boolean | true | 最後のスナップ位置を超えるドラッグでドロワーを閉じられるようにします。 |
snapPoints | readonly number[] | — | ドラッグ後にパネルが停止する位置。ドロワーのサイズに対する割合で指定します。 |
activeSnapPoint | number | — | 制御されるスナップ位置。snapPoints内の値のいずれかを指定します。 |
defaultActiveSnapPoint | number | — | 非制御の初期スナップ位置。 |
onSnapChange | (snap: number) => void | — | ドロワーが停止したスナップ位置で呼び出します。 |
children | ReactNode | — | Trigger、Contentと内部のパーツ。 |
Drawer.Trigger (client)
| Prop | 型 | 既定値 | 説明 |
|---|---|---|---|
className | string | — | トリガーボタンに適用するクラス。 |
onClick | (event: MouseEvent<HTMLButtonElement>) => void | — | トリガーをクリックすると、ドロワーが開く前に呼び出します。 |
ref | Ref<HTMLButtonElement> | — | ドロワーが閉じると再びフォーカスするトリガーボタンへのref。 |
children | ReactNode | — | トリガーボタンの内容。 |
Drawer.Content (client)
| Prop | 型 | 既定値 | 説明 |
|---|---|---|---|
className | string | — | dialog要素に適用するクラス。 |
style | CSSProperties | — | ドロワーが適用するドラッグのtransformとマージするインラインスタイル。 |
onCancel | ReactEventHandler<HTMLDialogElement> | — | Escapeを押した場合など、ネイティブのdialog cancelイベントで呼び出します。 |
onClose | ReactEventHandler<HTMLDialogElement> | — | ネイティブのdialog closeイベントで呼び出します。 |
ref | Ref<HTMLDialogElement> | — | dialog要素へのref。 |
children | ReactNode | — | ドロワーの内容。 |
Drawer.Title (client)
| Prop | 型 | 既定値 | 説明 |
|---|---|---|---|
className | string | — | タイトル要素に適用するクラス。 |
children | ReactNode | — | ドロワーのアクセシブルな名前になるタイトルの内容。 |
Drawer.Description (client)
| Prop | 型 | 既定値 | 説明 |
|---|---|---|---|
className | string | — | 説明要素に適用するクラス。 |
children | ReactNode | — | aria-describedbyから参照する説明の内容。 |
Drawer.Close (client)
| Prop | 型 | 既定値 | 説明 |
|---|---|---|---|
className | string | — | 閉じるボタンに適用するクラス。 |
onClick | (event: MouseEvent<HTMLButtonElement>) => void | — | 閉じるボタンをクリックすると、ドロワーが閉じる前に呼び出します。 |
children | ReactNode | — | 閉じるボタンの内容。 |
Drawer.Handle (client)
| Prop | 型 | 既定値 | 説明 |
|---|---|---|---|
className | string | — | ドラッグハンドルに適用するクラス。 |
onPointerDown | (event: PointerEvent<HTMLDivElement>) => void | — | ハンドルでドラッグが始まると呼び出します。 |
onPointerMove | (event: PointerEvent<HTMLDivElement>) => void | — | ドラッグ中にポインターが動くと呼び出します。 |
onPointerUp | (event: PointerEvent<HTMLDivElement>) => void | — | ドラッグが終わり、ドロワーがスナップ位置で停止すると呼び出します。 |
onPointerCancel | (event: PointerEvent<HTMLDivElement>) => void | — | ブラウザーがドラッグをキャンセルすると呼び出します。 |
キーボード
| キー | 操作 |
|---|---|
| Enter / Space | トリガーからダイアログを開く、またはCloseを実行 |
| Escape | dismissがnoneでなければ終了を要求 |
| Tab / Shift+Tab | モーダルダイアログ内を移動 |
アクセシビリティ
DrawerPanelは対象IDでつないだdialogを使うため、ハイドレーション前から開閉、フォーカスの封じ込め、フォーカスの復帰が動作します。dismissは背景とEscapeを制御します。パネルの幅はsm、md、lg、fullで、スマートフォンではボトムシートになります。スワイプはハンドルまたはヘッダーから始めるため、本文は引き続きスクロールできます。クライアントAPIは制御状態とスナップ位置を追加します。
スタイリングのフック
data-uiify-drawerdata-partdata-sidedata-sizedata-backdropdata-statedata-dragging--uiify-drawer-inline-size--uiify-drawer-transform--uiify-sheet-offset