Sidebar
サイドバーナビゲーションコンポーネント。折りたたみ、サブメニュー、ユーザーメニューに対応。
インポート
'use client'
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarProvider,
SidebarRail,
SidebarSeparator,
SidebarTrigger,
SidebarInset,
} from '@caroainc/ui-components/client'個別サブパス(バンドルサイズを抑えたい場合):
'use client'
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarProvider,
SidebarRail,
SidebarSeparator,
SidebarTrigger,
SidebarInset,
} from '@caroainc/ui-components/sidebar'基本的な使い方
<SidebarProvider>
<Sidebar>
<SidebarHeader>
<div className="flex items-center gap-2 px-2">
<div className="w-8 h-8 rounded-md bg-primary flex items-center justify-center">
<span className="text-primary-foreground text-sm font-bold">C</span>
</div>
<span className="font-semibold">Caroa App</span>
</div>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild isActive>
<a href="/">
<Icon name="Home" size="sm" />
<span>ホーム</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="/dashboard">
<Icon name="LayoutDashboard" size="sm" />
<span>ダッシュボード</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
<p className="text-xs text-muted-foreground">v1.0.0</p>
</SidebarFooter>
</Sidebar>
<main>メインコンテンツ</main>
</SidebarProvider>グループラベル付き
SidebarGroupLabelでメニューをセクションに分けられます。
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>メニュー</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="/"><Icon name="Home" size="sm" />ホーム</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
<SidebarSeparator />
<SidebarGroup>
<SidebarGroupLabel>設定</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="/settings"><Icon name="Settings" size="sm" />設定</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>サブメニュー付き
Collapsibleと組み合わせて折りたたみ可能なサブメニューを作成できます。
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '@caroainc/ui-components/client'
<SidebarMenu>
<Collapsible open={isOpen} onOpenChange={setIsOpen}>
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton>
<Icon name="Folder" size="sm" />
<span>プロジェクト</span>
<Icon
name="ChevronRight"
size="sm"
className={`ml-auto transition-transform ${isOpen ? 'rotate-90' : ''}`}
/>
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
<SidebarMenuSubItem>
<SidebarMenuSubButton asChild>
<a href="/projects/a">プロジェクトA</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
<SidebarMenuSubItem>
<SidebarMenuSubButton asChild>
<a href="/projects/b">プロジェクトB</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
</SidebarMenu>ユーザーメニュー付き
フッターにユーザー情報とドロップダウンメニューを配置できます。
<SidebarFooter>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton className="w-full">
<Avatar className="h-6 w-6">
<AvatarImage src="/avatar.png" alt="User" />
<AvatarFallback>U</AvatarFallback>
</Avatar>
<span>山田太郎</span>
<Icon name="ChevronsUpDown" size="sm" className="ml-auto" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent side="top" className="w-[--radix-dropdown-menu-trigger-width]">
<DropdownMenuItem>
<Icon name="User" size="sm" />
プロフィール
</DropdownMenuItem>
<DropdownMenuItem>
<Icon name="Settings" size="sm" />
設定
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>
<Icon name="LogOut" size="sm" />
ログアウト
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarFooter>折りたたみ可能
SidebarTriggerとSidebarRailで折りたたみ機能を追加できます。Cmd+B(Mac)/Ctrl+B(Windows)のキーボードショートカットにも対応。
<SidebarProvider>
<Sidebar>
<SidebarHeader>
<div className="flex items-center gap-2 px-2">
<Logo />
<span className="group-data-[collapsible=icon]:hidden">Caroa App</span>
</div>
</SidebarHeader>
<SidebarContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild tooltip="ホーム">
<a href="/"><Icon name="Home" size="sm" />ホーム</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarContent>
<SidebarRail />
</Sidebar>
<SidebarInset>
<header className="flex h-14 items-center gap-4 border-b px-6">
<SidebarTrigger />
<span>タイトル</span>
</header>
<main>コンテンツ</main>
</SidebarInset>
</SidebarProvider>インセットバリアント(カード風レイアウト)
variant="inset"でメインコンテンツが白いカードとして浮いて見えるレイアウトになります。サイドバーの背景色と白いメインエリアのコントラストで、コンテンツが際立ちます。
<SidebarProvider>
<Sidebar variant="inset" collapsible="none">
<SidebarHeader>{/* ロゴ */}</SidebarHeader>
<SidebarContent>{/* メニュー */}</SidebarContent>
</Sidebar>
<SidebarInset>
<header className="flex h-14 items-center gap-4 border-b px-6">
<span className="font-semibold">ダッシュボード</span>
</header>
<main className="p-6">{/* コンテンツ */}</main>
</SidebarInset>
</SidebarProvider>フローティングバリアント
variant="floating"で浮いているようなスタイルになります。
<SidebarProvider>
<Sidebar variant="floating">
{/* ... */}
</Sidebar>
<main>コンテンツ</main>
</SidebarProvider>コンポーネント構成
| コンポーネント | 説明 |
|---|---|
SidebarProvider | サイドバーの状態管理を提供 |
Sidebar | サイドバーのルートコンテナ |
SidebarHeader | ヘッダー部分(ロゴなど) |
SidebarContent | メインコンテンツエリア |
SidebarFooter | フッター部分(ユーザーメニューなど) |
SidebarGroup | メニューのグループ化 |
SidebarGroupLabel | グループのラベル |
SidebarGroupContent | グループ内のコンテンツ |
SidebarMenu | メニューリストのコンテナ |
SidebarMenuItem | メニューアイテム |
SidebarMenuButton | クリック可能なメニューボタン |
SidebarMenuSub | サブメニューのコンテナ |
SidebarMenuSubItem | サブメニューアイテム |
SidebarMenuSubButton | サブメニューボタン |
SidebarSeparator | 区切り線 |
SidebarTrigger | 折りたたみトリガーボタン |
SidebarRail | ドラッグで折りたたむためのレール |
SidebarInset | メインコンテンツエリア(サイドバーの隣) |
Props
SidebarProvider
| Prop | Type | Default | Description |
|---|---|---|---|
defaultOpen | boolean | true | デフォルトの開閉状態 |
open | boolean | - | 開閉状態(制御コンポーネント用) |
onOpenChange | (open: boolean) => void | - | 開閉状態変更時のコールバック |
Sidebar
| Prop | Type | Default | Description |
|---|---|---|---|
side | 'left' | 'right' | 'left' | サイドバーの位置 |
variant | 'sidebar' | 'floating' | 'inset' | 'sidebar' | サイドバーのスタイル |
collapsible | 'offcanvas' | 'icon' | 'none' | 'offcanvas' | 折りたたみ方式 |
aria-label | string | 'サイドバー' | ランドマーク(role="navigation")のアクセシブルネーム |
SidebarMenuButton
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | 子要素をボタンとしてレンダリング |
isActive | boolean | false | アクティブ状態 |
tooltip | string | TooltipContentProps | - | 折りたたみ時に表示するツールチップ |
variant | 'default' | 'outline' | 'default' | ボタンのスタイル |
size | 'default' | 'sm' | 'lg' | 'default' | ボタンのサイズ |
キーボードショートカット
| キー | 動作 |
|---|---|
Cmd+B / Ctrl+B | サイドバーの開閉をトグル |
モバイル対応
モバイルでは自動的にSheetコンポーネントを使用してオーバーレイ表示になります。useIsMobileフックで画面サイズを検出しています。
// useSidebarフックで状態にアクセス
const { isMobile, state, toggleSidebar } = useSidebar()サイドバー幅のカスタマイズ
SidebarProviderのstyleで--sidebar-width / --sidebar-width-iconを上書きすると、デフォルト幅(16rem / 3rem)を変更できます。
<SidebarProvider
style={
{
'--sidebar-width': '20rem',
'--sidebar-width-icon': '4rem',
} as React.CSSProperties
}
>
<Sidebar>{/* ... */}</Sidebar>
<main>コンテンツ</main>
</SidebarProvider>Next.jsでのCookie連携(開閉状態の永続化)
SidebarProviderは開閉状態が変わるたびにsidebar_state Cookie(7日間有効)へ自動保存します。サーバー側でCookieを読み、初期状態としてdefaultOpenに渡すことでリロード時のちらつきを防げます。
// app/layout.tsx(Server Component)
import { cookies } from 'next/headers'
import { SidebarProvider, Sidebar, SidebarInset } from '@caroainc/ui-components/client'
export default async function Layout({ children }: { children: React.ReactNode }) {
const cookieStore = await cookies()
const defaultOpen = cookieStore.get('sidebar_state')?.value !== 'false'
return (
<SidebarProvider defaultOpen={defaultOpen}>
<Sidebar>{/* ... */}</Sidebar>
<SidebarInset>{children}</SidebarInset>
</SidebarProvider>
)
}