Files
frontend/layouts/LAYOUTS.md
T
Thanh Quy - wolf dae381d182 Enhance Atoms and Layout Documentation
- Updated ATOMS.md to include new LoginInput and ErrorMessageLogin components with detailed usage examples and props descriptions.
- Adjusted the status and created date in ATOMS.md.
- Refined the layout and styling descriptions in LAYOUTS.md for Header and Footer components, including responsive behavior and accessibility improvements.
- Added new sections for WiFi card and social links in the Footer documentation.
- Improved code formatting and consistency across various components in the codebase.
2026-04-18 11:13:53 +07:00

17 KiB

Layouts Documentation

Tài liệu chi tiết về layout components (Header, Footer) và responsive behavior

Last Updated: 2026-04-18


Overview

The layouts/ directory contains layout-level components used across all pages. These are included in the root layout and provide consistent header/footer across the application.

layouts/
├── header.tsx      # Sticky top header with shop branding and auth
├── footer.tsx      # Footer with shop info, social links, WiFi details
└── LAYOUTS.md     # (this file)

Header (layouts/header.tsx)

File: layouts/header.tsx Type: Client component ("use client") Description: Sticky top navigation bar with brand info and authentication status display. Uses useAuth() context for real auth state and useRouter() for navigation.

Layout

┌─────────────────────────────────────────────────────┐
│  [Logo] [Shop Name] [Tagline]  │  [Auth Button(s)]  │
└─────────────────────────────────────────────────────┘
height: var(--spacing-header-height)  (72px)

2-Column Layout:

  • Left: Shop branding (logo + name + tagline) — wrapped in <Link href="/">
  • Right: Auth status indicator (varies by user role)

Features

Logo & Branding

  • Shop logo rendered with next/image (fill, 40x40px / 44x44px on md+)
  • Shop name (bold, color transitions on hover)
  • Tagline (hidden on mobile < md, visible md+)
  • Entire left section is a link to /

Responsive:

Breakpoint Logo Name Tagline
< sm (640px) h-10/w-10 Yes Hidden
sm-md h-10/w-10 Yes Hidden
md+ (768px) h-11/w-11 Yes Visible

Authentication Status

The header reads from useAuth() and reflects the actual logged-in user role.

State 1: Guest (user = null)

[brown button] "Đăng nhập"   ← icon always shown, label hidden on xs
  • title="Đăng nhập" on button
  • Clicking navigates to /login
  • Icon: fa-solid fa-right-to-bracket

State 2: Manager (user.role === "manager")

[Dashboard link] [Logout icon button]
  • Dashboard link → /manager
  • Icon: fa-solid fa-user-tie
  • Label "Dashboard" hidden on xs, visible sm+
  • Logout button: title="Đăng xuất", aria-label="Đăng xuất"
  • Logout icon: fa-solid fa-right-from-bracket
  • Hover: red tint on logout button

State 3: Staff (user.role === "staff")

[Ca làm link] [Avatar + Name button (logout on click)]
  • Ca làm link → /staff/schedule
  • Icon: fa-solid fa-calendar-check
  • Label "Ca làm" hidden on xs, visible sm+
  • Staff button: title="Nhấn để đăng xuất", aria-label="Đăng xuất"
  • Avatar: colored circle with fa-solid fa-user
  • Name hidden on xs, visible sm+

State 4: Customer (user.role === "customer")

[Customer icon + "Khách hàng" button (logout on click)]
  • title="Khách hàng - {user.phone} - Nhấn để đăng xuất"
  • Avatar circle with fa-solid fa-user
  • Label "Khách hàng" hidden on xs, visible sm+

Responsive Behavior

Breakpoint Layout
< sm (640px) Button labels hidden, icons only
sm-md (640px) Button labels visible, reduced spacing
md+ (768px) Full layout including tagline

Mobile (<640px):

  • Logo 40x40px
  • Shop name only (no tagline)
  • Auth button shows icon only (label hidden via hidden sm:inline)
  • Touch-friendly padding

Desktop (≥768px):

  • Logo 44x44px
  • Full layout with tagline
  • Buttons show icon + text label
  • Comfortable spacing

Accessibility

  • Logo image: alt="Logo {SHOP_INFO.name}"
  • Guest button: title="Đăng nhập"
  • Manager logout button: title="Đăng xuất", aria-label="Đăng xuất"
  • Staff logout button: title="Nhấn để đăng xuất", aria-label="Đăng xuất"
  • Customer button: title="Khách hàng - {phone} - Nhấn để đăng xuất"
  • Icons are presentational (no aria-hidden needed — buttons have title/aria-label)

Styling

