😄
Reactとshadcn/uiのSidebarでサイドバーを作る
Reactとshadcn/uiのSidebarでサイドバーを作る
初期設定
npx shadcn@latest add sidebar
で必要なセットアップが完了するのでとても簡単
<SidebarProvider>
で挟むことで開閉状態が共有できる。useContextが使われてた。公式ドキュメントではapp/layout.tsx
でアプリのroot上に追加とある。
実装
仕様
今回実装するサイドバーの仕様を決めてみる
- メニューアイテムは公式ドキュメントの配列データをそのまま転用
- Inboxのところのみ通知数が表示されるようにする
- メニューのラベリングは"アプリケーション"と表示する
- 同じデータを使用して折り畳み可能な"ヘルプ"というラベリングのメニューを表示する
- デスクトップでは横からぬるっとサイドバー、モバイルでは画面が薄暗くなってサイドバーを表示
- 現在のページがわかりやすいように背景色を変える(今回はHome)
コード
先にcollapsibleを追加してください。
2. Inboxのところのみ通知数が表示されるようにする
<SidebarMenuBadge>24</SidebarMenuBadge>
- メニューのラベリングは"アプリケーション"と表示する
<SidebarGroupLabel>アプリケーション</SidebarGroupLabel>
- 同じデータを使用して折り畳み可能な"ヘルプ"というラベリングのメニューを表示する
collapsible
というコンポーネントを使用することで折りたたむことができるメニューが実現可能
<Collapsible defaultOpen className="group/collapsible">
<SidebarGroup>
<SidebarGroupLabel asChild>
<CollapsibleTrigger>
ヘルプ
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
</CollapsibleTrigger>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
aaaaaa
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</CollapsibleContent>
</SidebarGroup>
</Collapsible>
- デスクトップでは横からぬるっとサイドバー、モバイルでは画面が薄暗くなってサイドバーを表示
variant
というpropsを渡すことで変更できる。他にも"floating" | "inset"があるが、insetが何かわからん。
<Sidebar side="right" variant="sidebar">
{/**
* -------------------
**/}
</Sidebar>
- 現在のページがわかりやすいように背景色を変える(今回はHome)
これだけで背景色が変わってアクティブなサイドバーアイテムがわかりやすくなる
<SidebarMenuButton asChild isActive></SidebarMenuButton>
コード全文
interface Items {
title: string;
url: string;
icon: ForwardRefExoticComponent<Omit<LucideProps, "ref"> & RefAttributes<SVGSVGElement>>;
notifications?: number;
isActive?: boolean;
}
// Menu items.
const items: Items[] = [
{
title: "Home",
url: "/",
icon: HomeIcon,
isActive: true,
},
{
title: "Inbox",
url: "/inbox",
icon: Inbox,
notifications: 24
},
{
title: "Calendar",
url: "/calendar",
icon: Calendar,
},
{
title: "Search",
url: "/search",
icon: Search,
},
{
title: "Settings",
url: "/setting",
icon: Settings,
},
]
// ------------------------------------ //
<SidebarTrigger />
<Sidebar side="right" variant="sidebar">
<SidebarHeader>
<h3 className="text-lg font-semibold text-foreground">テスト</h3>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>アプリケーション</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild>
<a href={item.url}>
<item.icon />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
{item.notifications && (
<SidebarMenuBadge>24</SidebarMenuBadge>
)}
</SidebarMenuItem>
))}
</SidebarMenu>
<Collapsible defaultOpen className="group/collapsible">
<SidebarGroup>
<SidebarGroupLabel asChild>
<CollapsibleTrigger>
ヘルプ
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
</CollapsibleTrigger>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild>
<a href={item.url}>
<item.icon />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
{item.notifications && (
<SidebarMenuBadge>24</SidebarMenuBadge>
)}
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</CollapsibleContent>
</SidebarGroup>
</Collapsible>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
モバイルサイズの時、以下のようなエラーが出ると思う。
おそらくSidebar内のSheetのTitle, Descriptionを使っていないせいで下記のようなエラーが出ると予想。
Dialog.tsx:540 Warning: Missing `Description` or `aria-describedby={undefined}` for {DialogContent}.
client.ts:59 `DialogContent` requires a `DialogTitle` for the component to be accessible for screen reader users.
If you want to hide the `DialogTitle`, you can wrap it with our VisuallyHidden component.
For more information, see
エラー文が気になる場合はSidebar内のSheetに以下を記述して無理やりエラーを解消する
<SheetTitle asChild>
<span className="sr-only">サイドバー</span>
</SheetTitle>
<SheetDescription asChild>
<span className="sr-only">サイドバー</span>
</SheetDescription>
swrなどでデータ取得までのローディング中はスケルトンローダーを表示したりできるらしい。
実際の画面
参考
感想
カスタマイズ性が高く、サイドバーも簡単に作ることができ、とても面白い。色々なバリエーションのサイドバーが作ることができるのでますますshadcn/uiから離れることができなくなりそう
Discussion