Bluewoo HRMS
Design System

Layouts

Sidebar, TopBar, and page structure patterns

Layout Patterns

This document defines the layout components and page structure for HRMS.

App Shell Structure

The HRMS app uses a standard dashboard layout:

┌─────────────────────────────────────────────────────────┐
│                      TopBar                              │
├──────────┬──────────────────────────────────────────────┤
│          │                                              │
│ Sidebar  │           Main Content Area                  │
│  (w-64)  │           (bg-background)                    │
│          │                                              │
│          │                                              │
└──────────┴──────────────────────────────────────────────┘
                        ┌────┐
                        │ AI │  (Fixed bottom-right)
                        └────┘

Desktop Sidebar (Theme-Aware)

The sidebar is theme-aware: white in light mode, dark gray in dark mode.

<aside className="
  bg-card text-card-foreground
  w-64 h-screen
  flex flex-col
  border-r border-border
  shadow-2xl shadow-black/5
">
  {/* Logo Section */}
  <div className="h-16 flex items-center px-6 border-b border-border">
    <span className="text-xl font-bold text-foreground">HRMS</span>
  </div>

  {/* Navigation */}
  <nav className="flex-1 px-3 py-4 space-y-1 overflow-y-auto">
    {/* Active Navigation Item */}
    <a className="
      flex items-center gap-3 px-3 py-2
      bg-primary text-white
      rounded-lg
      shadow-md shadow-primary/20
    ">
      <LayoutDashboard className="w-5 h-5" />
      <span className="font-medium">Dashboard</span>
    </a>

    {/* Inactive Navigation Item */}
    <a className="
      flex items-center gap-3 px-3 py-2
      text-muted-foreground
      rounded-lg
      hover:bg-accent hover:text-foreground
      transition-colors
    ">
      <Users className="w-5 h-5" />
      <span>Employees</span>
    </a>

    {/* Navigation items... */}
  </nav>

  {/* User Profile Section */}
  <div className="p-4 border-t border-border">
    <div className="flex items-center gap-3">
      <Avatar className="h-9 w-9">
        <AvatarImage src="/avatar.jpg" />
        <AvatarFallback>JD</AvatarFallback>
      </Avatar>
      <div className="flex-1 min-w-0">
        <p className="text-sm font-medium truncate">John Doe</p>
        <p className="text-xs text-muted-foreground truncate">HR Manager</p>
      </div>
      <Button variant="ghost" size="icon" className="shrink-0">
        <LogOut className="h-4 w-4" />
      </Button>
    </div>
  </div>
</aside>
StateBackgroundTextShadow
Activebg-primarytext-whiteshadow-md shadow-primary/20
Inactivetransparenttext-muted-foregroundnone
Hoverbg-accenttext-foregroundnone

Mobile Sidebar (Sheet)

On mobile, the sidebar becomes a slide-out drawer:

<Sheet>
  <SheetTrigger asChild>
    <Button variant="ghost" size="icon" className="md:hidden">
      <Menu className="h-5 w-5" />
    </Button>
  </SheetTrigger>
  <SheetContent side="left" className="w-64 p-0">
    {/* Same sidebar content */}
  </SheetContent>
</Sheet>

TopBar

The TopBar is sticky with backdrop blur:

<header className="
  sticky top-0 z-20
  w-full h-16
  bg-background/80 backdrop-blur-md
  border-b border-border
  px-4 sm:px-6
  flex items-center justify-between
">
  {/* Left: Mobile menu + Search */}
  <div className="flex items-center gap-4">
    {/* Mobile menu button (hidden on desktop) */}
    <Button variant="ghost" size="icon" className="md:hidden">
      <Menu className="h-5 w-5" />
    </Button>

    {/* Search */}
    <div className="relative hidden sm:block">
      <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
      <Input
        placeholder="Search..."
        className="pl-9 w-64 bg-muted/50"
      />
    </div>
  </div>

  {/* Right: Actions */}
  <div className="flex items-center gap-2">
    {/* Quick action button */}
    <Button size="sm" className="hidden sm:flex">
      <Plus className="h-4 w-4 mr-1" />
      Quick Add
    </Button>

    {/* Theme toggle */}
    <Button variant="ghost" size="icon">
      <Sun className="h-5 w-5 dark:hidden" />
      <Moon className="h-5 w-5 hidden dark:block" />
    </Button>

    {/* Notifications */}
    <Button variant="ghost" size="icon" className="relative">
      <Bell className="h-5 w-5" />
      <span className="absolute -top-1 -right-1 h-4 w-4 bg-destructive text-destructive-foreground text-xs rounded-full flex items-center justify-center">
        3
      </span>
    </Button>
  </div>
</header>

TopBar Styling

PropertyValue
Heighth-16 (64px)
Backgroundbg-background/80 backdrop-blur-md
Borderborder-b border-border
Positionsticky top-0 z-20

Main Content Area

<main className="
  flex-1
  bg-background
  p-6 lg:p-8
  overflow-y-auto
">
  {/* Page Header */}
  <div className="mb-8">
    <h1 className="text-2xl font-semibold tracking-tight">Dashboard</h1>
    <p className="text-muted-foreground">Welcome back, John!</p>
  </div>

  {/* Stats Grid */}
  <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
    <StatsCard ... />
    <StatsCard ... />
    <StatsCard ... />
    <StatsCard ... />
  </div>

  {/* Content Grid */}
  <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
    <ContentCard className="lg:col-span-2" />
    <ContentCard />
  </div>