Element Classes
Header wrapper sticky top-0 z-50 h-(--spacing-header-height) w-full border-b bg-(--color-bg-header) shadow-[...]
Container mx-auto flex h-full max-w-screen-2xl items-center justify-between gap-6 px-6 md:px-8 lg:px-12
Left section (brand) group flex shrink-0 items-center gap-4 no-underline (Link)
Logo wrapper relative h-10 w-10 shrink-0 md:h-11 md:w-11
Brand text text-base font-bold text-(--color-primary-dark) md:text-lg
Tagline hidden text-xs text-(--color-text-muted) md:block
Right section (auth) flex shrink-0 items-center gap-3
Guest button flex items-center gap-2.5 rounded-xl bg-(--color-primary) px-5 py-2.5 text-sm font-semibold text-white
Manager link flex items-center gap-2 rounded-xl border border-(--color-accent) bg-(--color-accent-light)
Logout button flex items-center gap-2 rounded-xl border border-(--color-border) bg-transparent px-3 py-2.5 hover:border-red-300 hover:bg-red-50 hover:text-red-500
Staff button flex items-center gap-2.5 rounded-xl border border-(--color-border) bg-background
Customer button flex items-center gap-2.5 rounded-xl bg-(--color-primary-light) px-4 py-2 text-white

CSS Variables Used

--spacing-header-height     /* 72px — header height */
--color-bg-header           /* header background */
--color-border              /* border color */
--color-shadow-sm           /* subtle shadow */
--color-primary             /* brand primary (brown) */
--color-primary-dark        /* darker brown */
--color-primary-light       /* lighter brown */
--color-accent              /* accent/gold color */
--color-accent-light        /* light accent background */
--color-text-muted          /* gray/muted text */
--color-text-secondary      /* secondary text color */
--color-border-light        /* light border */

Dependencies

  • next/image — Logo image rendering
  • next/link — Brand link, dashboard link, schedule link
  • next/navigationuseRouter for programmatic navigation
  • lib/auth-context: useAuth — user state, logout
  • lib/constants: SHOP_INFO

File: layouts/footer.tsx Type: Server component (no "use client") Description: Site footer with shop information, social links, and WiFi details. Copyright year is dynamic via new Date().getFullYear().

Layout

┌────────────────────────────────────────────────────────────────┐
│  [Brand Info]              │  [Social + WiFi]                  │
├────────────────────────────────────────────────────────────────┤
│  © {year} Coffee Shop. All rights reserved.  |  Powered by ... │
└────────────────────────────────────────────────────────────────┘

12-Column Grid Layout:

Breakpoint Brand Info Right column (Social + WiFi)
Mobile col-span-12 col-span-12
md (768px) col-span-6 col-span-6
lg+ (1024px) col-span-8 col-span-4
xl+ col-span-6 col-span-6 (with 2-col sub-grid)

The right column (Social + WiFi) uses an internal sub-grid:

  • Mobile/lg: stacked (1 column)
  • xl+: side-by-side (2 columns)

Sections

1. Brand Info (Left Section)

Content:

  • Shop logo (40x40px, next/image)
  • Shop name (bold, accent color)
  • Tagline (gray, 75% opacity)
  • Address with fa-solid fa-location-dot
  • Phone (clickable tel: link) with fa-solid fa-phone
  • Email (clickable mailto: link) with fa-solid fa-envelope
  • Open hours with fa-solid fa-clock

Links (heading: "Kết nối"):

  • Facebook → SOCIAL_LINKS.facebook (branded blue icon, opens _blank)
  • TikTok → SOCIAL_LINKS.tiktok (black icon, opens _blank)
  • Website → SOCIAL_LINKS.website (primary color icon, uses next/link)

Styling:

  • Each item: icon badge (8x8 rounded-lg) + label text
  • Hover: accent color + full opacity

3. WiFi Card

Content (heading: "WiFi Miễn Phí"):

  • WiFi icon (fa-solid fa-wifi)
  • Network name (monospace, accent-bordered)
  • Password (monospace, accent-bordered, always visible — no toggle)

Note: Current implementation shows password in plain text (no hide/show toggle). This differs from older documentation.

Styling:

  • Semi-transparent dark panel (bg-(--color-primary-dark) bg-opacity-30)
  • Rounded xl border
  • Stacked label + value rows (no overflow risk)
  • Monospace font for credentials

4. Bottom Bar

Content:

  • Left: © {year} {SHOP_INFO.name}. All rights reserved.
  • Right: Được vận hành ❤ bằng Drinkool
  • Responsive: stacked on mobile, side-by-side on sm+

Responsive Behavior

Mobile (<768px):

  • Single column layout
  • Stacked sections (brand, then social+WiFi)
  • Full width

Tablet (768px):

  • 2-column: brand (6 cols) | social+WiFi (6 cols)
  • Social and WiFi stacked within right column

Desktop (≥1024px):

  • Brand 8 cols, right 4 cols
  • Social and WiFi stacked in right col

XL (≥1280px):

  • Brand 6 cols, right 6 cols
  • Social and WiFi side-by-side in right col sub-grid

Styling

