@qijenchen/design-system 0.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +93 -0
- package/src/README.md +32 -0
- package/src/components/Accordion/accordion.tsx +104 -0
- package/src/components/Alert/alert.tsx +188 -0
- package/src/components/AppShell/_demo-helpers.tsx +198 -0
- package/src/components/AppShell/app-shell.tsx +364 -0
- package/src/components/AspectRatio/aspect-ratio.tsx +58 -0
- package/src/components/Avatar/avatar.tsx +368 -0
- package/src/components/Badge/badge.tsx +104 -0
- package/src/components/Breadcrumb/breadcrumb.tsx +609 -0
- package/src/components/BulkActionBar/bulk-action-bar.tsx +156 -0
- package/src/components/Button/button-group.tsx +96 -0
- package/src/components/Button/button.tsx +539 -0
- package/src/components/Calendar/calendar.tsx +411 -0
- package/src/components/Carousel/carousel.tsx +371 -0
- package/src/components/Chart/chart.tsx +376 -0
- package/src/components/Checkbox/checkbox-group.tsx +94 -0
- package/src/components/Checkbox/checkbox.tsx +237 -0
- package/src/components/Chip/chip.tsx +359 -0
- package/src/components/CircularProgress/circular-progress.tsx +204 -0
- package/src/components/Coachmark/coachmark.tsx +255 -0
- package/src/components/Combobox/combobox.tsx +826 -0
- package/src/components/Command/command.tsx +187 -0
- package/src/components/DataTable/active-editor-controller.ts +72 -0
- package/src/components/DataTable/cell-registry.tsx +520 -0
- package/src/components/DataTable/column-types.ts +180 -0
- package/src/components/DataTable/data-table-column-visibility-panel.tsx +261 -0
- package/src/components/DataTable/data-table-filter-panel.tsx +813 -0
- package/src/components/DataTable/data-table-interaction-layer.tsx +483 -0
- package/src/components/DataTable/data-table-sort-manager.tsx +210 -0
- package/src/components/DataTable/data-table.css +165 -0
- package/src/components/DataTable/data-table.tsx +2924 -0
- package/src/components/DataTable/filter-operators.ts +225 -0
- package/src/components/DataTable/filter-tree.ts +313 -0
- package/src/components/DataTable/lib/column-meta.ts +79 -0
- package/src/components/DateGrid/date-grid.tsx +209 -0
- package/src/components/DatePicker/date-picker.tsx +1114 -0
- package/src/components/DescriptionList/description-list.tsx +141 -0
- package/src/components/Dialog/dialog.tsx +267 -0
- package/src/components/DropdownMenu/dropdown-menu.tsx +475 -0
- package/src/components/Empty/empty.tsx +108 -0
- package/src/components/Field/field-context.ts +136 -0
- package/src/components/Field/field-types.ts +52 -0
- package/src/components/Field/field-wrapper.tsx +348 -0
- package/src/components/Field/field.tsx +535 -0
- package/src/components/FieldControlGroup/field-control-group.tsx +136 -0
- package/src/components/FileItem/file-item.tsx +322 -0
- package/src/components/FileUpload/file-upload.tsx +326 -0
- package/src/components/FileViewer/file-viewer-types.ts +76 -0
- package/src/components/FileViewer/file-viewer.tsx +1065 -0
- package/src/components/FileViewer/image-renderer.tsx +256 -0
- package/src/components/HoverCard/hover-card.tsx +79 -0
- package/src/components/Input/input.tsx +233 -0
- package/src/components/LinkInput/link-input.tsx +304 -0
- package/src/components/Menu/menu-item.tsx +334 -0
- package/src/components/NameCard/name-card.tsx +319 -0
- package/src/components/Notice/notice.tsx +196 -0
- package/src/components/NumberInput/number-input.tsx +203 -0
- package/src/components/OverflowIndicator/overflow-indicator.tsx +156 -0
- package/src/components/PeoplePicker/avatar-stack-overflow.ts +100 -0
- package/src/components/PeoplePicker/people-picker-helpers.ts +76 -0
- package/src/components/PeoplePicker/people-picker.tsx +455 -0
- package/src/components/PeoplePicker/person-display.tsx +358 -0
- package/src/components/Popover/popover.tsx +183 -0
- package/src/components/ProgressBar/progress-bar.tsx +157 -0
- package/src/components/README.md +58 -0
- package/src/components/RadioGroup/radio-group.tsx +261 -0
- package/src/components/Rating/rating.tsx +295 -0
- package/src/components/ScrollArea/scroll-area.tsx +110 -0
- package/src/components/SegmentedControl/segmented-control.tsx +304 -0
- package/src/components/Select/select.tsx +658 -0
- package/src/components/SelectMenu/select-menu.tsx +430 -0
- package/src/components/SelectionControl/selection-item.tsx +261 -0
- package/src/components/Separator/separator.tsx +48 -0
- package/src/components/Sheet/sheet.tsx +240 -0
- package/src/components/Sidebar/sidebar.tsx +1280 -0
- package/src/components/Skeleton/skeleton.tsx +35 -0
- package/src/components/Slider/slider.tsx +158 -0
- package/src/components/Steps/steps.tsx +850 -0
- package/src/components/Switch/switch.tsx +285 -0
- package/src/components/Tabs/tabs.tsx +515 -0
- package/src/components/Tag/tag.tsx +246 -0
- package/src/components/Textarea/textarea.tsx +280 -0
- package/src/components/TimePicker/time-columns.tsx +260 -0
- package/src/components/TimePicker/time-picker.tsx +419 -0
- package/src/components/Toast/toast.tsx +129 -0
- package/src/components/Tooltip/tooltip.tsx +68 -0
- package/src/components/TreeView/tree-view.tsx +1031 -0
- package/src/hooks/use-controllable.ts +40 -0
- package/src/hooks/use-is-narrow-viewport.ts +19 -0
- package/src/hooks/use-is-touch-device.ts +21 -0
- package/src/hooks/use-overflow-items.ts +256 -0
- package/src/index.ts +85 -0
- package/src/lib/README.md +82 -0
- package/src/lib/drag-visual.ts +272 -0
- package/src/lib/i18n/README.md +60 -0
- package/src/lib/i18n/i18n-context.tsx +129 -0
- package/src/lib/multi-select-ordering.ts +61 -0
- package/src/lib/utils.ts +93 -0
- package/src/patterns/README.md +67 -0
- package/src/patterns/element-anatomy/item-anatomy.tsx +744 -0
- package/src/patterns/header-canonical/chrome-header.tsx +175 -0
- package/src/patterns/header-canonical/header-canonical.css +27 -0
- package/src/patterns/horizontal-overflow/horizontal-overflow.tsx +217 -0
- package/src/patterns/overlay-surface/overlay-surface.tsx +191 -0
- package/src/patterns/resize-handle/resize-handle.tsx +188 -0
- package/src/stories-helpers/anatomy/anatomy-utils.tsx +64 -0
- package/src/tokens/README.md +53 -0
- package/src/tokens/color/primitives.css +429 -0
- package/src/tokens/color/semantic.css +539 -0
- package/src/tokens/elevation/overlay-geometry.ts +13 -0
- package/src/tokens/layoutSpace/layoutSpace.css +36 -0
- package/src/tokens/motion/motion.css +30 -0
- package/src/tokens/motion/motion.ts +17 -0
- package/src/tokens/opacity/opacity.css +23 -0
- package/src/tokens/radius/radius.css +19 -0
- package/src/tokens/typography/typography.css +118 -0
- package/src/tokens/uiSize/icon-size.ts +52 -0
- package/src/tokens/uiSize/uiSize.css +125 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
const Separator = React.forwardRef<
|
|
7
|
+
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
|
8
|
+
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
|
9
|
+
>(
|
|
10
|
+
(
|
|
11
|
+
{ className, orientation = "horizontal", decorative = true, ...props },
|
|
12
|
+
ref
|
|
13
|
+
) => (
|
|
14
|
+
<SeparatorPrimitive.Root
|
|
15
|
+
ref={ref}
|
|
16
|
+
decorative={decorative}
|
|
17
|
+
orientation={orientation}
|
|
18
|
+
className={cn(
|
|
19
|
+
"shrink-0 bg-divider",
|
|
20
|
+
orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
|
|
21
|
+
className
|
|
22
|
+
)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
)
|
|
27
|
+
Separator.displayName = "Separator"
|
|
28
|
+
|
|
29
|
+
// Story auto-compile metadata — Phase 1 mechanical migration(2026-04-24)
|
|
30
|
+
// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs
|
|
31
|
+
export const separatorMeta = {
|
|
32
|
+
component: 'Separator',
|
|
33
|
+
family: null, // non-family composite / overlay / layout
|
|
34
|
+
variants: {
|
|
35
|
+
|
|
36
|
+
},
|
|
37
|
+
sizes: {
|
|
38
|
+
|
|
39
|
+
},
|
|
40
|
+
states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
|
|
41
|
+
tokens: {
|
|
42
|
+
bg: [],
|
|
43
|
+
fg: [],
|
|
44
|
+
ring: [],
|
|
45
|
+
},
|
|
46
|
+
} as const
|
|
47
|
+
|
|
48
|
+
export { Separator }
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.
|
|
2
|
+
import * as React from "react"
|
|
3
|
+
import * as SheetPrimitive from "@radix-ui/react-dialog"
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
5
|
+
import { X as XIcon } from "lucide-react"
|
|
6
|
+
|
|
7
|
+
import { cn } from "@/lib/utils"
|
|
8
|
+
import {
|
|
9
|
+
SurfaceHeader,
|
|
10
|
+
SurfaceFooter,
|
|
11
|
+
type SurfaceHeaderProps,
|
|
12
|
+
} from "@/design-system/patterns/overlay-surface/overlay-surface"
|
|
13
|
+
import { Button } from "@/design-system/components/Button/button"
|
|
14
|
+
import { ScrollArea } from "@/design-system/components/ScrollArea/scroll-area"
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Sheet — **右側 Dialog primitive**(給消費者的 canonical)。
|
|
18
|
+
*
|
|
19
|
+
* ── 定位(2026-04-21 canonical)──
|
|
20
|
+
* Sheet 給**消費者**用的唯一合法形式 = **右側開啟的 modal**(side="right"),
|
|
21
|
+
* 內部結構跟 `Dialog` 一致:`SheetHeader` / `SheetBody` / `SheetFooter`(各自消費
|
|
22
|
+
* `SurfaceHeader` / `SurfaceBody` / `SurfaceFooter` primitive,padding token SSOT
|
|
23
|
+
* 在 `patterns/overlay-surface/`)。side="right" 是 defaultVariants,消費者不傳 side。
|
|
24
|
+
*
|
|
25
|
+
* ── 其他 side(top / bottom / left)——**非消費者 API**,內部基建用 ──
|
|
26
|
+
* top / bottom / left 變體保留給 DS 內部基建(例:Sidebar 在小尺寸視口時從 left 滑入)。
|
|
27
|
+
* 消費者 code **禁止** 傳 `side="top" | "bottom" | "left"` — 這些用途需 user 授權。
|
|
28
|
+
*
|
|
29
|
+
* ── 跟 Dialog 的差異 ──
|
|
30
|
+
* - Dialog = 中央 modal,用於「明確決策 / 表單 / 確認」
|
|
31
|
+
* - Sheet(side="right")= 側滑 modal,用於「補充資訊 / 多欄位表單 / 編輯 flow」
|
|
32
|
+
* - 兩者 API 結構 1:1 對應,差異只在 side / 動畫 / 初始寬度
|
|
33
|
+
*
|
|
34
|
+
* ── Header / Body / Footer 消費 SurfaceXxx SSOT ──
|
|
35
|
+
* 避免 padding 漂移 — Dialog / Popover / Sheet / Coachmark 共用同一套 overlay-surface
|
|
36
|
+
* padding token(px-loose / py-tight),改 overlay-surface.tsx 四者自動跟進。
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
const Sheet = SheetPrimitive.Root
|
|
40
|
+
|
|
41
|
+
const SheetTrigger = SheetPrimitive.Trigger
|
|
42
|
+
|
|
43
|
+
const SheetClose = SheetPrimitive.Close
|
|
44
|
+
|
|
45
|
+
const SheetPortal = SheetPrimitive.Portal
|
|
46
|
+
|
|
47
|
+
const SheetOverlay = React.forwardRef<
|
|
48
|
+
React.ElementRef<typeof SheetPrimitive.Overlay>,
|
|
49
|
+
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
|
|
50
|
+
>(({ className, ...props }, ref) => (
|
|
51
|
+
<SheetPrimitive.Overlay
|
|
52
|
+
className={cn(
|
|
53
|
+
"fixed inset-0 z-50 bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
54
|
+
className
|
|
55
|
+
)}
|
|
56
|
+
{...props}
|
|
57
|
+
ref={ref}
|
|
58
|
+
/>
|
|
59
|
+
))
|
|
60
|
+
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
|
|
61
|
+
|
|
62
|
+
// ── sheetVariants ─────────────────────────────────────────────────────────
|
|
63
|
+
// side="right" 給**消費者**。top/bottom/left 給 **DS 內部基建**用(如 Sidebar 在
|
|
64
|
+
// narrow viewport 時切 side="left")。消費者 code 不傳 side,用 default。
|
|
65
|
+
const sheetVariants = cva(
|
|
66
|
+
// 核心容器 — 無 padding(由 SheetBody / SheetHeader / SheetFooter 自理 padding,
|
|
67
|
+
// 對齊 overlay-surface pattern + Dialog canonical)
|
|
68
|
+
// Animation canonical:300ms 雙向一致(D4 audit:500ms 太久 sluggish)+ motion-reduce 豁免
|
|
69
|
+
"fixed z-50 flex flex-col bg-surface-raised shadow-[var(--elevation-200)] transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-300 motion-reduce:transition-none motion-reduce:data-[state=open]:duration-0 motion-reduce:data-[state=closed]:duration-0",
|
|
70
|
+
{
|
|
71
|
+
variants: {
|
|
72
|
+
side: {
|
|
73
|
+
top: "inset-x-0 top-0 border-b border-divider data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
|
74
|
+
bottom:
|
|
75
|
+
"inset-x-0 bottom-0 border-t border-divider data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
|
76
|
+
left: "inset-y-0 left-0 h-full w-3/4 border-r border-divider data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-md",
|
|
77
|
+
right:
|
|
78
|
+
"inset-y-0 right-0 h-full w-3/4 border-l border-divider data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-md",
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
defaultVariants: {
|
|
82
|
+
side: "right",
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
interface SheetContentProps
|
|
88
|
+
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
|
89
|
+
VariantProps<typeof sheetVariants> {}
|
|
90
|
+
|
|
91
|
+
// AutoFocus canonical(對齊 Dialog / Material / Polaris)— 見 dialog.tsx handleOpenAutoFocus 註解
|
|
92
|
+
const handleSheetOpenAutoFocus = (e: Event) => {
|
|
93
|
+
e.preventDefault()
|
|
94
|
+
const content = e.currentTarget as HTMLElement
|
|
95
|
+
const firstBodyTarget = content.querySelector<HTMLElement>(
|
|
96
|
+
'[data-sheet-body] input:not([disabled]),[data-sheet-body] textarea:not([disabled]),[data-sheet-body] select:not([disabled]),[data-sheet-body] button:not([disabled]):not([data-dismiss])'
|
|
97
|
+
)
|
|
98
|
+
const firstFooterButton = content.querySelector<HTMLElement>(
|
|
99
|
+
'[data-sheet-footer] button:not([disabled]):not([data-dismiss])'
|
|
100
|
+
)
|
|
101
|
+
;(firstBodyTarget ?? firstFooterButton ?? content).focus({ preventScroll: true })
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const SheetContent = React.forwardRef<
|
|
105
|
+
React.ElementRef<typeof SheetPrimitive.Content>,
|
|
106
|
+
SheetContentProps
|
|
107
|
+
>(({ side = "right", className, children, ...props }, ref) => (
|
|
108
|
+
<SheetPortal>
|
|
109
|
+
<SheetOverlay />
|
|
110
|
+
<SheetPrimitive.Content
|
|
111
|
+
ref={ref}
|
|
112
|
+
onOpenAutoFocus={handleSheetOpenAutoFocus}
|
|
113
|
+
// Sheet 不自設 density,繼承 page 層級的 `html[data-density]`(2026-04-21 canonical 定案)
|
|
114
|
+
className={cn(sheetVariants({ side }), className)}
|
|
115
|
+
{...props}
|
|
116
|
+
>
|
|
117
|
+
{children}
|
|
118
|
+
</SheetPrimitive.Content>
|
|
119
|
+
</SheetPortal>
|
|
120
|
+
))
|
|
121
|
+
SheetContent.displayName = SheetPrimitive.Content.displayName
|
|
122
|
+
|
|
123
|
+
// ── SheetHeader:SurfaceHeader + Close X(對齊 DialogHeader canonical)──────────
|
|
124
|
+
// 2026-05-18 audit gap fix:type 對齊 SurfaceHeaderProps,withTabs / lockDensity expose
|
|
125
|
+
// 給 consumer(per header-canonical.spec.md W1 跨 6 consumer 同契約)。Spread 早 forward
|
|
126
|
+
// 過去,只是 TS type 沒 expose 導致 consumer 不能 type-safe 用 `<SheetHeader withTabs>`。
|
|
127
|
+
const SheetHeader = React.forwardRef<
|
|
128
|
+
HTMLDivElement,
|
|
129
|
+
SurfaceHeaderProps
|
|
130
|
+
>(({ className, children, ...props }, ref) => (
|
|
131
|
+
// 2026-05-18:className 不再硬加 justify-between(同 DialogHeader 邏輯,避 column mode 破裂)。
|
|
132
|
+
<SurfaceHeader
|
|
133
|
+
ref={ref}
|
|
134
|
+
className={className}
|
|
135
|
+
{...props}
|
|
136
|
+
>
|
|
137
|
+
<div className="flex-1 min-w-0">{children}</div>
|
|
138
|
+
<SheetPrimitive.Close asChild>
|
|
139
|
+
{/* Dismiss X = native sm,SurfaceHeader 負 my trick 讓 layout 佔位 24 → chrome-header-height */}
|
|
140
|
+
<Button data-dismiss iconOnly dismiss size="sm" startIcon={XIcon} aria-label="關閉" />
|
|
141
|
+
</SheetPrimitive.Close>
|
|
142
|
+
</SurfaceHeader>
|
|
143
|
+
))
|
|
144
|
+
SheetHeader.displayName = "SheetHeader"
|
|
145
|
+
|
|
146
|
+
// ── SheetBody:flex-1 ScrollArea + chrome padding(對齊 DialogBody + ScrollArea canonical) ──
|
|
147
|
+
// 捲軸必用 ScrollArea(跨 OS 一致、不吃寬度)— 不自寫 overflow-y-auto。
|
|
148
|
+
// padding 搬進 viewport inner div:px-loose / pt-tight / pb-bottom。
|
|
149
|
+
// data-sheet-body:讓 SheetContent onOpenAutoFocus 找得到 body 第一個互動元素
|
|
150
|
+
//
|
|
151
|
+
// ── List-as-region 場景(menu / nav / settings list)──
|
|
152
|
+
// 不再提供 `flush` variant(2026-05-01 移除)。canonical = consumer 用 className override:
|
|
153
|
+
// `<SheetBody className="!px-0 !pt-0 !pb-0"><div className="py-2">{items}</div></SheetBody>`
|
|
154
|
+
// 詳 DialogBody comment + `tokens/layoutSpace/layoutSpace.spec.md`「List-as-region in overlay body」
|
|
155
|
+
// `className` forward 到 **inner content div**(非外層 ScrollArea wrapper)——
|
|
156
|
+
// consumer `<SheetBody className="flex flex-col gap-X">` 期望作用於 children 排列;
|
|
157
|
+
// 套在 ScrollArea 上會 0 效果(children 住 inner div),曾造成 Sheet form field 完全貼邊。
|
|
158
|
+
const SheetBody = React.forwardRef<
|
|
159
|
+
HTMLDivElement,
|
|
160
|
+
React.ComponentPropsWithoutRef<typeof ScrollArea>
|
|
161
|
+
>(({ className, children, ...props }, ref) => (
|
|
162
|
+
<ScrollArea ref={ref} data-sheet-body className="flex-1 min-h-0" {...props}>
|
|
163
|
+
<div
|
|
164
|
+
className={cn(
|
|
165
|
+
"px-[var(--layout-space-loose)] pt-[var(--layout-space-tight)] pb-[var(--layout-space-bottom)]",
|
|
166
|
+
className,
|
|
167
|
+
)}
|
|
168
|
+
>
|
|
169
|
+
{children}
|
|
170
|
+
</div>
|
|
171
|
+
</ScrollArea>
|
|
172
|
+
))
|
|
173
|
+
SheetBody.displayName = "SheetBody"
|
|
174
|
+
|
|
175
|
+
// ── SheetFooter:SurfaceFooter wrap 加 data-sheet-footer(autoFocus fallback target)──
|
|
176
|
+
const SheetFooter = React.forwardRef<
|
|
177
|
+
HTMLDivElement,
|
|
178
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
179
|
+
>(({ ...props }, ref) => <SurfaceFooter ref={ref} data-sheet-footer {...props} />)
|
|
180
|
+
SheetFooter.displayName = "SheetFooter"
|
|
181
|
+
|
|
182
|
+
const SheetTitle = React.forwardRef<
|
|
183
|
+
React.ElementRef<typeof SheetPrimitive.Title>,
|
|
184
|
+
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
|
185
|
+
>(({ className, ...props }, ref) => (
|
|
186
|
+
<SheetPrimitive.Title
|
|
187
|
+
ref={ref}
|
|
188
|
+
className={cn("text-body-lg font-medium truncate text-foreground", className)}
|
|
189
|
+
{...props}
|
|
190
|
+
/>
|
|
191
|
+
))
|
|
192
|
+
SheetTitle.displayName = SheetPrimitive.Title.displayName
|
|
193
|
+
|
|
194
|
+
const SheetDescription = React.forwardRef<
|
|
195
|
+
React.ElementRef<typeof SheetPrimitive.Description>,
|
|
196
|
+
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
|
197
|
+
>(({ className, ...props }, ref) => (
|
|
198
|
+
<SheetPrimitive.Description
|
|
199
|
+
ref={ref}
|
|
200
|
+
// title → description 間距 canonical:SheetTitle body-lg(16)+ desc body(14)→ reading-lg token
|
|
201
|
+
// (label tier 決定;對齊 Dialog canonical。Tailwind preflight reset h2/p margin=0 → 必顯式 mt)
|
|
202
|
+
className={cn("mt-[var(--item-gap-label-desc-reading-lg)] text-body text-fg-secondary", className)}
|
|
203
|
+
{...props}
|
|
204
|
+
/>
|
|
205
|
+
))
|
|
206
|
+
SheetDescription.displayName = SheetPrimitive.Description.displayName
|
|
207
|
+
|
|
208
|
+
// Story auto-compile metadata — Phase 1 mechanical migration(2026-04-24)
|
|
209
|
+
// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs
|
|
210
|
+
export const sheetMeta = {
|
|
211
|
+
component: 'Sheet',
|
|
212
|
+
family: null, // non-family composite / overlay / layout
|
|
213
|
+
variants: {
|
|
214
|
+
|
|
215
|
+
},
|
|
216
|
+
sizes: {
|
|
217
|
+
|
|
218
|
+
},
|
|
219
|
+
states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
|
|
220
|
+
tokens: {
|
|
221
|
+
bg: ['bg-surface-raised'],
|
|
222
|
+
fg: ['text-fg-secondary', 'text-foreground'],
|
|
223
|
+
ring: [],
|
|
224
|
+
},
|
|
225
|
+
} as const
|
|
226
|
+
|
|
227
|
+
export {
|
|
228
|
+
Sheet,
|
|
229
|
+
SheetPortal,
|
|
230
|
+
SheetOverlay,
|
|
231
|
+
SheetTrigger,
|
|
232
|
+
SheetClose,
|
|
233
|
+
SheetContent,
|
|
234
|
+
SheetHeader,
|
|
235
|
+
SheetBody,
|
|
236
|
+
SheetFooter,
|
|
237
|
+
SheetTitle,
|
|
238
|
+
SheetDescription,
|
|
239
|
+
sheetVariants,
|
|
240
|
+
}
|