Files
Vault/UI_DESIGN_SYSTEM.md
T
twotalesanimation 81ad7e4ea9 Initial commit
2026-06-11 10:46:09 +02:00

1139 lines
30 KiB
Markdown

# OW Animation Arts Vault - UI Design System & Layout Guide
This document outlines the complete UI/style and layout architecture used in this codebase. Use this guide to create additional applications for the same client with consistent design and user experience.
---
## Table of Contents
1. [Technology Stack](#technology-stack)
2. [Project Architecture](#project-architecture)
3. [Color System & Theming](#color-system--theming)
4. [Layout System](#layout-system)
5. [Navigation & Sidebar](#navigation--sidebar)
6. [Page Layouts](#page-layouts)
7. [Component Library](#component-library)
8. [Typography & Spacing](#typography--spacing)
9. [Form Patterns](#form-patterns)
10. [Responsive Design](#responsive-design)
11. [Dark Mode Implementation](#dark-mode-implementation)
12. [Reusable Patterns](#reusable-patterns)
13. [Asset Guidelines](#asset-guidelines)
---
## 1. Technology Stack
### Core Framework
- **Next.js 16.0.3** - React framework with App Router
- **React 18+** - UI library
- **TypeScript** - Type safety
- **Tailwind CSS 3.4+** - Utility-first CSS framework
### UI Component Library
- **shadcn/ui** - Pre-built, composable React components
- **@radix-ui/** - Unstyled, accessible component primitives
- **Lucide React** - Beautiful, consistent icon library
- **Tabler Icons** - Alternative icon set
### State Management & Data
- **NextAuth.js** - Authentication
- **Next-Themes** - Theme management (dark/light mode)
- **Prisma ORM** - Database abstraction
- **TanStack React Table** - Advanced table data management
- **Sonner** - Toast notifications
### Additional Libraries
- **@dnd-kit** - Drag and drop functionality
- **Embla Carousel** - Carousel/slider component
- **Recharts** - Data visualization charts
- **HLS.js** - Video streaming (HLS protocol)
- **date-fns** - Date utilities
- **class-variance-authority (CVA)** - Component variant management
- **clsx** - Conditional className merging
---
## 2. Project Architecture
### Directory Structure
```
app/
├── layout.tsx # Root layout (server component)
├── page.tsx # Landing/home page
├── providers.tsx # Client-side providers (SessionProvider, ThemeProvider)
├── globals.css # Global styles & CSS variables
├── login/
│ ├── page.tsx # Login page
│ └── unauthorized/
├── dashboard/
│ ├── page.tsx # Protected dashboard
│ ├── dashboard-client.tsx # Client component with content
│ ├── liked-videos/
│ └── watch-history/
├── admin/
│ ├── page.tsx # Admin gate (server component)
│ ├── admin-client.tsx # Admin UI (client component)
│ ├── users/
│ ├── courses/
│ ├── playlists/
│ ├── videos/
│ ├── enrollments/
│ └── stats/
├── api/ # API routes for server operations
└── videoplayer/ # Video player page
components/
├── app-sidebar.tsx # Main navigation sidebar
├── site-header.tsx # Top header with breadcrumbs
├── nav-main.tsx # Primary navigation menu
├── nav-secondary.tsx # Secondary navigation items
├── nav-user.tsx # User profile dropdown
├── login-form.tsx # Google OAuth login form
├── data-table.tsx # Advanced data table component
├── hls.tsx # Video player (HLS streaming)
├── chart-area-interactive.tsx # Interactive chart component
├── comments-section.tsx # Comments/discussion area
├── admin-notifications.tsx # Admin notifications
├── ui/ # shadcn/ui components
│ ├── button.tsx
│ ├── card.tsx
│ ├── sidebar.tsx
│ ├── input.tsx
│ ├── label.tsx
│ ├── badge.tsx
│ ├── dropdown-menu.tsx
│ ├── dialog.tsx
│ ├── drawer.tsx
│ ├── table.tsx
│ ├── tabs.tsx
│ ├── carousel.tsx
│ ├── chart.tsx
│ ├── select.tsx
│ ├── checkbox.tsx
│ ├── field.tsx
│ ├── collapsible.tsx
│ └── ... (27+ components)
lib/
├── utils.ts # Utility functions (cn for className merging)
├── auth-options.ts # NextAuth configuration
├── auth-check.ts # Authentication helpers
├── prisma.ts # Prisma client
└── video-urls.ts # Video URL generation
hooks/
├── use-mobile.ts # Mobile breakpoint hook
├── useVideo.ts # Video data hooks
├── usePlaylists.ts # Playlist data hooks
└── usePlaylist.ts # Single playlist hook
public/
├── icon.svg # App icon
├── vault.png # Vault image (login page)
└── vault.exr # Vault image (high-res)
```
### Component Structure Pattern
**Server Component (pages):**
```tsx
// app/dashboard/page.tsx
import { requireUser } from '@/lib/auth-check';
import DashboardClient from './dashboard-client';
export default async function DashboardPage() {
const session = await requireUser('/login');
return <DashboardClient />;
}
```
**Client Component (content):**
```tsx
// app/dashboard/dashboard-client.tsx
'use client';
import React from 'react';
import { AppSidebar } from '@/components/app-sidebar';
import { SiteHeader } from '@/components/site-header';
import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar';
export default function DashboardClient() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<SiteHeader />
<main className="flex flex-col gap-4 p-4">
{/* Page content */}
</main>
</SidebarInset>
</SidebarProvider>
);
}
```
---
## 3. Color System & Theming
### CSS Variables (OKLch Color Space)
The design system uses **OKLch color space** for perceptually uniform colors across light and dark modes.
**Light Mode (`:root`):**
```css
--background: oklch(1 0 0); /* White */
--foreground: oklch(0.141 0.005 285.823); /* Near Black */
--card: oklch(1 0 0); /* White */
--card-foreground: oklch(0.141 0.005 285.823); /* Near Black */
--primary: oklch(0.646 0.222 41.116); /* Warm Yellow/Orange */
--primary-foreground: oklch(0.98 0.016 73.684); /* Light cream */
--secondary: oklch(0.967 0.001 286.375); /* Light gray */
--secondary-foreground: oklch(0.21 0.006 285.885);
--muted: oklch(0.967 0.001 286.375); /* Light gray (buttons, etc) */
--muted-foreground: oklch(0.552 0.016 285.938); /* Medium gray (text) */
--accent: oklch(0.967 0.001 286.375); /* Light gray */
--accent-foreground: oklch(0.21 0.006 285.885);
--destructive: oklch(0.577 0.245 27.325); /* Red */
--border: oklch(0.92 0.004 286.32); /* Light gray */
--input: oklch(0.92 0.004 286.32); /* Light gray */
--ring: oklch(0.75 0.183 55.934); /* Orange/Gold for focus */
```
**Dark Mode (`.dark`):**
```css
.dark {
--background: oklch(0.141 0.005 285.823); /* Near Black */
--foreground: oklch(0.985 0 0); /* White */
--card: oklch(0.21 0.006 285.885); /* Dark gray */
--card-foreground: oklch(0.985 0 0); /* White */
--primary: oklch(0.705 0.213 47.604); /* Lighter Orange */
--secondary: oklch(0.274 0.006 286.033); /* Dark gray */
--muted: oklch(0.274 0.006 286.033); /* Dark gray */
--muted-foreground: oklch(0.705 0.015 286.067);
--border: oklch(1 0 0 / 10%); /* White with 10% opacity */
--input: oklch(1 0 0 / 15%); /* White with 15% opacity */
--ring: oklch(0.408 0.123 38.172); /* Red-orange for focus */
}
```
### Chart Colors
```css
--chart-1: oklch(0.837 0.128 66.29); /* Warm yellow */
--chart-2: oklch(0.705 0.213 47.604); /* Orange */
--chart-3: oklch(0.646 0.222 41.116); /* Dark orange */
--chart-4: oklch(0.553 0.195 38.402); /* Red-orange */
--chart-5: oklch(0.47 0.157 37.304); /* Deep red-orange */
```
### Sidebar Colors
```css
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.141 0.005 285.823);
--sidebar-primary: oklch(0.646 0.222 41.116);
--sidebar-primary-foreground: oklch(0.98 0.016 73.684);
--sidebar-accent: oklch(0.967 0.001 286.375);
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
--sidebar-border: oklch(0.92 0.004 286.32);
--sidebar-ring: oklch(0.75 0.183 55.934);
```
### Color Usage
| Color | Usage |
|-------|-------|
| **Primary** | Main CTA buttons, active links, selected items |
| **Secondary** | Secondary buttons, badges |
| **Muted** | Disabled states, placeholder text, subtle backgrounds |
| **Accent** | Hover states, subtle highlights |
| **Destructive** | Delete buttons, error states |
| **Ring** | Focus indicators, form input focus |
---
## 4. Layout System
### Main Layout Structure
The application uses a **sidebar + content** layout pattern:
```
┌─────────────────────────────┐
│ SidebarProvider │
├──────────┬──────────────────┤
│ │ │
│AppSidebar│ SidebarInset │
│ ├──────────────────┤
│ │ SiteHeader │
│ Logo │ (breadcrumbs) │
│ Nav ├──────────────────┤
│ Items │ │
│ │ Main Content │
│ Footer │ │
│ (User) │ │
│ │ │
└──────────┴──────────────────┘
```
### Layout Implementation
```tsx
// Standard page layout
export default function DashboardClient() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<SiteHeader />
<main className="flex flex-col gap-4 p-4 md:gap-6 md:p-6">
{/* Page content */}
</main>
</SidebarInset>
</SidebarProvider>
);
}
```
### Content Container Sizing
```tsx
// Wide content area with centered max-width
<div className="flex flex-col gap-6 py-4 md:gap-6 md:py-6 px-4 lg:px-16">
{/* Content */}
</div>
// Grid layout patterns
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* Columns adjust: 1 on mobile, 3 on desktop */}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{/* Responsive grid: 1 → 2 → 3 columns */}
</div>
```
---
## 5. Navigation & Sidebar
### AppSidebar Component
Located in `components/app-sidebar.tsx`
**Features:**
- Collapsible sidebar (offcanvas mode on mobile)
- Uses `next-auth` for user session and roles
- Dynamic navigation based on user role (admin/superadmin/user)
- Logo and brand in header
- User profile footer with avatar
**Navigation Items:**
**For Regular Users:**
- Library → `/dashboard`
- Liked Videos → `/dashboard/liked-videos`
- History → `/dashboard/watch-history`
- Search → `#` (secondary item)
**For Admins/Superadmins (Additional):**
- Admin (collapsible parent with submenu):
- Manage Users → `/admin/users`
- Manage Enrollments → `/admin/enrollments`
- Manage Courses → `/admin/courses`
- Manage Playlists → `/admin/playlists`
- Manage Videos → `/admin/videos`
### SiteHeader Component
Located in `components/site-header.tsx`
**Features:**
- Responsive breadcrumb navigation
- Sidebar toggle trigger button
- Dynamic breadcrumbs based on current route
- Breadcrumb mapping for all main routes
**Breadcrumb Pattern:**
```
Dashboard
Dashboard > Liked Videos
Dashboard > Watch History
Admin Panel
Admin Panel > Users > User Details
Admin Panel > Videos > Edit Video
```
### NavMain Component
Located in `components/nav-main.tsx`
**Features:**
- Collapsible menu items with expandable submenus
- Icon support (Tabler icons)
- Smooth transitions with chevron rotation
- Accessible keyboard navigation
```tsx
// Usage
<NavMain
items={[
{
title: 'Dashboard',
url: '/dashboard',
icon: IconDashboard
},
{
title: 'Admin',
url: '/admin',
icon: IconShieldCheck,
items: [
{ title: 'Manage Users', url: '/admin/users' }
]
}
]}
/>
```
### NavSecondary Component
Located in `components/nav-secondary.tsx`
For secondary navigation items (Search, Help, etc.)
### NavUser Component
Located in `components/nav-user.tsx`
**Features:**
- User avatar display
- User name and email
- Dropdown menu with user actions
- Sign out button
- Accessible user menu
---
## 6. Page Layouts
### Login Page
**Location:** `app/login/page.tsx`
**Layout Structure:**
```
Centered Container (min-h-screen, flex-col)
├── Brand Logo + Text (top)
├── Vault Image
└── Login Form (Card with Google OAuth button)
```
**Styling:**
```tsx
<div className="bg-muted flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10">
<div className="flex w-full max-w-sm flex-col gap-6">
{/* Content */}
</div>
</div>
```
**Key Features:**
- Centered, max-width container (sm = 448px)
- Muted background color
- Responsive padding (6 on mobile, 10 on desktop)
- Logo + app name at top
- Vault imagery
- Google OAuth login form in card
### Dashboard Page
**Location:** `app/dashboard/page.tsx` (server) → `dashboard-client.tsx` (client)
**Layout Structure:**
```
Sidebar + Content Layout
├── AppSidebar
└── SidebarInset
├── SiteHeader (breadcrumbs)
└── Main Content
├── Hero Section (Welcome)
├── Video Carousels (by course/playlist)
├── Segmented Progress Bars
└── Lock indicators for restricted content
```
**Content Structure:**
```tsx
<div className="flex flex-col gap-6">
{/* Section: Welcome/Title */}
<div>
<h1 className="text-2xl font-bold">Welcome back, {userName}</h1>
<p className="text-muted-foreground">Continue your learning</p>
</div>
{/* Section: Courses/Playlists with Video Carousels */}
{playlists.map(playlist => (
<div key={playlist.id} className="flex flex-col gap-4">
<h2 className="text-xl font-semibold">{playlist.title}</h2>
<Carousel>
{/* Video cards with progress bars */}
</Carousel>
</div>
))}
</div>
```
### Admin Page
**Location:** `app/admin/page.tsx` (server) → `admin-client.tsx` (client)
**Layout Structure:**
```
Sidebar + Content Layout
├── AppSidebar (with Admin menu)
└── SidebarInset
├── SiteHeader (breadcrumbs)
└── Main Content
├── Page Title & Description
├── Grid of Management Cards (2-3 columns)
│ ├── Video Statistics Card
│ ├── Manage Users Card
│ ├── Manage Courses Card
│ ├── Manage Playlists Card
│ ├── Manage Videos Card
│ └── Manage Enrollments Card
└── Admin Notifications (right sidebar)
```
**Admin Grid Layout:**
```tsx
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{/* Admin cards */}
</div>
</div>
<div className="lg:col-span-1">
<AdminNotifications />
</div>
</div>
```
---
## 7. Component Library
### shadcn/ui Components
The following pre-built components are used throughout the application:
| Component | Used For |
|-----------|----------|
| **Button** | CTAs, form submissions, interactive elements |
| **Card** | Container for content sections |
| **Input** | Text input fields |
| **Label** | Form labels |
| **Badge** | Tags, status indicators, trending indicators |
| **Sidebar** | Main navigation (with collapsible support) |
| **Dropdown Menu** | User menus, action menus |
| **Dialog** | Modal dialogs |
| **Drawer** | Mobile-friendly off-canvas menus |
| **Table** | Data tables with sorting, filtering, pagination |
| **Tabs** | Tab navigation |
| **Carousel** | Image/video sliders |
| **Chart** | Data visualization (AreaChart, BarChart, etc.) |
| **Select** | Dropdown select fields |
| **Checkbox** | Multi-select checkboxes |
| **Form/Field** | Form field containers and validation |
| **Collapsible** | Expandable/collapsible sections |
| **Progress** | Progress bars |
| **Avatar** | User profile pictures |
| **Separator** | Visual dividers |
| **Toast/Sonner** | Toast notifications |
| **Tooltip** | Info tooltips |
### Custom Components
**HlsPlayer** (`components/hls.tsx`)
- HLS video streaming with fallback to MP4
- Subtitle/caption support
- Controls with no-download protection
- Used in: Video player pages
**DataTable** (`components/data-table.tsx`)
- Advanced table with sorting, filtering, pagination
- Column visibility toggle
- Drag-and-drop row reordering (via dnd-kit)
- Export functionality
- Used in: Admin management pages (Users, Videos, Courses, etc.)
**SegmentedProgressBar** (`components/segmented-progress-bar.tsx`)
- Shows watched segments of video
- Visual indication of progress across duration
- Used in: Dashboard video carousels
**VideoCarousel** (`components/VideoCarousel.tsx`)
- Embla carousel-based video slider
- Responsive grid layout
- Lock indicators for restricted content
- Used in: Dashboard, video listings
**CommentsSection** (`components/comments-section.tsx`)
- Comments display and threading
- Used in: Video player pages
**LoginForm** (`components/login-form.tsx`)
- Google OAuth integration
- Card-based layout
- Terms and privacy links
- Used in: Login page
---
## 8. Typography & Spacing
### Font Families
The project uses **Geist** font family (Next.js default):
- `--font-sans: var(--font-geist-sans)` - Primary (body text, UI)
- `--font-mono: var(--font-geist-mono)` - Monospace (code, technical text)
Imported in `layout.tsx`:
```tsx
import { Geist, Geist_Mono } from "next/font/google";
```
### Typography Scale
| Element | Class | Size | Weight | Usage |
|---------|-------|------|--------|-------|
| H1 | `.text-3xl` | 30px | bold (700) | Page titles |
| H2 | `.text-2xl` | 24px | bold (700) | Section titles |
| H3 | `.text-xl` | 20px | semibold (600) | Subsection titles |
| H4 | `.text-lg` | 18px | semibold (600) | Card titles |
| Body | `.text-base` | 16px | normal (400) | Body text |
| Small | `.text-sm` | 14px | normal (400) | Labels, captions, secondary text |
| Extra Small | `.text-xs` | 12px | normal (400) | Tiny labels |
### Spacing Scale
Tailwind default spacing (4px base):
| Class | Size |
|-------|------|
| `gap-1` | 4px |
| `gap-2` | 8px |
| `gap-3` | 12px |
| `gap-4` | 16px |
| `gap-6` | 24px |
| `gap-8` | 32px |
| `p-4` | 16px padding |
| `p-6` | 24px padding |
| `py-4` | 16px vertical padding |
| `px-4` | 16px horizontal padding |
### Text Opacity/Color Hierarchy
```tsx
// Primary text
<p className="text-foreground">Main content</p>
// Secondary text
<p className="text-muted-foreground">Secondary info</p>
// Subtle text
<span className="text-xs text-muted-foreground">Caption</span>
```
---
## 9. Form Patterns
### Login Form Pattern
Located in `components/login-form.tsx`
```tsx
<div className="flex flex-col gap-6">
<Card>
<CardHeader className="text-center">
<CardTitle className="text-xl">Welcome</CardTitle>
<CardDescription>Please login with your account</CardDescription>
</CardHeader>
<CardContent>
<form>
<FieldGroup>
<Field>
<Button
variant="outline"
className="w-full flex items-center justify-center gap-2"
onClick={() => signIn('google')}
>
<GoogleIcon className="w-4 h-4" />
Login with Google
</Button>
</Field>
</FieldGroup>
</form>
</CardContent>
</Card>
<FieldDescription className="text-center">
By continuing, you agree to our <a href="#">Terms of Service</a> and
<a href="#">Privacy Policy</a>
</FieldDescription>
</div>
```
### Admin Form Patterns
Located in `app/admin/*/` directories
**Data Table Integration:**
```tsx
<DataTable
columns={columns}
data={data}
onSave={handleSave}
onDelete={handleDelete}
/>
```
**Modal Form Pattern:**
```tsx
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Create New Item</DialogTitle>
</DialogHeader>
<form>
{/* Form fields */}
</form>
</DialogContent>
</Dialog>
```
---
## 10. Responsive Design
### Tailwind Breakpoints
```
sm: 640px
md: 768px
lg: 1024px
xl: 1280px
2xl: 1536px
```
### Mobile-First Approach
All responsive classes use mobile-first convention:
```tsx
// Mobile: 1 column, Tablet: 2 columns, Desktop: 3 columns
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{/* Content */}
</div>
// Mobile: padding-4, Desktop: padding-6
<main className="p-4 md:p-6">
{/* Content */}
</main>
// Mobile: hidden, Desktop: visible
<aside className="hidden md:block">
{/* Content only on desktop */}
</aside>
```
### Mobile-Specific Components
- **Drawer** - Off-canvas menus on mobile (instead of Dialog)
- **Sidebar Collapsible** - Sidebar collapses to mobile menu on small screens
- **useMobile Hook** - `hooks/use-mobile.ts` for React-based breakpoint logic
```tsx
const isMobile = useIsMobile();
return isMobile ? <MobileLayout /> : <DesktopLayout />;
```
### Container Queries
Used for responsive component sizing:
```tsx
<div className="@container">
<h1 className="@[250px]:text-3xl text-2xl">
Responsive heading
</h1>
</div>
```
---
## 11. Dark Mode Implementation
### Theme Provider Setup
Located in `app/providers.tsx`:
```tsx
<ThemeProvider
attribute="class" // Toggles 'class' on <html>
defaultTheme="dark" // Dark by default
enableSystem={false} // Don't auto-detect system preference
>
{children}
</ThemeProvider>
```
### Dark Mode Styling
CSS variables automatically switch in `.dark` class:
```tsx
// Light mode (automatic)
:root {
--background: oklch(1 0 0); /* White */
--foreground: oklch(0.141 0.005 285.823); /* Dark gray */
}
// Dark mode (when .dark is on <html>)
.dark {
--background: oklch(0.141 0.005 285.823); /* Dark gray */
--foreground: oklch(0.985 0 0); /* White */
}
```
### Toggle Theme Button Pattern
```tsx
// In component
const { theme, setTheme } = useTheme();
<Button
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
>
{theme === 'dark' ? <SunIcon /> : <MoonIcon />}
</Button>
```
---
## 12. Reusable Patterns
### Protected Page Pattern
**Server Component (checks auth):**
```tsx
// app/dashboard/page.tsx
import { requireUser } from '@/lib/auth-check';
import DashboardClient from './dashboard-client';
export default async function DashboardPage() {
const session = await requireUser('/login');
return <DashboardClient />;
}
```
**Client Component (renders content):**
```tsx
// app/dashboard/dashboard-client.tsx
'use client';
import React from 'react';
import { AppSidebar } from '@/components/app-sidebar';
import { SiteHeader } from '@/components/site-header';
export default function DashboardClient() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<SiteHeader />
<main /* content */>
</SidebarInset>
</SidebarProvider>
);
}
```
### Role-Based Navigation
Located in `components/app-sidebar.tsx`:
```tsx
const { data: session } = useSession();
const role = session?.user?.role ?? 'user';
const navMain = React.useMemo(() => {
const base = [...navMainBase];
if (role === 'admin' || role === 'superadmin') {
base.unshift({
title: 'Admin',
url: '/admin',
icon: IconShieldCheck,
items: [/*submenu items*/]
});
}
return base;
}, [role]);
```
### Session Initialization
Located in `app/layout.tsx`:
```tsx
export default async function RootLayout({ children }) {
// Get server session once, pass to client providers
const session = await getServerSession(authOptions);
return (
<html>
<body>
<Providers session={session}>
{children}
</Providers>
<Toaster />
</body>
</html>
);
}
```
### Data Fetching Pattern
Using `useFetch`/SWR for client-side data:
```tsx
// hooks/usePlaylists.ts
export function usePlaylists() {
const [subjects, setSubjects] = React.useState([]);
const [isLoading, setIsLoading] = React.useState(true);
React.useEffect(() => {
fetchPlaylists().then(data => {
setSubjects(data);
setIsLoading(false);
});
}, []);
return { subjects, isLoading };
}
// Usage in component
export default function DashboardClient() {
const { subjects, isLoading } = usePlaylists();
if (isLoading) return <LoadingState />;
return <>{/* Content */}</>;
}
```
### Carousel Pattern
```tsx
// Embla-based carousel
<Carousel className="w-full">
<CarouselContent className="gap-4">
{videos.map(video => (
<CarouselItem key={video.id} className="basis-1/2 md:basis-1/3 lg:basis-1/4">
<VideoCard video={video} />
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
```
### Badge & Status Pattern
```tsx
// Icon + Badge combination
<div className="flex items-center gap-2">
<Badge variant="outline">
<IconTrendingUp className="size-4" />
+12.5%
</Badge>
</div>
// Status badge
<Badge variant={status === 'active' ? 'default' : 'secondary'}>
{status}
</Badge>
```
---
## 13. Asset Guidelines
### Logo & Branding
- **Icon**: `/public/icon.svg` - Small 5x5 size in sidebar header
- **Vault Image**: `/public/vault.png` - 1:1 aspect ratio for login page
- **High-Res Alternative**: `/public/vault.exr` - For promotional use
### Image Optimization
```tsx
// Use Next.js Image for optimization
import Image from 'next/image';
<Image
src="/path/to/image.png"
alt="Description"
width={400}
height={300}
quality={60}
/>
// Regular images
<img src="/icon.svg" alt="Icon" className="size-5" />
```
### Approved Icon Sets
1. **Tabler Icons** (`@tabler/icons-react`) - Primary
- Large collection (4000+)
- Consistent stroke weight
- Import: `import { IconHome, IconUsers } from '@tabler/icons-react';`
2. **Lucide React** (`lucide-react`) - Secondary
- Modern, clean icons
- Import: `import { Home, Users } from 'lucide-react';`
3. **SVG Files** - Custom branding
- Small icons in public/
- Optimized for performance
### Sizing Conventions
```tsx
// Icon sizes
<Icon className="size-3" /> /* 12px */
<Icon className="size-4" /> /* 16px */
<Icon className="size-5" /> /* 20px */
<Icon className="w-6 h-6" /> /* 24px */
<Icon className="w-8 h-8" /> /* 32px */
// Image sizes
<Image className="w-full" /> /* Full width */
<Image className="max-w-sm" /> /* Max 448px */
<Image className="max-w-md" /> /* Max 512px */
```
---
## Quick Reference - Common Patterns
### Button Variants
```tsx
<Button>Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Delete</Button>
<Button disabled>Disabled</Button>
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
```
### Card Layout
```tsx
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
<CardDescription>Subtitle</CardDescription>
</CardHeader>
<CardContent>
{/* Content */}
</CardContent>
<CardFooter>
{/* Footer */}
</CardFooter>
</Card>
```
### Container Classes
```tsx
// Full width
className="w-full"
// Max width containers
className="w-full max-w-sm" /* 448px */
className="w-full max-w-md" /* 512px */
className="w-full max-w-lg" /* 576px */
className="w-full max-w-2xl" /* 672px */
// Flex containers
className="flex flex-col gap-4"
className="flex items-center justify-between"
// Grid containers
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"
```
### Responsive Padding
```tsx
className="p-4 md:p-6 lg:p-8" /* All sides */
className="px-4 py-6" /* Horizontal & vertical */
className="p-4 md:py-6 md:px-8" /* Different per breakpoint */
```
### Text & Styling
```tsx
className="text-foreground" /* Main text */
className="text-muted-foreground" /* Secondary text */
className="text-sm text-muted-foreground" /* Label text */
className="font-semibold" /* Bold text */
className="line-clamp-1" /* Truncate to 1 line */
className="text-center" /* Centered text */
```
---
## Migration Checklist for New Projects
When creating a new app with this design system:
- [ ] Copy `globals.css` (CSS variables)
- [ ] Copy `tailwind.config.cjs`
- [ ] Copy `components/ui/` directory (all base components)
- [ ] Copy `components/app-sidebar.tsx`, `site-header.tsx`, `nav-*.tsx`
- [ ] Copy `app/providers.tsx` (SessionProvider, ThemeProvider)
- [ ] Copy `lib/utils.ts` (utility functions)
- [ ] Copy `lib/auth-options.ts` and auth-related files
- [ ] Install dependencies from `package.json`
- [ ] Update branding assets (/public icons, logos)
- [ ] Customize navigation items in `app-sidebar.tsx`
- [ ] Update theme colors in `globals.css` if needed
- [ ] Test responsive design on mobile/tablet/desktop
---
## Key Takeaways
1. **Framework**: Next.js 16 with shadcn/ui component library
2. **Styling**: Tailwind CSS with OKLch color variables
3. **Layout**: Sidebar + content pattern with collapsible nav
4. **Dark Mode**: CSS class-based switching with automatic variable updates
5. **Components**: Pre-built shadcn/ui components + custom components (HLS, DataTable, etc.)
6. **Responsiveness**: Mobile-first, Tailwind breakpoints (sm/md/lg/xl)
7. **Navigation**: Role-based dynamic nav, breadcrumb system
8. **Auth**: NextAuth.js with Google OAuth integration
9. **Icons**: Tabler Icons (primary), Lucide (secondary)
10. **Consistency**: Use className patterns, spacing scale, and color variables throughout
---
**Last Updated**: February 2026
**Version**: 1.0
For questions or updates to this design system guide, refer to the component files and config files referenced throughout.