- 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.
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/navigation —
useRouterfor programmatic navigation - lib/auth-context:
useAuth— user state, logout - lib/constants:
SHOP_INFO
Footer (layouts/footer.tsx)
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) withfa-solid fa-phone - Email (clickable
mailto:link) withfa-solid fa-envelope - Open hours with
fa-solid fa-clock
2. Social Links
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, usesnext/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 */
}
}
Footer Responsive Pattern
/* 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:
- Add dark mode CSS variable overrides:
@media (prefers-color-scheme: dark) {
:root {
--color-bg-main: #1a1a1a;
--color-text-primary: #ffffff;
/* etc */
}
}
- Or use Tailwind dark class:
<div className="dark:bg-gray-900 dark:text-white">Content</div>
Accessibility
Header
- Logo image has descriptive
alttext:"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)
Footer
- Phone and email are clickable
<a>links (tel:,mailto:) - Social links open in
_blankwithrel="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-95on interactive buttons for tactile feedback- Semantic HTML structure (
<header>,<footer>,<nav>implicit via links) - ARIA labels on icon-only buttons (logout buttons)
Best Practices
- Keep layouts simple: Avoid complex nested layouts
- Responsive first: Use mobile-first CSS approach (
hidden sm:inline) - Reuse components: Use Header/Footer across all pages
- Props over hardcoding: Use lib/constants for data
- Type safety: Use TypeScript for component props
- Performance: Optimize images with next/image (
fill,sizes,priority) - Accessibility: Add title/aria-label on icon-only buttons