アプリレールAppRailExperimental
左側の細いプライマリナビゲーションです。
プレビュー
選択中
ホーム
最近の更新、タスク、概要を確認します。
状態とバリエーション
主要ナビゲーション
アプリ全体の移動先をアイコンボタンで縦に並べます。アイコンのみのため、ツールチップと aria-label を必ず合わせます。
選択中
ホーム
最近の更新、タスク、概要を確認します。
少数アクション
アクションが少ない場合も、設定などの補助操作は下端に寄せて役割を分けます。
選択中
ホーム
最近の更新、タスク、概要を確認します。
プロパティ
表は横にスクロールできます
| プロパティ | 型 | 初期値 | 説明 |
|---|---|---|---|
| className | string | - | レール本体に追加するクラス名。 |
| children | React.ReactNode | - | レール内に配置するナビゲーションや操作。 |
使い方
import { AppRail, TooltipButton } from "@gunjo/ui"
import { IconBell as Bell, IconHome as Home, IconSearch as Search, IconSettings as Settings, IconUserCircle as UserRound } from "@tabler/icons-react"
import type { ReactNode } from "react"
import { useState } from "react"
function RailAction({
label,
children,
active,
onSelect,
}: {
label: string
children: ReactNode
active?: boolean
onSelect: () => void
}) {
return (
<TooltipButton
type="button"
variant="ghost"
size="icon"
tooltip={label}
tooltipSide="right"
tooltipOpenOnClick
aria-label={label}
aria-pressed={active}
onClick={onSelect}
className={[
"h-10 w-10 text-muted hover:bg-background/10 hover:text-background",
active ? "bg-background/20 text-background ring-1 ring-background/25" : "",
].join(" ")}
>
{children}
</TooltipButton>
)
}
export function AppRailExample() {
const items = [
{
key: "home",
label: "ホーム",
icon: <Home className="h-5 w-5" />,
title: "ホーム",
description: "最近の更新、タスク、概要を確認します。",
},
{
key: "search",
label: "検索",
icon: <Search className="h-5 w-5" />,
title: "検索",
description: "ワークスペース全体からドキュメントや操作を探します。",
},
{
key: "notifications",
label: "通知",
icon: <Bell className="h-5 w-5" />,
title: "通知",
description: "未読通知と重要な更新を確認します。",
},
{
key: "account",
label: "アカウント",
icon: <UserRound className="h-5 w-5" />,
title: "アカウント",
description: "プロフィール、チーム、請求情報を管理します。",
},
]
const settingsItem = {
key: "settings",
label: "設定",
icon: <Settings className="h-5 w-5" />,
title: "設定",
description: "表示、通知、権限などの環境設定を変更します。",
}
const allItems = [...items, settingsItem]
const [activeKey, setActiveKey] = useState(allItems[0].key)
const activeItem = allItems.find((item) => item.key === activeKey) ?? allItems[0]
return (
<div className="flex h-[340px] w-full max-w-3xl overflow-hidden rounded-md border bg-background">
<AppRail>
{items.map((item) => (
<RailAction
key={item.key}
label={item.label}
active={activeItem.key === item.key}
onSelect={() => setActiveKey(item.key)}
>
{item.icon}
</RailAction>
))}
<div className="mt-auto">
<RailAction
label={settingsItem.label}
active={activeItem.key === settingsItem.key}
onSelect={() => setActiveKey(settingsItem.key)}
>
{settingsItem.icon}
</RailAction>
</div>
</AppRail>
<main className="flex min-w-0 flex-1 items-center justify-center bg-secondary/50 p-6">
<div className="max-w-sm space-y-2 text-center">
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
選択中
</p>
<h3 className="text-2xl font-semibold tracking-tight">{activeItem.title}</h3>
<p className="text-sm leading-6 text-muted-foreground">
{activeItem.description}
</p>
</div>
</main>
</div>
)
}使用コンポーネント
関連コンポーネント
設計の判断(UIXHERO)
「いつ・なぜ使うか」の判断は、姉妹サイト UIXHERO の記事で解説しています。