Initial commit: HMDesignSystem baseline
This commit is contained in:
commit
b6a0a61103
486 files changed
+68432
No files matched your search
@@ -0,0 +1,114 @@
|
||||
import { useState } from "react"
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite"
|
||||
import {
|
||||
ContextMenu,
|
||||
ContextMenuCheckboxItem,
|
||||
ContextMenuContent,
|
||||
ContextMenuGroup,
|
||||
ContextMenuItem,
|
||||
ContextMenuLabel,
|
||||
ContextMenuRadioGroup,
|
||||
ContextMenuRadioItem,
|
||||
ContextMenuSeparator,
|
||||
ContextMenuShortcut,
|
||||
ContextMenuSub,
|
||||
ContextMenuSubContent,
|
||||
ContextMenuSubTrigger,
|
||||
ContextMenuTrigger,
|
||||
} from "@hm-design/ui"
|
||||
import { STORY_KICKER, StoryPage, StoryPageHeader, StorySection } from "@/components/story-page"
|
||||
|
||||
// Context Menu opens from pointer context (right click, the context-menu key / Shift+F10, long press) on its trigger area.
|
||||
// The representative Story is a target area: right click it. Radix owns keyboard navigation, focus return and Escape.
|
||||
|
||||
function Full() {
|
||||
const [showStatus, setShowStatus] = useState(true)
|
||||
const [showPanel, setShowPanel] = useState(false)
|
||||
const [position, setPosition] = useState("bottom")
|
||||
return (
|
||||
<ContextMenu>
|
||||
{/* tabIndex lets keyboard users focus the area and open the menu with Shift+F10 / the context-menu key; Radix Trigger is a plain span. */}
|
||||
<ContextMenuTrigger tabIndex={0} className="flex h-40 w-80 items-center justify-center rounded-md border border-dashed text-sm text-muted-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring">
|
||||
이 영역에서 오른쪽 클릭
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent className="w-56">
|
||||
<ContextMenuLabel>파일</ContextMenuLabel>
|
||||
<ContextMenuGroup>
|
||||
<ContextMenuItem>
|
||||
열기 <ContextMenuShortcut>⌘O</ContextMenuShortcut>
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem>
|
||||
이름 바꾸기 <ContextMenuShortcut>F2</ContextMenuShortcut>
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem disabled>붙여넣기 (사용 불가)</ContextMenuItem>
|
||||
</ContextMenuGroup>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuLabel>보기</ContextMenuLabel>
|
||||
<ContextMenuCheckboxItem checked={showStatus} onCheckedChange={setShowStatus}>
|
||||
상태 표시줄
|
||||
</ContextMenuCheckboxItem>
|
||||
<ContextMenuCheckboxItem checked={showPanel} onCheckedChange={setShowPanel}>
|
||||
패널
|
||||
</ContextMenuCheckboxItem>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuLabel>위치</ContextMenuLabel>
|
||||
<ContextMenuRadioGroup value={position} onValueChange={setPosition}>
|
||||
<ContextMenuRadioItem value="top">상단</ContextMenuRadioItem>
|
||||
<ContextMenuRadioItem value="bottom">하단</ContextMenuRadioItem>
|
||||
<ContextMenuRadioItem value="right">오른쪽</ContextMenuRadioItem>
|
||||
</ContextMenuRadioGroup>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuSub>
|
||||
<ContextMenuSubTrigger>더 보기</ContextMenuSubTrigger>
|
||||
<ContextMenuSubContent>
|
||||
<ContextMenuItem>이메일로 공유</ContextMenuItem>
|
||||
<ContextMenuItem>링크 복사</ContextMenuItem>
|
||||
</ContextMenuSubContent>
|
||||
</ContextMenuSub>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuItem variant="destructive">삭제</ContextMenuItem>
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
)
|
||||
}
|
||||
|
||||
const meta = { title: "Components/Overlay/Context Menu", component: ContextMenu, parameters: { layout: "centered" } } satisfies Meta<typeof ContextMenu>
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
// Representative Story: right click the area to open the full menu (item, disabled, separator, shortcut, checkbox, radio group, sub menu, destructive).
|
||||
export const All: Story = {
|
||||
name: "Context Menu",
|
||||
parameters: { layout: "fullscreen", controls: { disable: true } },
|
||||
render: () => (
|
||||
<StoryPage>
|
||||
<StoryPageHeader
|
||||
kicker={STORY_KICKER.components}
|
||||
title="Context Menu"
|
||||
description="영역에서 오른쪽 클릭, 컨텍스트 메뉴 키 / Shift+F10, 길게 누르기로 여는 메뉴입니다."
|
||||
/>
|
||||
<StorySection title="Overview" description="항목 · Disabled · 단축키 · Checkbox · Radio Group · 하위 메뉴 · 위험 항목을 한 메뉴에서 확인합니다. 점선 영역에서 오른쪽 클릭합니다.">
|
||||
<Full />
|
||||
</StorySection>
|
||||
</StoryPage>
|
||||
),
|
||||
}
|
||||
|
||||
// Verification Story: opens the menu at the area center on load (synthetic contextmenu event), hidden from the sidebar (tag `verification`).
|
||||
export const Open: Story = {
|
||||
tags: ["verification"],
|
||||
parameters: { layout: "fullscreen" },
|
||||
render: () => (
|
||||
<div className="flex min-h-[560px] justify-center p-8">
|
||||
<Full />
|
||||
</div>
|
||||
),
|
||||
play: async ({ canvasElement }) => {
|
||||
const area = canvasElement.querySelector<HTMLElement>("[data-slot='context-menu-trigger']")
|
||||
if (!area) return
|
||||
const r = area.getBoundingClientRect()
|
||||
area.dispatchEvent(
|
||||
new MouseEvent("contextmenu", { bubbles: true, cancelable: true, clientX: r.left + r.width / 2, clientY: r.top + r.height / 2, button: 2 }),
|
||||
)
|
||||
},
|
||||
}
|
||||
Reference in new issue
Block a user