Initial commit: HMDesignSystem baseline
This commit is contained in:
commit
b6a0a61103
486 files changed
+68432
No files matched your search
@@ -0,0 +1,155 @@
|
||||
import type { ReactNode } from "react"
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite"
|
||||
import {
|
||||
NavigationMenu,
|
||||
NavigationMenuContent,
|
||||
NavigationMenuIndicator,
|
||||
NavigationMenuItem,
|
||||
NavigationMenuLink,
|
||||
NavigationMenuList,
|
||||
NavigationMenuTrigger,
|
||||
} from "@hm-design/ui"
|
||||
import { StateBoard } from "@/components/story-board"
|
||||
import { STORY_KICKER, StoryPage, StoryPageHeader, StorySection } from "@/components/story-page"
|
||||
|
||||
// Navigation Menu is for destinations (links), not commands. The representative Story opens the real menus with hover, click or
|
||||
// keyboard; the same specimens also exist as Stories tagged `verification` (hidden from the sidebar). Title + description children
|
||||
// inside a content link are marked with `data-description` for the secondary text.
|
||||
|
||||
function Destination({ href, title, description, active }: { href: string; title: string; description?: string; active?: boolean }) {
|
||||
return (
|
||||
<NavigationMenuLink href={href} active={active}>
|
||||
<span>{title}</span>
|
||||
{description ? <span data-description="">{description}</span> : null}
|
||||
</NavigationMenuLink>
|
||||
)
|
||||
}
|
||||
|
||||
function Specimen({ viewport = true }: { viewport?: boolean }) {
|
||||
return (
|
||||
<NavigationMenu viewport={viewport}>
|
||||
<NavigationMenuList>
|
||||
<NavigationMenuItem>
|
||||
<NavigationMenuTrigger>제품</NavigationMenuTrigger>
|
||||
<NavigationMenuContent>
|
||||
<ul className="sm:w-[min(360px,calc(100cqw-18px))]" style={{ display: "grid", gap: 4 }}>
|
||||
<li>
|
||||
<Destination href="#analytics" title="분석" description="노선과 시설물 데이터를 한눈에 확인합니다." />
|
||||
</li>
|
||||
<li>
|
||||
<Destination href="#maps" title="지도" description="공간 정보를 지도 위에서 관리합니다." />
|
||||
</li>
|
||||
<li>
|
||||
<Destination href="#reports" title="리포트" description="점검 결과를 보고서로 만듭니다." />
|
||||
</li>
|
||||
</ul>
|
||||
</NavigationMenuContent>
|
||||
</NavigationMenuItem>
|
||||
<NavigationMenuItem>
|
||||
<NavigationMenuTrigger>자료</NavigationMenuTrigger>
|
||||
<NavigationMenuContent>
|
||||
<ul className="sm:w-[min(300px,calc(100cqw-18px))]" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 4 }}>
|
||||
<li>
|
||||
<Destination href="#docs" title="문서" />
|
||||
</li>
|
||||
<li>
|
||||
<Destination href="#guides" title="가이드" />
|
||||
</li>
|
||||
<li>
|
||||
<Destination href="#api" title="API" />
|
||||
</li>
|
||||
<li>
|
||||
<Destination href="#blog" title="블로그" />
|
||||
</li>
|
||||
</ul>
|
||||
</NavigationMenuContent>
|
||||
</NavigationMenuItem>
|
||||
<NavigationMenuItem>
|
||||
<NavigationMenuLink href="#company" active>
|
||||
회사
|
||||
</NavigationMenuLink>
|
||||
</NavigationMenuItem>
|
||||
<NavigationMenuItem>
|
||||
<NavigationMenuLink href="#contact">문의</NavigationMenuLink>
|
||||
</NavigationMenuItem>
|
||||
<NavigationMenuItem>
|
||||
<NavigationMenuTrigger disabled>준비 중</NavigationMenuTrigger>
|
||||
</NavigationMenuItem>
|
||||
</NavigationMenuList>
|
||||
{viewport ? <NavigationMenuIndicator /> : null}
|
||||
</NavigationMenu>
|
||||
)
|
||||
}
|
||||
|
||||
// Size specimens to their review area (including the panel's 8px padding + 1px border on each side).
|
||||
// Mobile uses the content's natural minimum width instead of a fixed desktop specimen width.
|
||||
const frame = (node: ReactNode) => (
|
||||
<div
|
||||
style={{ minHeight: 256, width: "100%", containerType: "inline-size" }}
|
||||
className="max-md:[&_[data-viewport=false]_[data-slot=navigation-menu-content]]:absolute"
|
||||
>
|
||||
{node}
|
||||
</div>
|
||||
)
|
||||
|
||||
const meta = { title: "Components/Navigation/Navigation Menu", component: NavigationMenu, parameters: { layout: "padded" } } satisfies Meta<typeof NavigationMenu>
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const All: Story = {
|
||||
name: "Navigation Menu",
|
||||
parameters: { layout: "fullscreen", controls: { disable: true } },
|
||||
render: () => (
|
||||
<StoryPage>
|
||||
<StoryPageHeader
|
||||
kicker={STORY_KICKER.components}
|
||||
title="Navigation Menu"
|
||||
description="목적지(링크)로 이동하는 메뉴입니다. 명령 실행에는 쓰지 않습니다. hover, 클릭 또는 키보드로 엽니다."
|
||||
/>
|
||||
<StorySection title="Overview">
|
||||
<StateBoard
|
||||
min={520}
|
||||
states={[
|
||||
{ id: "viewport", label: "Viewport (default)", note: "제품 / 자료는 content, 회사는 현재 위치(active), 문의는 일반 링크, 준비 중은 disabled trigger", children: frame(<Specimen />) },
|
||||
]}
|
||||
/>
|
||||
</StorySection>
|
||||
<StorySection title="Variants">
|
||||
<StateBoard
|
||||
min={520}
|
||||
states={[
|
||||
{ id: "no-viewport", label: "viewport={false}", note: "각 content가 자기 trigger 아래에 열립니다", children: frame(<Specimen viewport={false} />) },
|
||||
]}
|
||||
/>
|
||||
</StorySection>
|
||||
</StoryPage>
|
||||
),
|
||||
}
|
||||
|
||||
export const Default: Story = { tags: ["verification"], render: () => frame(<Specimen />) }
|
||||
export const NoViewport: Story = { tags: ["verification"], name: "No Viewport", render: () => frame(<Specimen viewport={false} />) }
|
||||
|
||||
// Three enabled triggers with different widths exercise first / middle / last offsets in both positioning modes.
|
||||
export const IndicatorAlignment: Story = {
|
||||
tags: ["verification"],
|
||||
render: () => (
|
||||
<StateBoard min={520} states={[true, false].map((viewport) => ({
|
||||
id: viewport ? "viewport" : "no-viewport",
|
||||
label: `Indicator alignment · viewport=${viewport}`,
|
||||
children: frame(
|
||||
<NavigationMenu viewport={viewport}>
|
||||
<NavigationMenuList>
|
||||
{["제품", "기술 자료", "지원 센터"].map((label) => (
|
||||
<NavigationMenuItem key={label}>
|
||||
<NavigationMenuTrigger>{label}</NavigationMenuTrigger>
|
||||
<NavigationMenuContent><Destination href="#verification" title={`${label} 안내`} /></NavigationMenuContent>
|
||||
</NavigationMenuItem>
|
||||
))}
|
||||
</NavigationMenuList>
|
||||
{viewport ? <NavigationMenuIndicator /> : null}
|
||||
</NavigationMenu>
|
||||
),
|
||||
}))} />
|
||||
),
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user