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:hidden, lg:flex দিয়ে responsive | | Icons | Lucide React icons ব্যবহার |
📁 নতুন Files:
src/components/layout/
├── Sidebar.tsx
├── MobileSidebar.tsx
├── Header.tsx
└── MainLayout.tsx