Repository: Singuralitylabs/portal-site
Pull request #28: 共通のサイドバーを追加
Author: login: satinoue
Created: 2025-03-02T04:02:07Z | Merged: 2025-03-06T13:43:23Z

## 変更内容

サイドバーを追加しました。

## 関連Issue

https://github.com/Singuralitylabs/portal-site/issues/9

## 特記事項

- モバイル、デスクトップとも問題ないか
- アイコンは lucide-reactから取得しております
- url直下の表示にて、「シンラボ〜です」とメニューが被っているのが大丈夫か、確認お願いします


Diff:
diff --git a/app/components/SideNav.tsx b/app/components/SideNav.tsx
new file mode 100644
index 00000000..8dd0e04b
--- /dev/null
+++ b/app/components/SideNav.tsx
@@ -0,0 +1,104 @@
+'use client';
+
+import { useState } from "react";
+import { Drawer, Button, Burger } from "@mantine/core";
+import { Menu, House, Video, FileText, User, LogOut } from "lucide-react";
+import Link from "next/link";
+
+interface NavItem {
+    title: string;
+    href: string;
+    icon: React.ReactNode;
+  }
+  
+  const navItems: NavItem[] = [
+    {
+      title: "ホーム",
+      href: "/",
+      icon: <House className="h-5 w-5" />,
+    },
+    // {
+    //   title: "動画一覧",
+    //   href: "/videos",
+    //   icon: <Video className="h-5 w-5" />,
+    // },
+    {
+      title: "資料一覧",
+      href: "/documents",
+      icon: <FileText className="h-5 w-5" />,
+    },
+    // {
+    //   title: "プロフィール",
+    //   href: "/profile",
+    //   //icon: <User className="h-5 w-5" />,
+    // },
+    {
+      title: "ログアウト",
+      href: "/login",
+      icon: <LogOut className="h-5 w-5" />,
+    },
+  ];
+
+  export function SideNav() {
+    const [open, setOpen] = useState(false);
+    
+    return (
+      <>
+
+        {/* ハンバーガーメニュー (モバイル用) */}
+        <Button 
+            variant="subtle" 
+            onClick={() => setOpen(true)} 
+            className="sm:hidden"
+        >
+        <Menu 
+            size={24}
+            className="sm:hidden" 
+        />
+        </Button>
+        
+        {/* モバイル用ハンバーガーメニュー */}
+        <Drawer
+            opened={open}
+            onClose={() => setOpen(false)}
+            position="left"
+            size="250px"
+            padding="md"
+            title="メニュー"
+        >
+            <nav className="space-y-2">
+            {navItems.map((item) => (
+                <Link
+                key={item.href}
+                href={item.href}
+                onClick={() => setOpen(false)}
+                className="flex items-center gap-3 rounded-sm px-3 py-2 text-muted-foreground transition-all hover:text-foreground"
+                >
+                {item.icon}
+                {item.title}
+                </Link>
+            ))}
+            </nav>
+        </Drawer>
+
+        {/* デスクトップ用サイドバー */}
+        <div className="hidden sm:flex h-screen w-64 flex-col fixed left-0 top-0 border-r bg-card">
+          <div className="p-6">
+            <h1 className="text-xl font-bold">Sinlab Portal</h1>
+          </div>
+          <nav className="flex-1 space-y-2 p-4">
+            {navItems.map((item) => (
+              <Link
+                key={item.href}
+                href={item.href}
+                className="flex items-center gap-3 rounded-sm px-3 py-2 text-muted-foreground transition-all hover:text-foreground"
+              >
+                {item.icon}
+                {item.title}
+              </Link>
+            ))}
+          </nav>
+        </div>
+      </>
+    );
+  }
\ No newline at end of file
diff --git a/app/layout.tsx b/app/layout.tsx
index 101ae49b..7e1bd53a 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -2,6 +2,7 @@ import type { Metadata } from "next";
 import "@mantine/core/styles.css";
 import "./globals.css";
 import { ColorSchemeScript, mantineHtmlProps, MantineProvider } from "@mantine/core";
