【Next.js】shadcnでサイドバーを作成する
はじめに
個人開発で作成しているアプリでサイドバーを作成したのでその方法を紹介します。
shadcnで作っているので、まんまshadcnのテンプレートをそのまま使っているような形ではあるのですが、実際のアプリに画面全体に適用するとどうなるかという観点で見て頂ければと思います。
実際に作ったサイドバーは以下のように動作します。
開発環境
- Next.js 15.1.6
- pnpm 10.1.0
- shadcn/ui
※ デザインアーキテクチャは、FSDを採用しています。
サイドバーの作成
shadcnのsidebarコンポーネントをインストール
shadcnのサイドバーコンポーネントのテンプレートをインストールするために以下のコマンドを実行します。
src/shared/ui/sidebar.tsx
pnpm dlx shadcn@latest add sidebar
このコマンドでsidebar.tsx以外にもsidebar.tsx内で使用している他のコンポーネントもインストールされたます。
エラーが出る場合は、対象のファイルがないときにエラーが出たりします。
※ app/globals.cssがない場合にエラーが発生したので作成してから実行すれば解決します。
❯ pnpm dlx shadcn@latest add sidebar
✔ Checking registry.
✔ Updating tailwind.config.ts
✔ Updating CSS variables in app/globals.css
✔ Installing dependencies.
✔ The file sidebar.tsx already exists. Would you like to overwrite? … yes
✔ The file button.tsx already exists. Would you like to overwrite? … yes
✔ The file tooltip.tsx already exists. Would you like to overwrite? … yes
✔ The file input.tsx already exists. Would you like to overwrite? … yes
ℹ Updated 4 files:
- src/shared/ui/sidebar.tsx
- src/shared/ui/button.tsx
- src/shared/ui/tooltip.tsx
- src/shared/ui/input.tsx
ℹ Skipped 4 files: (files might be identical, use --overwrite to overwrite)
- src/shared/ui/separator.tsx
- src/shared/ui/sheet.tsx
- hooks/use-mobile.tsx
- src/shared/ui/skeleton.tsx
サイドバーの作成
次に以下のファイルを作成します。
FSDを採用しているので、ディレクトリ構成的に珍しいかもしれないので、関連するディレクトリを以下に示します。
app
├── (protected)
│ ├── account
│ ├── layout.tsx
│ └── page.tsx
├── globals.css
└── layout.tsx
src
├── app
│ ├── globals.css
│ ├── layouts
│ ├── page
│ └── provider.tsx
├── shared
│ ├── lib
│ └── ui
└── widgets
├── content-area
├── navbar
├── sidebar
└── sidebar-layout
- app/(protected)/layout.tsx
ReportLayout.tsxファイルをNextjsの標準ファイルであるlayout.tsxのimportで読み込みます。
export {
ReportLayout as default,
} from "@/src/app/layouts"
- src/app/layouts/ui/ReportLayout.tsx
NabvarとSidebarを表示するためのラッパーコンポーネントを作成します。
import "@/src/app/globals.css"
import { Navbar } from "@/src/widgets/navbar"
import { SidebarLayout } from "@/src/widgets/sidebar-layout"
export const ReportLayout = ({
children,
}: Readonly<{
children: React.ReactNode
}>) => {
return (
<div className="h-screen w-full">
<Navbar />
<div className="pl-16 h-full">
<SidebarLayout>{children}</SidebarLayout>
</div>
</div>
)
}
- src/widgets/sidebar-layout/ui/SidebarLayout.tsx
SidebarProvider内で、AppSidebarとコンテンツ領域を表示します。
コンテンツ領域内でサイドバーの開閉ボタンを表示するSidebarTriggerを配置します。
"use client"
import { SidebarProvider, SidebarTrigger } from "@/src/shared/ui/sidebar"
import { AppSidebar } from "@/src/widgets/sidebar/ui/Sidebar"
import type React from "react"
export const SidebarLayout: React.FC<{
children: React.ReactNode
}> = ({ children }) => {
return (
<SidebarProvider className="w-full">
<AppSidebar />
<main className="flex flex-1 flex-col min-h-0 overflow-hidden">
<SidebarTrigger />
<div className="p-4 overflow-y-auto flex-1">{children}</div>
</main>
</SidebarProvider>
)
}
- src/widgets/sidebar/ui/Sidebar.tsx
サイドバー本体を作成します。
"use client"
import { SelectDate, SelectYear } from "@/src/features/select-date"
import { Sidebar, SidebarContent, SidebarHeader } from "@/src/shared/ui/sidebar"
import { StickyNote } from "lucide-react"
import Link from "next/link"
import type React from "react"
export const AppSidebar: React.FC = () => {
return (
<Sidebar>
<SidebarHeader className="bg-gray-100">
<Link href="/" className="flex items-center gap-2 p-4">
<StickyNote className="w-6 h-6" />
<p className="text-lg font-bold">日報管理ツール</p>
</Link>
</SidebarHeader>
<SidebarContent>
<div className="h-full bg-gray-100">
<SelectYear />
<SelectDate />
</div>
</SidebarContent>
</Sidebar>
)
}
これでサイドバーの作成は完了です。
冒頭でも記載したようにgifのようにサイドバーが表示されます。
これだけで、PCだけでなく、スマホでもサイドバーが表示されます。
PCサイズ
スマホサイズ
スマホの場合は、画面外からサイドバーがスライドインして出てきます。
終わりに
shadcnを使ってサイドバーを実装する方法について解説しました。
PCもスマホサイズごとに個別の実装をしなくても、いい感じに表示されるようになります。
Discussion