1. Home
  2. ShadCn
  3. Phase 3: Navigation & Layout

Phase 3: Navigation & Layout

Step 1: প্রয়োজনীয় Components Install করো

npx shadcn@latest add sheet
npx shadcn@latest add separator

Step 2: Lucide Icons Install করো

npm install lucide-react

Step 3: Sidebar Component নিজে হাতে বানাও

src/components/layout/Sidebar.tsx file তৈরি করো:

import { 
  LayoutDashboard, 
  Users, 
  GraduationCap, 
  ClipboardList, 
  Settings,
  LogOut
} from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Separator } from '@/components/ui/separator'

// Menu items define করলাম
const menuItems = [
  { icon: LayoutDashboard, label: 'Dashboard', href: '/' },
  { icon: Users, label: 'Students', href: '/students' },
  { icon: GraduationCap, label: 'Classes', href: '/classes' },
  { icon: ClipboardList, label: 'Attendance', href: '/attendance' },
  { icon: Settings, label: 'Settings', href: '/settings' },
]

export function Sidebar() {
  return (
    <div className="flex flex-col h-full w-64 bg-white border-r">
      {/* Logo/Header */}
      <div className="p-6">
        <h1 className="text-xl font-bold text-gray-800">
          📚 Student MS
        </h1>
      </div>
      
      <Separator />
      
      {/* Navigation Menu */}
      <nav className="flex-1 p-4">
        <ul className="space-y-2">
          {menuItems.map((item) => (
            <li key={item.href}>
              <Button
                variant="ghost"
                className="w-full justify-start gap-3"
              >
                <item.icon className="h-5 w-5" />
                {item.label}
              </Button>
            </li>
          ))}
        </ul>
      </nav>
      
      <Separator />
      
      {/* Footer */}
      <div className="p-4">
        <Button variant="ghost" className="w-full justify-start gap-3 text-red-500 hover:text-red-600 hover:bg-red-50">
          <LogOut className="h-5 w-5" />
          Logout
        </Button>
      </div>
    </div>
  )
}

Step 4: Mobile Sidebar (Sheet দিয়ে)

src/components/layout/MobileSidebar.tsx file তৈরি করো:

import { Menu } from 'lucide-react'
import { Button } from '@/components/ui/button'
import {
  Sheet,
  SheetContent,
  SheetTrigger,
} from '@/components/ui/sheet'
import { Sidebar } from './Sidebar'

export function MobileSidebar() {
  return (
    <Sheet>
      <SheetTrigger asChild>
        <Button variant="ghost" size="icon" className="lg:hidden">
          <Menu className="h-6 w-6" />
        </Button>
      </SheetTrigger>
      <SheetContent side="left" className="p-0 w-64">
        <Sidebar />
      </SheetContent>
    </Sheet>
  )
}

Step 5: Header Component

src/components/layout/Header.tsx file তৈরি করো:

import { Bell, Search } from 'lucide-react'
import { Input } from '@/components/ui/input'
import { Button } from '@/components/ui/button'
import { MobileSidebar } from './MobileSidebar'

export function Header() {
  return (
    <header className="h-16 border-b bg-white flex items-center justify-between px-4 lg:px-6">
      {/* Left side */}
      <div className="flex items-center gap-4">
        <MobileSidebar />
        <div className="hidden md:flex items-center gap-2">
          <Search className="h-4 w-4 text-gray-400" />
          <Input 
            placeholder="Search students..." 
            className="w-64"
          />
        </div>
      </div>
      
      {/* Right side */}
      <div className="flex items-center gap-4">
        <Button variant="ghost" size="icon">
          <Bell className="h-5 w-5" />
        </Button>
        <div className="h-8 w-8 rounded-full bg-blue-500 flex items-center justify-center text-white font-medium">
          A
        </div>
      </div>
    </header>
  )
}

Step 6: Main Layout Component

src/components/layout/MainLayout.tsx file তৈরি করো:

import { Sidebar } from './Sidebar'
import { Header } from './Header'

interface MainLayoutProps {
  children: React.ReactNode
}

export function MainLayout({ children }: MainLayoutProps) {
  return (
    <div className="min-h-screen bg-gray-100">
      {/* Sidebar - desktop only */}
      <aside className="hidden lg:fixed lg:inset-y-0 lg:flex lg:w-64">
        <Sidebar />
      </aside>
      
      {/* Main content area */}
      <div className="lg:pl-64">
        <Header />
        <main className="p-6">
          {children}
        </main>
      </div>
    </div>
  )
}

Step 7: App.tsx Update করো

import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from '@/components/ui/card'
import { MainLayout } from '@/components/layout/MainLayout'
import { students } from '@/data/students'

function App() {
  return (
    <MainLayout>
      <div className="mb-6">
        <h1 className="text-2xl font-bold text-gray-800">Students</h1>
        <p className="text-gray-600">Total: {students.length} students</p>
      </div>

      <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
        {students.map((student) => (
          <Card key={student.id}>
            <CardHeader>
              <div className="flex justify-between items-start">
                <CardTitle className="text-lg">{student.name}</CardTitle>
                <Badge variant={student.status === 'active' ? 'default' : 'destructive'}>
                  {student.status}
                </Badge>
              </div>
              <CardDescription>Roll: {student.rollNumber}</CardDescription>
            </CardHeader>
            <CardContent className="space-y-2 text-sm">
              <p><span className="font-medium">Class:</span> {student.class} ({student.section})</p>
              <p><span className="font-medium">Email:</span> {student.email}</p>
            </CardContent>
            <CardFooter className="gap-2">
              <Button size="sm">View</Button>
              <Button size="sm" variant="outline">Edit</Button>
            </CardFooter>
          </Card>
        ))}
      </div>
    </MainLayout>
  )
}

export default App

🎯 যা শিখলে:

| Concept | কী শিখলে | |———|———| | Sidebar | নিজে হাতে navigation বানানো | | Sheet | Mobile এ slide-in menu | | Layout | Fixed sidebar + scrollable content | | Responsive | lg:hiddenlg:flex দিয়ে responsive | | Icons | Lucide React icons ব্যবহার |

📁 নতুন Files:

src/components/layout/
├── Sidebar.tsx
├── MobileSidebar.tsx
├── Header.tsx
└── MainLayout.tsx

How can we help?