+import { SideNav } from "./components/SideNav";
 
 export const metadata: Metadata = {
   title: "Sinlab Portal",
@@ -28,7 +29,12 @@ export default function RootLayout({
         <ColorSchemeScript />
       </head>
       <body>
-        <MantineProvider>{children}</MantineProvider>
+        <MantineProvider>
+          <div className="sm:flex min-h-screen">
+            <SideNav />
+            <div className="flex-1 sm:ml-48">{children}</div>
+          </div>
+        </MantineProvider>
       </body>
     </html>
   );


Reviews:
user: login: yamashin01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T23:01:25Z
user: login: yamashin01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T23:03:55Z
user: login: yamashin01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T23:05:04Z
user: login: satinoue
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T11:31:42Z
user: login: satinoue
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T11:32:19Z
user: login: yamashin01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T22:55:01Z
user: login: yamashin01
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T13:24:35Z

Review comments:
diff_hunk: @@ -0,0 +1,106 @@
+'use client';
+
+import { useState } from "react";
+import { Drawer, Button, Burger } from "@mantine/core";
+import { Menu, House, Video, FileText, User, LogOut } from "lucide-react";
+import { usePathname } from "next/navigation";
+import Link from "next/link";
+
+interface NavItem {
+    title: string;
+    href: string;
+    icon: React.ReactNode;
+  }
+  
+  const navItems: NavItem[] = [
+    {
+      title: "ホーム",
+      href: "/",
+      icon: <House className="h-5 w-5" />,
+    },
+    // {
+    //   title: "動画一覧",
+    //   href: "/videos",
+    //   icon: <Video className="h-5 w-5" />,
+    // },
+    {
+      title: "資料一覧",
+      href: "/documents",
+      icon: <FileText className="h-5 w-5" />,
+    },
+    // {
+    //   title: "プロフィール",
+    //   href: "/profile",
+    //   //icon: <User className="h-5 w-5" />,
+    // },
+    {
+      title: "ログアウト",
+      href: "/logout",
+      icon: <LogOut className="h-5 w-5" />,
+    },
+  ];
+  
+  export function SideNav() {
+    const pathname = usePathname();
path: app/components/SideNav.tsx
user: login: yamashin01
body: このpathnameは使われていないようなので、削除をお願いします。
created_at: 2025-03-02T23:01:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,106 @@
+'use client';
+
+import { useState } from "react";
+import { Drawer, Button, Burger } from "@mantine/core";
+import { Menu, House, Video, FileText, User, LogOut } from "lucide-react";
+import { usePathname } from "next/navigation";
+import Link from "next/link";
+
+interface NavItem {
+    title: string;
+    href: string;
+    icon: React.ReactNode;
+  }
+  
+  const navItems: NavItem[] = [
+    {
+      title: "ホーム",
+      href: "/",
+      icon: <House className="h-5 w-5" />,
+    },
+    // {
+    //   title: "動画一覧",
+    //   href: "/videos",
+    //   icon: <Video className="h-5 w-5" />,
+    // },
+    {
+      title: "資料一覧",
+      href: "/documents",
+      icon: <FileText className="h-5 w-5" />,
+    },
+    // {
+    //   title: "プロフィール",
+    //   href: "/profile",
+    //   //icon: <User className="h-5 w-5" />,
+    // },
+    {
+      title: "ログアウト",
+      href: "/logout",
+      icon: <LogOut className="h-5 w-5" />,
+    },
+  ];
+  
+  export function SideNav() {
+    const pathname = usePathname();
+    const [open, setOpen] = useState(false);
+    
+    return (
+      <>
+
+        {/* ハンバーガーメニュー (モバイル用) */}
+        <Button 
+            variant="subtle" 
+            onClick={() => setOpen(true)} 
+            className="lg:hidden"
path: app/components/SideNav.tsx
user: login: yamashin01
body: この`lg:hidden`は、画面サイズが `lg`を超えるとハンバーガーメニューを非表示にして下さいという意味なのですが、 `lg`はモバイル用というには画面サイズが大きすぎるので、`sm`あたりにしませんか？

ここ以外の `lg:`となっている箇所も同様の修正が必要です。
created_at: 2025-03-02T23:03:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -28,7 +29,10 @@ export default function RootLayout({
         <ColorSchemeScript />
       </head>
       <body>
-        <MantineProvider>{children}</MantineProvider>
+        <MantineProvider>
+          <SideNav />
+          {children}
+        </MantineProvider>
path: app/layout.tsx
user: login: yamashin01
body: すいません、少し設定を誤っていました。

今の実装だと、サイドバーとページが重なってしまいますね。

app/layout.tsxの実装を下記のように修正をお願いします。

```js
<MantineProvider>
  <div className="sm:flex min-h-screen">
    <SideNav />
    <div className="flex-1 sm:ml-48">{children}</div>
  </div>
</MantineProvider>
```
created_at: 2025-03-02T23:05:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,106 @@
+'use client';
+
+import { useState } from "react";
+import { Drawer, Button, Burger } from "@mantine/core";
+import { Menu, House, Video, FileText, User, LogOut } from "lucide-react";
+import { usePathname } from "next/navigation";
+import Link from "next/link";
+
+interface NavItem {
+    title: string;
+    href: string;
+    icon: React.ReactNode;
+  }
+  
+  const navItems: NavItem[] = [
+    {
+      title: "ホーム",
+      href: "/",
+      icon: <House className="h-5 w-5" />,
+    },
+    // {
+    //   title: "動画一覧",
+    //   href: "/videos",
+    //   icon: <Video className="h-5 w-5" />,
+    // },
+    {
+      title: "資料一覧",
+      href: "/documents",
+      icon: <FileText className="h-5 w-5" />,
+    },
+    // {
+    //   title: "プロフィール",
+    //   href: "/profile",
+    //   //icon: <User className="h-5 w-5" />,
+    // },
+    {
+      title: "ログアウト",
+      href: "/logout",
+      icon: <LogOut className="h-5 w-5" />,
+    },
+  ];
+  
+  export function SideNav() {
+    const pathname = usePathname();
path: app/components/SideNav.tsx
user: login: satinoue
body: importごと削除しました。
created_at: 2025-03-03T11:31:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,106 @@
+'use client';
+
+import { useState } from "react";
+import { Drawer, Button, Burger } from "@mantine/core";
+import { Menu, House, Video, FileText, User, LogOut } from "lucide-react";
+import { usePathname } from "next/navigation";
+import Link from "next/link";
+
+interface NavItem {
+    title: string;
+    href: string;
+    icon: React.ReactNode;
+  }
+  
+  const navItems: NavItem[] = [
+    {
+      title: "ホーム",
+      href: "/",
+      icon: <House className="h-5 w-5" />,
+    },
+    // {
+    //   title: "動画一覧",
+    //   href: "/videos",
+    //   icon: <Video className="h-5 w-5" />,
+    // },
+    {
+      title: "資料一覧",
+      href: "/documents",
+      icon: <FileText className="h-5 w-5" />,
+    },
+    // {
+    //   title: "プロフィール",
+    //   href: "/profile",
+    //   //icon: <User className="h-5 w-5" />,
+    // },
+    {
+      title: "ログアウト",
+      href: "/logout",
+      icon: <LogOut className="h-5 w-5" />,
+    },
+  ];
+  
+  export function SideNav() {
+    const pathname = usePathname();
+    const [open, setOpen] = useState(false);
+    
+    return (
+      <>
+
+        {/* ハンバーガーメニュー (モバイル用) */}
+        <Button 
+            variant="subtle" 
+            onClick={() => setOpen(true)} 
+            className="lg:hidden"
path: app/components/SideNav.tsx
user: login: satinoue
body: lg -> sm に変更
created_at: 2025-03-03T11:32:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,104 @@
+'use client';
+
+import { useState } from "react";
+import { Drawer, Button, Burger } from "@mantine/core";
+import { Menu, House, Video, FileText, User, LogOut } from "lucide-react";
+import Link from "next/link";
+
+interface NavItem {
+    title: string;
+    href: string;
+    icon: React.ReactNode;
+  }
+  
+  const navItems: NavItem[] = [
+    {
+      title: "ホーム",
+      href: "/",
+      icon: <House className="h-5 w-5" />,
+    },
+    // {
+    //   title: "動画一覧",
+    //   href: "/videos",
+    //   icon: <Video className="h-5 w-5" />,
+    // },
+    {
+      title: "資料一覧",
+      href: "/documents",
+      icon: <FileText className="h-5 w-5" />,
+    },
+    // {
+    //   title: "プロフィール",
+    //   href: "/profile",
+    //   //icon: <User className="h-5 w-5" />,
+    // },
+    {
+      title: "ログアウト",
+      href: "/logout",
path: app/components/SideNav.tsx
user: login: yamashin01
body: 考えてみたら、ログアウト後の遷移先は、 `/logout`ではなく`/login`ですね。

修正をお願いできますでしょうか？
created_at: 2025-03-03T22:55:01Z
author_association: CONTRIBUTOR

PR comments:
user: login: yamashin01
created_at: 2025-03-02T23:05:42Z
body: @satinoue 

コメントを出したので、ご確認をお願いします。
author_association: CONTRIBUTOR
user: login: yamashin01
created_at: 2025-03-02T23:07:05Z
body: @satinoue 

一つ指摘漏れでした。

rebaseが完了してないようなので、対応ください。
author_association: CONTRIBUTOR
user: login: satinoue
created_at: 2025-03-03T11:35:09Z
body: @yamashin01 
修正と合わせて、rounded-lg / rounded-sm について調べたところ、
- rounded-lg : ラベル（radius  2px)
- rounded-sm : カードUI（radius  6px)

ということだったので、指摘のあった [lg:] の話ではないですが、rounded-sm に変更しました。
author_association: CONTRIBUTOR