Element Classes
Footer wrapper w-full overflow-x-hidden bg-(--color-bg-footer) text-(--color-text-on-dark)
Container mx-auto max-w-screen-2xl px-4 py-10 md:px-6 lg:px-8
Grid grid grid-cols-12 gap-x-8 gap-y-8
Brand section col-span-12 md:col-span-6 lg:col-span-8 xl:col-span-6
Right section col-span-12 grid grid-cols-1 gap-6 md:col-span-6 lg:col-span-4 xl:col-span-6 xl:grid-cols-2
Logo relative h-10 w-10 shrink-0
Shop name text-lg font-bold text-(--color-accent)
Tagline text-sm leading-relaxed opacity-75
Contact list flex flex-col gap-2 text-sm opacity-80
Social icon badge flex h-8 w-8 shrink-0 items-center justify-center rounded-lg
WiFi card rounded-xl border border-(--color-primary-light) bg-(--color-primary-dark) p-4
WiFi value rounded border border-(--color-accent) px-2 py-1 font-mono font-bold text-(--color-accent)
Bottom bar border-t border-white border-opacity-10
Copyright row mx-auto flex max-w-screen-2xl flex-col sm:flex-row items-center justify-between gap-2 px-4 py-4 text-xs opacity-50

CSS Variables Used

--color-bg-footer           /* dark footer background */
--color-text-on-dark        /* light text for dark backgrounds */
--color-accent              /* accent/gold color */
--color-primary             /* brand primary (brown) */
--color-primary-dark        /* darker brown */
--color-primary-light       /* lighter brown */
--color-border              /* border color */

Dependencies

  • next/image — Shop logo
  • next/link — Website social link
  • lib/constants: SHOP_INFO, SOCIAL_LINKS
  • FontAwesome icons: location-dot, phone, envelope, clock, fa-brands fa-facebook-f, fa-brands fa-tiktok, globe, wifi, heart

Integration in Root Layout

File: app/layout.tsx

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <Header />
        {children}
        <Footer />
      </body>
    </html>
  );
}

Result:

  • Header: Always at top (sticky, z-50)
  • Content: Takes full width between header/footer
  • Footer: Always at bottom

Responsive Design Patterns

Header Responsive Pattern

/* Mobile first — icon-only auth buttons */
.header-auth-label {
  display: none; /* hidden on xs */
}

/* sm+ — show button labels */
@media (min-width: 640px) {
  .header-auth-label {
    display: inline; /* hidden sm:inline */
  }
}

/* md+ — show tagline */
@media (min-width: 768px) {
  .tagline {
    display: block; /* hidden md:block */
  }
}
/* Mobile: single column */
.footer-grid {
  grid-template-columns: repeat(12, 1fr);
}

/* md: brand 6 cols, right 6 cols */
/* lg: brand 8 cols, right 4 cols */
/* xl: brand 6 cols, right 6 cols — right col uses xl:grid-cols-2 */

Dark Mode Support

CSS variables are set up for dark mode support. To enable:

  1. Add dark mode CSS variable overrides:
@media (prefers-color-scheme: dark) {
  :root {
    --color-bg-main: #1a1a1a;
    --color-text-primary: #ffffff;
    /* etc */
  }
}
  1. Or use Tailwind dark class:
<div className="dark:bg-gray-900 dark:text-white">Content</div>

Accessibility

Header

  • Logo image has descriptive alt text: "Logo {SHOP_INFO.name}"
  • Guest button: title="Đăng nhập"
  • Manager logout button: title="Đăng xuất" + aria-label="Đăng xuất"
  • Staff logout button: title="Nhấn để đăng xuất" + aria-label="Đăng xuất"
  • Customer button: title="Khách hàng - {phone} - Nhấn để đăng xuất"
  • Interactive elements have hover and active states (visual feedback)
  • Touch targets are sized appropriately (px-4/5 + py-2/2.5)
  • Phone and email are clickable <a> links (tel:, mailto:)
  • Social links open in _blank with rel="noopener noreferrer"
  • Section headings use <h3> semantic tags
  • Icons are decorative within labelled list items
  • WiFi credentials in monospace font for readability

General

  • Touch targets ≥ 44px (py-2.5 + px-4/5 buttons)
  • active:scale-95 on interactive buttons for tactile feedback
  • Semantic HTML structure (<header>, <footer>, <nav> implicit via links)
  • ARIA labels on icon-only buttons (logout buttons)

Best Practices

  1. Keep layouts simple: Avoid complex nested layouts
  2. Responsive first: Use mobile-first CSS approach (hidden sm:inline)
  3. Reuse components: Use Header/Footer across all pages
  4. Props over hardcoding: Use lib/constants for data
  5. Type safety: Use TypeScript for component props
  6. Performance: Optimize images with next/image (fill, sizes, priority)
  7. Accessibility: Add title/aria-label on icon-only buttons