💭

【Next.js】shadcnでサイドバーを作成する

に公開

はじめに

個人開発で作成しているアプリでサイドバーを作成したのでその方法を紹介します。
shadcnで作っているので、まんまshadcnのテンプレートをそのまま使っているような形ではあるのですが、実際のアプリに画面全体に適用するとどうなるかという観点で見て頂ければと思います。

実際に作ったサイドバーは以下のように動作します。

sidebar

開発環境

  • Next.js 15.1.6
  • pnpm 10.1.0
  • shadcn/ui

※ デザインアーキテクチャは、FSDを採用しています。

https://feature-sliced.design/ja

サイドバーの作成

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

https://ui.shadcn.com/docs/components/sidebar

サイドバーの作成

次に以下のファイルを作成します。
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サイズ
sidebar

スマホサイズ
sidebar

スマホの場合は、画面外からサイドバーがスライドインして出てきます。

終わりに

shadcnを使ってサイドバーを実装する方法について解説しました。
PCもスマホサイズごとに個別の実装をしなくても、いい感じに表示されるようになります。

Discussion