125k

Sidebar

組み合わせ可能で、テーマ設定とカスタマイズに対応したサイドバー コンポーネント。

"use client"

import * as React from "react"

アイコン表示に折りたたまれるサイドバー。

サイドバーは、構築が最も複雑なコンポーネントの一つです。あらゆるアプリケーションの中核を担い、多くの可動部分を含むことがよくあります。

今では、それを支える確かな基盤が整いました。組み合わせ可能で、テーマ設定にも対応し、自由にカスタマイズできます。

ブロックライブラリを見る。

インストール

pnpm dlx shadcn@latest add sidebar

使い方

app/layout.tsx
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>
  )
}
components/app-sidebar.tsx
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 — サイドバーの開閉を切り替えるコントロールです。
Sidebar Structure

SidebarProvider

SidebarProvider コンポーネントは、Sidebar コンポーネントにサイドバーのコンテキストを提供するために使用します。アプリケーション全体を必ず SidebarProvider コンポーネントでラップしてください。

プロパティ

NameTypeDescription
defaultOpenbooleanサイドバーのデフォルトの開閉状態です。
openbooleanサイドバーの開閉状態です(制御時)。
onOpenChange(open: boolean) => voidサイドバーの開閉状態を設定します(制御時)。

幅

アプリケーション内にサイドバーが 1 つしかない場合は、sidebar.tsx の SIDEBAR_WIDTH と SIDEBAR_WIDTH_MOBILE 変数を使用してサイドバーの幅を設定できます。

components/ui/sidebar.tsx
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 のキーボードショートカットを使用します。

components/ui/sidebar.tsx
const SIDEBAR_KEYBOARD_SHORTCUT = "b"

Sidebar は、折りたたみ可能なサイドバーをレンダリングするためのメインコンポーネントです。

プロパティ

PropertyTypeDescription
sideleft or rightサイドバーの表示位置です。
variantsidebar, floating, or insetサイドバーのバリアントです。
collapsibleoffcanvas, icon, or noneサイドバーの折りたたみ状態です。
PropDescription
offcanvas左右からスライドして表示される、折りたたみ可能なサイドバーです。
iconアイコン表示に折りたたまれるサイドバーです。
none折りたたみができないサイドバーです。
<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()
}
PropertyTypeDescription
stateexpanded or collapsedサイドバーの現在の状態です。
openbooleanサイドバーが開いているかどうかです。
setOpen(open: boolean) => voidサイドバーの開閉状態を設定します。
openMobilebooleanモバイルでサイドバーが開いているかどうかです。
setOpenMobile(open: boolean) => voidモバイルでのサイドバーの開閉状態を設定します。
isMobilebooleanサイドバーがモバイル表示かどうかです。
toggleSidebar() => voidサイドバーの開閉を切り替えます。デスクトップ・モバイル両対応です。

SidebarHeader

SidebarHeader コンポーネントを使用して、サイドバーに固定ヘッダーを追加します。

components/app-sidebar.tsx
<Sidebar>
  <SidebarHeader>
    <SidebarMenu>
      <SidebarMenuItem>
        <DropdownMenu>
          <DropdownMenuTrigger render={<SidebarMenuButton />}>
            Select Workspace
            <ChevronDown className="ml-auto" />
          </DropdownMenuTrigger>
          <DropdownMenuContent>
            <DropdownMenuItem>
              <span>Acme Inc</span>
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </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 defaultOpen className="group/collapsible">
  <SidebarGroup>
    <SidebarGroupLabel render={<CollapsibleTrigger />}>
      Help
      <ChevronDown className="ml-auto transition-transform group-data-open/collapsible:rotate-180" />
    </SidebarGroupLabel>
    <CollapsibleContent>
      <SidebarGroupContent />
    </CollapsibleContent>
  </SidebarGroup>
</Collapsible>

SidebarMenu

SidebarMenu コンポーネントは、SidebarGroup 内にメニューを構築するために使用します。

Sidebar Menu
<SidebarMenu>
  {projects.map((project) => (
    <SidebarMenuItem key={project.name}>
      <SidebarMenuButton render={<a href={project.url} />}>
        <project.icon />
        <span>{project.name}</span>
      </SidebarMenuButton>
    </SidebarMenuItem>
  ))}
</SidebarMenu>

SidebarMenuButton

SidebarMenuButton コンポーネントは、SidebarMenuItem 内にメニューボタンをレンダリングするために使用します。

デフォルトでは、SidebarMenuButton はボタンをレンダリングしますが、render プロップを使用すると Link や a タグなど別のコンポーネントをレンダリングできます。

isActive プロップを使用して、メニュー項目をアクティブとしてマークします。

<SidebarMenuButton render={<a href="#" />} isActive>
  Home
</SidebarMenuButton>

SidebarMenuAction

SidebarMenuAction コンポーネントは、SidebarMenuItem 内にメニューアクションをレンダリングするために使用します。

<SidebarMenuItem>
  <SidebarMenuButton render={<a 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 の両方のレイアウトで正しく配置され、操作にも適切に対応します。