- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- Marker
- Message
- Message Scroller
- Native Select
- Pagination
- Popover
- Progress
- Questionnaire
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
- Typography
"use client"
import * as React from "react"アイコン表示に折りたたまれるサイドバー。
サイドバーは、構築が最も複雑なコンポーネントの一つです。あらゆるアプリケーションの中核を担い、多くの可動部分を含むことがよくあります。
今では、それを支える確かな基盤が整いました。組み合わせ可能で、テーマ設定にも対応し、自由にカスタマイズできます。
インストール#
pnpm dlx shadcn@latest add sidebar
使い方#
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
import { AppSidebar } from "@/components/app-sidebar"
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<SidebarProvider>
<AppSidebar />
<main>
<SidebarTrigger />
{children}
</main>
</SidebarProvider>
)
}import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarHeader,
} from "@/components/ui/sidebar"
export function AppSidebar() {
return (
<Sidebar>
<SidebarHeader />
<SidebarContent>
<SidebarGroup />
<SidebarGroup />
</SidebarContent>
<SidebarFooter />
</Sidebar>
)
}構成#
以下の構成で Sidebar レイアウトを作成します。
SidebarProvider
├── Sidebar
│ ├── SidebarHeader
│ ├── SidebarContent
│ │ ├── SidebarGroup
│ │ │ ├── SidebarGroupLabel
│ │ │ ├── SidebarGroupAction
│ │ │ ├── SidebarGroupContent
│ │ │ └── SidebarMenu
│ │ │ ├── SidebarMenuItem
│ │ │ │ ├── SidebarMenuButton
│ │ │ │ ├── SidebarMenuAction
│ │ │ │ └── SidebarMenuBadge
│ │ │ └── SidebarMenuItem
│ │ │ ├── SidebarMenuButton
│ │ │ └── SidebarMenuSub
│ │ │ ├── SidebarMenuSubItem
│ │ │ └── SidebarMenuSubItem
│ │ └── SidebarGroup
│ │ └── SidebarMenu
│ │ ├── SidebarMenuItem
│ │ └── SidebarMenuItem
│ ├── SidebarFooter
│ └── SidebarRail
├── SidebarInset
└── SidebarTrigger構造#
- SidebarProvider — 開閉状態を管理し、子コンポーネントにサイドバーのコンテキストを提供します。
- Sidebar — 折りたたみ可能なメインのサイドバーパネルです。
- SidebarHeader — 上部に固定表示され、ブランディングやタイトル、ワークスペース切り替えなどに使用します。
- SidebarFooter — 下部に固定表示され、ユーザーメニューや設定、アクションなどに使用します。
- SidebarContent — ヘッダーとフッターの間にあるスクロール可能な領域です。
- SidebarGroup — ラベル、アクション、コンテンツ領域を任意で持つ、関連するナビゲーションをグループ化します。
- SidebarMenu / SidebarMenuItem — リンク、バッジ、アクション、ネストされたサブメニューのためのメニュー構造です。
- SidebarRail — 該当する場合にサイドバーの幅を調整するためのリサイズハンドルです。
- SidebarInset —
insetバリアントを使用する場合にメインコンテンツをラップします。 - SidebarTrigger — サイドバーの開閉を切り替えるコントロールです。
SidebarProvider#
SidebarProvider コンポーネントは、Sidebar コンポーネントにサイドバーのコンテキストを提供するために使用します。アプリケーション全体を必ず SidebarProvider コンポーネントでラップしてください。
プロパティ#
| Name | Type | Description |
|---|---|---|
defaultOpen | boolean | サイドバーのデフォルトの開閉状態です。 |
open | boolean | サイドバーの開閉状態です(制御時)。 |
onOpenChange | (open: boolean) => void | サイドバーの開閉状態を設定します(制御時)。 |
幅#
アプリケーション内にサイドバーが 1 つしかない場合は、sidebar.tsx の SIDEBAR_WIDTH と SIDEBAR_WIDTH_MOBILE 変数を使用してサイドバーの幅を設定できます。
const SIDEBAR_WIDTH = "16rem"
const SIDEBAR_WIDTH_MOBILE = "18rem"アプリケーション内に複数のサイドバーがある場合は、style プロップで --sidebar-width と --sidebar-width-mobile の CSS 変数を使用できます。
<SidebarProvider
style={
{
"--sidebar-width": "20rem",
"--sidebar-width-mobile": "20rem",
} as React.CSSProperties
}
>
<Sidebar />
</SidebarProvider>キーボードショートカット#
サイドバーを開閉するには、Mac では cmd+b、Windows では ctrl+b のキーボードショートカットを使用します。
const SIDEBAR_KEYBOARD_SHORTCUT = "b"Sidebar#
Sidebar は、折りたたみ可能なサイドバーをレンダリングするためのメインコンポーネントです。
プロパティ#
| Property | Type | Description |
|---|---|---|
side | left or right | サイドバーの表示位置です。 |
variant | sidebar, floating, or inset | サイドバーのバリアントです。 |
collapsible | offcanvas, icon, or none | サイドバーの折りたたみ状態です。 |
| Prop | Description |
|---|---|
offcanvas | 左右からスライドして表示される、折りたたみ可能なサイドバーです。 |
icon | アイコン表示に折りたたまれるサイドバーです。 |
none | 折りたたみができないサイドバーです。 |
注: inset バリアントを使用する場合は、メインコンテンツを必ず
SidebarInset コンポーネントでラップしてください。
<SidebarProvider>
<Sidebar variant="inset" />
<SidebarInset>
<main>{children}</main>
</SidebarInset>
</SidebarProvider>useSidebar#
useSidebar フックは、サイドバーを制御するために使用します。
import { useSidebar } from "@/components/ui/sidebar"
export function AppSidebar() {
const {
state,
open,
setOpen,
openMobile,
setOpenMobile,
isMobile,
toggleSidebar,
} = useSidebar()
}| Property | Type | Description |
|---|---|---|
state | expanded or collapsed | サイドバーの現在の状態です。 |
open | boolean | サイドバーが開いているかどうかです。 |
setOpen | (open: boolean) => void | サイドバーの開閉状態を設定します。 |
openMobile | boolean | モバイルでサイドバーが開いているかどうかです。 |
setOpenMobile | (open: boolean) => void | モバイルでのサイドバーの開閉状態を設定します。 |
isMobile | boolean | サイドバーがモバイル表示かどうかです。 |
toggleSidebar | () => void | サイドバーの開閉を切り替えます。デスクトップ・モバイル両対応です。 |
SidebarHeader#
SidebarHeader コンポーネントを使用して、サイドバーに固定ヘッダーを追加します。
<Sidebar>
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenuTrigger>
<SidebarMenuButton>
Select Workspace
<ChevronDown className="ml-auto" />
</SidebarMenuButton>
<DropdownMenu className="w-[--trigger-width]">
<DropdownMenuItem>
<span>Acme Inc</span>
</DropdownMenuItem>
</DropdownMenu>
</DropdownMenuTrigger>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
</Sidebar>SidebarFooter#
SidebarFooter コンポーネントを使用して、サイドバーに固定フッターを追加します。
<Sidebar>
<SidebarFooter>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton>
<User2 /> Username
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarFooter>
</Sidebar>SidebarContent#
SidebarContent コンポーネントは、サイドバーのコンテンツをラップするために使用します。ここに SidebarGroup コンポーネントを追加します。スクロール可能です。
<Sidebar>
<SidebarContent>
<SidebarGroup />
<SidebarGroup />
</SidebarContent>
</Sidebar>SidebarGroup#
SidebarGroup コンポーネントを使用して、サイドバー内にセクションを作成します。
SidebarGroup は、SidebarGroupLabel、SidebarGroupContent、そして任意で SidebarGroupAction を持ちます。
<SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupAction>
<Plus /> <span className="sr-only">Add Project</span>
</SidebarGroupAction>
<SidebarGroupContent></SidebarGroupContent>
</SidebarGroup>SidebarGroup を折りたたみ可能にするには、Collapsible でラップします。
<Collapsible defaultExpanded className="group/collapsible">
<SidebarGroup>
<SidebarGroupLabel elementType={CollapsibleTrigger}>
Help
<ChevronDown className="ml-auto transition-transform group-data-expanded/collapsible:rotate-180" />
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent />
</CollapsibleContent>
</SidebarGroup>
</Collapsible>SidebarMenu#
SidebarMenu コンポーネントは、SidebarGroup 内にメニューを構築するために使用します。
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton href={project.url}>
<project.icon />
<span>{project.name}</span>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>SidebarMenuButton#
SidebarMenuButton コンポーネントは、SidebarMenuItem 内にメニューボタンをレンダリングするために使用します。
デフォルトでは、SidebarMenuButton はボタンをレンダリングしますが、href プロップを渡すとリンクとしてレンダリングされます。
isActive プロップを使用して、メニュー項目をアクティブとしてマークします。
<SidebarMenuButton href="#" isActive>
Home
</SidebarMenuButton>SidebarMenuAction#
SidebarMenuAction コンポーネントは、SidebarMenuItem 内にメニューアクションをレンダリングするために使用します。
<SidebarMenuItem>
<SidebarMenuButton href="#">
<Home />
<span>Home</span>
</SidebarMenuButton>
<SidebarMenuAction>
<Plus /> <span className="sr-only">Add Project</span>
</SidebarMenuAction>
</SidebarMenuItem>SidebarMenuSub#
SidebarMenuSub コンポーネントは、SidebarMenu 内にサブメニューをレンダリングするために使用します。
<SidebarMenuItem>
<SidebarMenuButton />
<SidebarMenuSub>
<SidebarMenuSubItem>
<SidebarMenuSubButton />
</SidebarMenuSubItem>
</SidebarMenuSub>
</SidebarMenuItem>SidebarMenuBadge#
SidebarMenuBadge コンポーネントは、SidebarMenuItem 内にバッジをレンダリングするために使用します。
<SidebarMenuItem>
<SidebarMenuButton />
<SidebarMenuBadge>24</SidebarMenuBadge>
</SidebarMenuItem>SidebarMenuSkeleton#
SidebarMenuSkeleton コンポーネントは、SidebarMenu 用のスケルトンをレンダリングするために使用します。
<SidebarMenu>
{Array.from({ length: 5 }).map((_, index) => (
<SidebarMenuItem key={index}>
<SidebarMenuSkeleton />
</SidebarMenuItem>
))}
</SidebarMenu>SidebarTrigger#
SidebarTrigger コンポーネントを使用して、サイドバーの開閉を切り替えるボタンをレンダリングします。
import { useSidebar } from "@/components/ui/sidebar"
export function CustomTrigger() {
const { toggleSidebar } = useSidebar()
return <button onClick={toggleSidebar}>Toggle Sidebar</button>
}SidebarRail#
SidebarRail コンポーネントは、Sidebar 内にレールをレンダリングするために使用します。このレールはサイドバーの開閉に使用できます。
<Sidebar>
<SidebarHeader />
<SidebarContent>
<SidebarGroup />
</SidebarContent>
<SidebarFooter />
<SidebarRail />
</Sidebar>制御されたサイドバー#
open と onOpenChange プロップを使用して、サイドバーを制御します。
export function AppSidebar() {
const [open, setOpen] = React.useState(false)
return (
<SidebarProvider open={open} onOpenChange={setOpen}>
<Sidebar />
</SidebarProvider>
)
}テーマ#
サイドバーのテーマ設定には、以下の CSS 変数を使用します。
@layer base {
:root {
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 0 0% 98%;
--sidebar-primary-foreground: 240 5.9% 10%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}スタイリング#
状態に応じてサイドバーをスタイリングするためのヒントをいくつか紹介します。
<Sidebar collapsible="icon">
<SidebarContent>
<SidebarGroup className="group-data-[collapsible=icon]:hidden" />
</SidebarContent>
</Sidebar><SidebarMenuItem>
<SidebarMenuButton />
<SidebarMenuAction className="peer-data-[active=true]/menu-button:opacity-100" />
</SidebarMenuItem>RTL#
shadcn/ui で RTL サポートを有効にするには、RTL 構成ガイドを参照してください。
View RTL Sidebar変更履歴#
RTL サポート#
以前のバージョンの Sidebar コンポーネントからアップグレードする場合は、RTL サポートを追加するために以下の変更を適用する必要があります。
Sidebar コンポーネントに dir プロップを追加します。
分割代入したプロップに dir を追加し、モバイル用の SheetContent に渡します。
function Sidebar({
side = "left",
variant = "sidebar",
collapsible = "offcanvas",
className,
children,
+ dir,
...props
}: React.ComponentProps<"div"> & {
side?: "left" | "right"
variant?: "sidebar" | "floating" | "inset"
collapsible?: "offcanvas" | "icon" | "none"
}) {続いて、モバイルビューの SheetContent に渡します。
<Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
<SheetContent
+ dir={dir}
data-sidebar="sidebar"
data-slot="sidebar"
data-mobile="true"サイドバーコンテナに data-side 属性を追加します。
サイドバーコンテナ要素に data-side={side} を追加します。
<div
data-slot="sidebar-container"
+ data-side={side}
className={cn(サイドバーコンテナの配置用クラスを更新します。
JavaScript の三項演算子による条件付きクラスを、CSS のデータ属性セレクターに置き換えます。
className={cn(
- "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
- side === "left"
- ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
- : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
+ "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex data-[side=left]:left-0 data-[side=right]:right-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",SidebarRail の配置用クラスを更新します。
レールに物理的な配置を使用するよう、SidebarRail コンポーネントを更新します。
className={cn(
- "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-end-4 group-data-[side=right]:start-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] sm:flex",
+ "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 ltr:-translate-x-1/2 rtl:-translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] sm:flex",SidebarTrigger のアイコンに RTL 反転を追加します。
SidebarTrigger 内のアイコンに className="rtl:rotate-180" を追加し、RTL モードで反転させます。
<Button ...>
- <PanelLeftIcon />
+ <PanelLeftIcon className="rtl:rotate-180" />
<span className="sr-only">Toggle Sidebar</span>
</Button>これらの変更を適用すると、dir プロップを使用して方向を設定できるようになります。
<Sidebar dir="rtl" side="right">
{/* ... */}
</Sidebar>これにより、サイドバーは LTR と RTL の両方のレイアウトで正しく配置され、操作にも適切に対応します。