</main>

Content Spacing

ElementSpacing
Page padding (desktop)p-6 lg:p-8
Page padding (mobile)p-4
Section marginmb-8
Card grid gapgap-6

App Shell Component

Complete layout wrapper:

export function AppShell({ children }: { children: React.ReactNode }) {
  return (
    <div className="min-h-screen flex bg-background">
      {/* Sidebar - hidden on mobile */}
      <aside className="hidden md:flex md:w-64 md:flex-col md:fixed md:inset-y-0">
        <Sidebar />
      </aside>

      {/* Main content area */}
      <div className="flex-1 md:pl-64">
        <TopBar />
        <main className="p-6 lg:p-8">
          {children}
        </main>
      </div>

      {/* AI Floating Button */}
      <AIButton />
    </div>
  );
}

AI Floating Button

Always visible in bottom-right corner:

<motion.button
  className="
    fixed z-50
    bottom-6 right-6 md:bottom-8 md:right-8
    w-14 h-14 rounded-full
    bg-gradient-to-br from-violet-500 via-purple-500 to-fuchsia-500
    text-white
    shadow-xl shadow-violet-500/30
    hover:shadow-2xl hover:shadow-violet-500/40
    hover:scale-105 active:scale-95
    transition-all duration-200
    flex items-center justify-center
  "
  initial={{ scale: 0.8, opacity: 0 }}
  animate={{ scale: 1, opacity: 1 }}
  whileHover={{ scale: 1.05 }}
  whileTap={{ scale: 0.95 }}
>
  <Sparkles className="w-6 h-6" />
</motion.button>

AI Button Position

Screen SizePosition
Mobilebottom-6 right-6
Desktopbottom-8 right-8

Responsive Breakpoints

Using Tailwind's default breakpoints:

BreakpointMin WidthUsage
sm640pxShow search, quick actions
md768pxShow sidebar (fixed)
lg1024pxLarger content padding
xl1280pxFull dashboard grid
2xl1536pxMax content width

Responsive Patterns

// Sidebar visibility
className="hidden md:flex"

// Grid columns
className="grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"

// Padding
className="p-4 sm:p-6 lg:p-8"

// Content span
className="col-span-1 lg:col-span-2"

Page Templates

Dashboard Page

export default function DashboardPage() {
  return (
    <>
      {/* Page Header */}
      <div className="mb-8">
        <h1 className="text-2xl font-semibold tracking-tight">Dashboard</h1>
        <p className="text-muted-foreground">Overview of your HR metrics</p>
      </div>

      {/* Stats Row */}
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
        <StatsCard
          title="Total Employees"
          value="156"
          icon={Users}
          gradient="from-blue-500 to-blue-600"
        />
        {/* ... more stats cards */}
      </div>

      {/* Content Grid */}
      <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
        <ContentCard title="Recent Activity" className="lg:col-span-2">
          {/* ... */}
        </ContentCard>
        <ContentCard title="Quick Actions">
          {/* ... */}
        </ContentCard>
      </div>
    </>
  );
}

List Page (e.g., Employees)

export default function EmployeesPage() {
  return (
    <>
      {/* Page Header with Action */}
      <div className="flex items-center justify-between mb-8">
        <div>
          <h1 className="text-2xl font-semibold tracking-tight">Employees</h1>
          <p className="text-muted-foreground">Manage your team members</p>
        </div>
        <Button>
          <Plus className="w-4 h-4 mr-2" />
          Add Employee
        </Button>
      </div>

      {/* Filters/Search */}
      <ContentCard className="mb-6">
        <div className="flex gap-4">
          <Input placeholder="Search employees..." className="max-w-xs" />
          <Select>
            <SelectTrigger className="w-40">
              <SelectValue placeholder="Department" />
            </SelectTrigger>
            {/* ... */}
          </Select>
        </div>
      </ContentCard>

      {/* Data Table */}
      <ContentCard>
        <Table>
          {/* ... */}
        </Table>
      </ContentCard>
    </>
  );
}

Detail Page (e.g., Employee Profile)

export default function EmployeeDetailPage() {
  return (
    <>
      {/* Back Link */}
      <Button variant="ghost" className="mb-4">
        <ChevronLeft className="w-4 h-4 mr-1" />
        Back to Employees
      </Button>

      {/* Profile Header Card */}
      <ContentCard className="mb-6">
        <div className="flex items-start gap-6">
          <Avatar className="w-20 h-20">
            <AvatarImage src="/avatar.jpg" />
            <AvatarFallback>JD</AvatarFallback>
          </Avatar>
          <div className="flex-1">
            <h1 className="text-2xl font-semibold">John Doe</h1>
            <p className="text-muted-foreground">Senior Developer</p>
            <div className="flex gap-2 mt-2">
              <Badge>Engineering</Badge>
              <Badge variant="outline">Full-time</Badge>
            </div>
          </div>
          <Button>Edit Profile</Button>
        </div>
      </ContentCard>

      {/* Tabbed Content */}
      <Tabs defaultValue="overview">
        <TabsList>
          <TabsTrigger value="overview">Overview</TabsTrigger>
          <TabsTrigger value="documents">Documents</TabsTrigger>
          <TabsTrigger value="time-off">Time Off</TabsTrigger>
        </TabsList>
        <TabsContent value="overview">
          {/* ... */}
        </TabsContent>
      </Tabs>
    </>
  );
}