NavigationMenu
사이트의 내비게이션입니다. 목적지들이 한 줄로 놓이고, 그중 일부는 더 많은 목적지가 담긴 패널을 엽니다. 모든 행이 진짜 링크이며, 그래서 링크 목록에도, 상태 표시줄에도, 크롤러의 색인에도 들어갑니다.
tsx
import { NavigationMenu, NavigationMenuItem, NavigationMenuLink } from 'neba';
<NavigationMenu aria-label="Main">
<NavigationMenuItem label="Product">
<NavigationMenuLink href="/analytics" title="Analytics" description="Every number." />
</NavigationMenuItem>
<NavigationMenuItem label="Pricing" href="/pricing" />
</NavigationMenu>;Props
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| size공통 | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | 항목의 높이와 타입 스케일. 패널 안의 링크까지 함께 따라갑니다 |
| color공통 | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'primary' | 열린 항목과 패널의 가장자리가 띠는 색 역할 |
| density공통 | 'default' | 'compact' | 'default' | 가로 여백만 바꿉니다 |
| orientation공통 | 'horizontal' | 'vertical' | 'horizontal' | 줄이 이어지는 방향. vertical은 패널이 옆으로 열리는 내비게이션 레일이 됩니다 |
| value | string | null | — | 어느 항목의 패널이 열려 있는지. nullish면 닫힌 상태입니다 |
| defaultValue | string | null | — | 처음에 열려 있는 항목 (uncontrolled) |
| onValueChange | (value: string | null) => void | — | 열린 항목이 바뀔 때마다 호출됩니다 |
| delay | number | 50 | 패널이 열리기까지 포인터가 머물러야 하는 시간 (ms) |
| closeDelay | number | 50 | 포인터가 떠난 뒤 패널이 남아 있는 시간 (ms) |
| sideOffset | number | 8 | 줄과 패널 사이의 거리 (px) |
| children | ReactNode | — | NavigationMenuItem들 |
<nav>의 모든 속성이 color를 제외하고 그대로 전달됩니다.
Menu와의 차이는 행이 무엇인가에 있습니다. 메뉴는 액션을 담으므로 행이 menuitem입니다. 이쪽은 링크를 담으므로 <a>로 가득 찬 <nav>입니다. 행이 무언가를 하면 Menu를, 어딘가로 가면 이 컴포넌트를 쓰세요.
NavigationMenuItem
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| label * | ReactNode | — | 줄에 놓이는 단어 |
| href | string | — | 패널을 여는 대신 그냥 링크가 되게 합니다. href가 있고 children이 없는 항목은 목적지이며, 그렇게 안내됩니다 |
| target | string | — | 링크가 열리는 곳. href가 없으면 무시됩니다. 이 탭이 아닌 곳으로 열면 rel에 noopener noreferrer가 더해집니다 |
| rel | string | — | 링크의 rel. 덮어쓰는 것이 아니라 합쳐집니다. nofollow를 쓴다고 새 탭의 보호가 사라지지는 않습니다 |
| startIcon | ReactNode | — | 단어 앞의 내용 |
| value | string | — | controlled 메뉴에서 이 항목을 식별하는 값 |
| disabled | boolean | false | 사용 불가. 단어는 줄에 남고 아무것도 열지 않습니다 |
| columns | number | 1 | 패널이 링크를 몇 개의 열로 배치할지 |
| children | ReactNode | — | 패널의 내용. 보통 NavigationMenuLink들입니다 |
NavigationMenuLink
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| href * | string | — | 가는 곳 |
| title * | ReactNode | — | 행의 이름 |
| description | ReactNode | — | 그 아래 한 줄. 한 단계 아래 스케일에 흐린 색 |
| startIcon | ReactNode | — | 제목 앞의 글리프 |
예시
패널이 있는 항목과 없는 항목
children이 있는 항목은 trigger와 패널이 되고, href만 있고 children이 없는 항목은 링크가 됩니다. 두 가지는 스크린 리더에 다르게 전달됩니다.
columns
패널이 링크를 몇 개의 열로 배치할지 정합니다. 짧은 목록은 한 열이 맞고, 지역이나 제품이 많은 넓은 메뉴는 두세 열을 원합니다.
tsx
import { NavigationMenu, NavigationMenuItem, NavigationMenuLink } from 'neba';
export default function NavigationMenuColumns() {
return (
<NavigationMenu aria-label="Regions" size="sm">
<NavigationMenuItem label="One column">
<NavigationMenuLink href="#seoul" title="Seoul" />
<NavigationMenuLink href="#tokyo" title="Tokyo" />
<NavigationMenuLink href="#osaka" title="Osaka" />
</NavigationMenuItem>
<NavigationMenuItem label="Three columns" columns={3}>
<NavigationMenuLink href="#seoul" title="Seoul" description="ap-northeast-2" />
<NavigationMenuLink href="#tokyo" title="Tokyo" description="ap-northeast-1" />
<NavigationMenuLink href="#osaka" title="Osaka" description="ap-northeast-3" />
<NavigationMenuLink href="#frankfurt" title="Frankfurt" description="eu-central-1" />
<NavigationMenuLink href="#dublin" title="Dublin" description="eu-west-1" />
<NavigationMenuLink href="#virginia" title="Virginia" description="us-east-1" />
</NavigationMenuItem>
</NavigationMenu>
);
}orientation
vertical은 항목을 세로로 쌓고 패널을 옆으로 엽니다. 바가 아니라 내비게이션 레일이 됩니다.
tsx
import { NavigationMenu, NavigationMenuItem, NavigationMenuLink } from 'neba';
export default function NavigationMenuOrientation() {
return (
<NavigationMenu orientation="vertical" size="sm" aria-label="Sections" className="w-44">
<NavigationMenuItem label="Overview" href="#overview" />
<NavigationMenuItem label="Deploys">
<NavigationMenuLink href="#production" title="Production" />
<NavigationMenuLink href="#preview" title="Preview" />
</NavigationMenuItem>
<NavigationMenuItem label="Settings">
<NavigationMenuLink href="#general" title="General" />
<NavigationMenuLink href="#members" title="Members" />
</NavigationMenuItem>
</NavigationMenu>
);
}header 안에서
tsx
import {
AppLogo,
Button,
Header,
NavigationMenu,
NavigationMenuItem,
NavigationMenuLink
} from 'neba';
export default function NavigationMenuHeader() {
return (
<Header
className="w-full"
brand={<AppLogo name="Neba" src="/128x128.png" size="sm" />}
actions={
<Button size="sm" variant="outline">
Sign in
</Button>
}
>
<NavigationMenu size="sm" aria-label="Main">
<NavigationMenuItem label="Product">
<NavigationMenuLink href="#analytics" title="Analytics" description="Every number." />
<NavigationMenuLink href="#pipelines" title="Pipelines" description="Build and ship." />
</NavigationMenuItem>
<NavigationMenuItem label="Docs" href="#docs" />
<NavigationMenuItem label="Pricing" href="#pricing" />
</NavigationMenu>
</Header>
);
}접근성
- 진짜
<nav>로 렌더링됩니다. 한 페이지에 nav가 둘 이상이면aria-label을 주세요. - 모든 목적지가
<a href>이므로 새 탭에서 열고, 주소를 복사하고, 크롤러가 따라가고, 스크린 리더의 링크 목록에서 도달할 수 있습니다. - 키보드로 조작합니다. 방향키로 항목 사이와 열린 패널 안을 오가고, Escape로 닫습니다.
- 패널은 항목 사이를 이동할 때 닫혔다 열리는 대신 크기를 바꿉니다. 그래서 줄을 가로지르는 동작이 하나의 표면처럼 읽힙니다.