Files
ColaFlow/docs/design/responsive-design-guide.md
Yaojia Wang fe8ad1c1f9
Some checks failed
Code Coverage / Generate Coverage Report (push) Has been cancelled
Tests / Run Tests (9.0.x) (push) Has been cancelled
Tests / Docker Build Test (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
In progress
2025-11-03 11:51:02 +01:00

1334 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Responsive Design Guide
## Document Overview
This document defines responsive design patterns, breakpoints, and mobile-first strategies for ColaFlow's multi-tenant, SSO, and MCP Token management features.
**Version:** 1.0
**Last Updated:** 2025-11-03
**Tech Stack:** Tailwind CSS 4 + Next.js 16 (App Router)
**Owner:** UX/UI Team
---
## Table of Contents
1. [Breakpoint System](#breakpoint-system)
2. [Mobile-First Approach](#mobile-first-approach)
3. [Registration Flow Responsive Patterns](#registration-flow-responsive-patterns)
4. [Login Pages Responsive Design](#login-pages-responsive-design)
5. [SSO Configuration Responsive Layout](#sso-configuration-responsive-layout)
6. [MCP Token Management Mobile Views](#mcp-token-management-mobile-views)
7. [Component Adaptations](#component-adaptations)
8. [Performance Considerations](#performance-considerations)
---
## Breakpoint System
### Tailwind CSS Breakpoints
Following Tailwind's default breakpoints with custom extensions:
```typescript
// tailwind.config.ts
const screens = {
'xs': '480px', // Extra small devices (large phones)
'sm': '640px', // Small devices (tablets)
'md': '768px', // Medium devices (landscape tablets)
'lg': '1024px', // Large devices (laptops)
'xl': '1280px', // Extra large devices (desktops)
'2xl': '1536px', // 2X large devices (large desktops)
}
```
### Device Categories
| Breakpoint | Range | Device Type | Typical Width |
|------------|-------|-------------|---------------|
| **xs** | 480px - 639px | Large phones | 480px - 640px |
| **sm** | 640px - 767px | Small tablets | 640px - 768px |
| **md** | 768px - 1023px | Tablets | 768px - 1024px |
| **lg** | 1024px - 1279px | Laptops | 1024px - 1280px |
| **xl** | 1280px - 1535px | Desktops | 1280px - 1536px |
| **2xl** | 1536px+ | Large desktops | 1536px+ |
### Container Max-Widths
```typescript
// Container sizes per breakpoint
const container = {
center: true,
padding: {
DEFAULT: '1rem', // 16px
sm: '2rem', // 32px
lg: '4rem', // 64px
xl: '5rem', // 80px
'2xl': '6rem', // 96px
},
screens: {
sm: '640px',
md: '768px',
lg: '1024px',
xl: '1280px',
'2xl': '1536px',
},
}
```
---
## Mobile-First Approach
### Core Principles
1. **Start with mobile** (320px+) as the base
2. **Progressive enhancement** for larger screens
3. **Touch-friendly** targets (min 44x44px)
4. **Readable typography** (min 16px body text)
5. **Simplified navigation** on small screens
### Example Pattern
```tsx
// Mobile-first Tailwind classes
<div className="
w-full px-4 py-6 // Mobile default
sm:px-6 sm:py-8 // Small tablets
md:max-w-2xl md:mx-auto // Medium screens
lg:max-w-4xl // Large screens
">
{/* Content */}
</div>
```
### CSS Custom Properties
```css
:root {
--spacing-mobile: 16px;
--spacing-tablet: 24px;
--spacing-desktop: 32px;
--font-size-mobile: 14px;
--font-size-tablet: 15px;
--font-size-desktop: 16px;
}
```
---
## Registration Flow Responsive Patterns
### Multi-Step Form Layout
#### Desktop (lg+)
```
┌───────────────────────────────────────────┐
│ [Logo] Step 1 of 3 │
├───────────────────────────────────────────┤
│ │
│ Company Information │
│ │
│ [ ] │
│ [ ] │
│ │
│ [Cancel] [Next →] │
│ │
└───────────────────────────────────────────┘
```
- Width: 600px max-width, centered
- Padding: 64px
- Form fields: Full width, 24px gap
- Buttons: Right-aligned, 160px width
#### Tablet (md)
```
┌─────────────────────────────────┐
│ [Logo] Step 1 of 3 │
├─────────────────────────────────┤
│ │
│ Company Information │
│ │
│ [ ] │
│ [ ] │
│ │
│ [Cancel] [Next →] │
│ │
└─────────────────────────────────┘
```
- Width: 480px max-width, centered
- Padding: 48px
- Form fields: Full width, 20px gap
- Buttons: Right-aligned, 140px width
#### Mobile (< sm)
```
┌─────────────────────────┐
│ [≡] Step 1 of 3 │
├─────────────────────────┤
│ │
│ Company Info │
│ │
│ [ ] │
│ [ ] │
│ │
│ [Cancel] │
│ [Next →] │
│ │
└─────────────────────────┘
```
- Width: Full width with 16px padding
- Progress: Compact dots only
- Fields: Stacked, full width, 16px gap
- Buttons: Stacked, full width, 12px gap
- Secondary button above primary
**Implementation:**
```tsx
<div className="
min-h-screen flex items-center justify-center
px-4 py-6 // Mobile
sm:px-6 sm:py-8 // Tablet
md:px-8 md:py-12 // Desktop
">
<div className="
w-full // Mobile: full width
sm:max-w-md // Tablet: 448px
md:max-w-lg // Desktop: 512px
lg:max-w-xl // Large: 576px
">
{/* Form content */}
<div className="
space-y-4 // Mobile: 16px gap
sm:space-y-5 // Tablet: 20px gap
md:space-y-6 // Desktop: 24px gap
">
{/* Fields */}
</div>
{/* Buttons */}
<div className="
mt-6 space-y-3 // Mobile: stacked
sm:mt-8 sm:flex sm:space-y-0 sm:space-x-4 // Tablet+: horizontal
sm:justify-end
">
<button className="
w-full sm:w-auto // Mobile: full width, Tablet+: auto
">
Cancel
</button>
<button className="
w-full sm:w-auto
">
Next
</button>
</div>
</div>
</div>
```
---
### Tenant Slug Preview
#### Desktop
```
Company Slug *
[acme ]
✓ acme.colaflow.com is available
```
#### Mobile
```
Company Slug *
[acme ]
✓ Available
```
- Hide full domain, show only "Available" / "Taken"
- Tap to view full domain in bottom sheet
**Implementation:**
```tsx
<div>
<Input value={slug} onChange={handleChange} />
{/* Desktop preview */}
<p className="hidden sm:block text-sm text-gray-600">
{slug}.colaflow.com is available
</p>
{/* Mobile preview */}
<p className="sm:hidden text-sm text-green-600">
Available
</p>
</div>
```
---
### Subscription Plan Cards
#### Desktop (lg+)
```
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Free │ │ Starter │ │ Pro │ │Enterprise│
│ $0 │ │ $19 │ │ $49 │ │ Custom │
│ ... │ │ ... │ │ ... │ │ ... │
│ [Start] │ │ [Start] │ │ [Start] │ │[Contact]│
└─────────┘ └─────────┘ └─────────┘ └─────────┘
```
- 4 columns, equal width
- Side-by-side comparison
#### Tablet (md)
```
┌───────────┐ ┌───────────┐
│ Free │ │ Starter │
│ $0 │ │ $19 │
│ ... │ │ ... │
│ [Start] │ │ [Start] │
└───────────┘ └───────────┘
┌───────────┐ ┌───────────┐
│ Pro │ │Enterprise │
│ $49 │ │ Custom │
│ ... │ │ ... │
│ [Start] │ │ [Contact] │
└───────────┘ └───────────┘
```
- 2 columns, 2 rows
- Grid layout
#### Mobile (< sm)
```
┌───────────────┐
│ Free │
│ $0 │
│ ... │
│ [Start] │
└───────────────┘
┌───────────────┐
│ Starter │
│ $19 │
│ ... │
│ [Start] │
└───────────────┘
```
- 1 column, scrollable
- Cards stacked vertically
- "Compare Plans" button to show comparison table
**Implementation:**
```tsx
<div className="
grid gap-4
grid-cols-1 // Mobile: 1 column
sm:grid-cols-2 // Tablet: 2 columns
lg:grid-cols-4 // Desktop: 4 columns
">
{plans.map(plan => (
<SubscriptionPlanCard key={plan.id} {...plan} />
))}
</div>
```
---
## Login Pages Responsive Design
### Login Form Layout
#### Desktop (md+)
```
┌──────────────────────────────────────┐
│ │
│ Welcome to Acme Corp │
│ │
│ Email Address │
│ [ ] │
│ │
│ Password │
│ [ ] │
│ │
│ [☐] Remember me Forgot password? │
│ │
│ [Sign In →] │
│ │
│ ────── OR ────── │
│ │
│ [🟦 Continue with Microsoft] │
│ [🔴 Continue with Google] │
│ │
└──────────────────────────────────────┘
```
- Max-width: 448px, centered
- Vertical spacing: 24px
- SSO buttons: full width
#### Mobile (< md)
```
┌────────────────────┐
│ │
│ Welcome │
│ │
│ Email │
│ [ ] │
│ │
│ Password │
│ [ ] │
│ │
│ [☐] Remember me │
│ Forgot password? │
│ │
│ [Sign In →] │
│ │
│ ─── OR ─── │
│ │
│ [Microsoft] │
│ [Google] │
│ │
└────────────────────┘
```
- Full width with 16px padding
- Smaller fonts (14px body)
- Compact spacing (16px)
- "Remember me" and "Forgot password" stacked
**Implementation:**
```tsx
<div className="
min-h-screen flex items-center justify-center
bg-gray-50 px-4 py-8
">
<div className="
w-full max-w-md
bg-white rounded-lg shadow-lg
p-6 sm:p-8
">
<h1 className="
text-2xl sm:text-3xl
font-bold text-center mb-6
">
Welcome to {tenantName}
</h1>
{/* SSO buttons (if configured) */}
{ssoEnabled && (
<div className="
space-y-3 mb-6
">
<SsoButton provider="AzureAD" fullWidth />
<SsoButton provider="Google" fullWidth />
</div>
)}
{ssoEnabled && <LoginDivider />}
{/* Local login form */}
<form className="space-y-4">
<Input label="Email Address" type="email" />
<Input label="Password" type="password" />
<div className="
flex flex-col sm:flex-row
sm:items-center sm:justify-between
space-y-2 sm:space-y-0
">
<Checkbox label="Remember me" />
<Link className="text-sm">Forgot password?</Link>
</div>
<Button type="submit" fullWidth>
Sign In
</Button>
</form>
</div>
</div>
```
---
### SSO Button Responsive Sizing
#### Desktop
```
[🟦 Continue with Microsoft]
│ 24px gap │
```
- Height: 48px
- Padding: 12px 24px
- Icon: 20x20px
- Font: 16px
#### Mobile
```
[🟦 Microsoft]
│ 12px │
```
- Height: 44px (touch-friendly)
- Padding: 12px 16px
- Icon: 18x18px
- Font: 14px
- Shorter text: "Microsoft" instead of "Continue with Microsoft"
**Implementation:**
```tsx
<button className="
w-full flex items-center justify-center gap-3
h-11 sm:h-12 // 44px / 48px
px-4 sm:px-6 // 16px / 24px
text-sm sm:text-base // 14px / 16px
rounded-lg
">
<Icon className="w-5 h-5" />
<span className="
hidden sm:inline // Hide "Continue with" on mobile
">
Continue with
</span>
<span>{providerName}</span>
</button>
```
---
## SSO Configuration Responsive Layout
### Settings Page Structure
#### Desktop (lg+)
```
┌─────────────────────────────────────────────────────┐
│ Settings │
├───────────┬─────────────────────────────────────────┤
│ │ │
│ General │ Single Sign-On (SSO) │
│ SSO │ │
│ Billing │ ┌──────────────────────────────────┐ │
│ Usage │ │ General │ │
│ Team │ │ OIDC Config │ │
│ │ │ SAML Config │ │
│ │ │ Users │ │
│ │ │ Test │ │
│ │ └──────────────────────────────────┘ │
│ │ │
│ │ [Tab content...] │
│ │ │
└───────────┴─────────────────────────────────────────┘
```
- Sidebar: 240px fixed width
- Content: Flexible, max-width 800px
- Tabs: Horizontal
#### Tablet (md)
```
┌─────────────────────────────────┐
│ Settings [≡] │
├─────────────────────────────────┤
│ │
│ Single Sign-On (SSO) │
│ │
│ ┌─────────────────────────┐ │
│ │ General │ │
│ │ OIDC Config │ │
│ │ SAML Config │ │
│ │ Users │ │
│ │ Test │ │
│ └─────────────────────────┘ │
│ │
│ [Tab content...] │
│ │
└─────────────────────────────────┘
```
- No sidebar (hamburger menu)
- Content: Full width with padding
- Tabs: Scrollable horizontal
#### Mobile (< sm)
```
┌───────────────────┐
│ SSO Config [≡] │
├───────────────────┤
│ │
│ [General ▼] │
│ │
│ [Tab content...] │
│ │
│ [Save] │
│ │
└───────────────────┘
```
- No sidebar
- Tabs: Dropdown select
- Sticky footer with save button
- Forms: Stacked fields
**Implementation:**
```tsx
<div className="
min-h-screen flex
flex-col lg:flex-row
">
{/* Sidebar (desktop only) */}
<aside className="
hidden lg:block
w-60 border-r bg-gray-50
">
<SettingsSidebar />
</aside>
{/* Mobile header with menu */}
<header className="
lg:hidden
sticky top-0 z-10
bg-white border-b
px-4 py-3
">
<div className="flex items-center justify-between">
<h1>SSO Configuration</h1>
<MenuButton />
</div>
</header>
{/* Main content */}
<main className="
flex-1 p-4 sm:p-6 lg:p-8
">
{/* Desktop tabs */}
<Tabs className="hidden sm:flex">
<Tab>General</Tab>
<Tab>OIDC Config</Tab>
<Tab>SAML Config</Tab>
<Tab>Users</Tab>
<Tab>Test</Tab>
</Tabs>
{/* Mobile dropdown */}
<Select className="sm:hidden mb-4">
<option>General</option>
<option>OIDC Config</option>
<option>SAML Config</option>
<option>Users</option>
<option>Test</option>
</Select>
{/* Tab content */}
<div className="mt-6">
{tabContent}
</div>
</main>
</div>
```
---
### Form Fields Responsive Stack
#### Desktop
```
Authority / Issuer URL *
[ ]
Client ID *
[ ]
Client Secret *
[ ]
```
- Single column
- Full width inputs
- 24px vertical gap
#### Mobile
```
Authority *
[ ]
Client ID *
[ ]
Secret *
[ ]
```
- Shorter labels
- Smaller inputs
- 16px vertical gap
- Multiline inputs collapse to single line
**Implementation:**
```tsx
<div className="space-y-4 sm:space-y-6">
<Input
label={
<span>
<span className="hidden sm:inline">Authority / Issuer URL</span>
<span className="sm:hidden">Authority</span>
</span>
}
required
/>
<Input
label="Client ID"
required
/>
<Input
label={
<span>
<span className="hidden sm:inline">Client Secret</span>
<span className="sm:hidden">Secret</span>
</span>
}
type="password"
required
/>
</div>
```
---
## MCP Token Management Mobile Views
### Token List Responsive Cards
#### Desktop (md+)
```
┌────────────────────────────────────────────────┐
│ Claude Desktop [Active] │
│ Permissions: Projects (R), Issues (R/W) │
│ Created: Nov 1 • Last Used: 2 hours ago │
│ Expires: In 30 days │
│ │
│ [View Details] [Revoke] │
└────────────────────────────────────────────────┘
```
- Horizontal card
- All info visible
- Buttons inline
#### Mobile (< md)
```
┌──────────────────────────┐
│ Claude Desktop [●] │
│ │
│ Projects (R) │
│ Issues (R/W) │
│ +2 more │
│ │
│ Last used: 2h ago │
│ Expires: 30d │
│ │
│ [Details] [Revoke] │
└──────────────────────────┘
```
- Vertical card
- Compact info
- Abbreviated permissions
- Buttons full width
**Implementation:**
```tsx
<div className="
rounded-lg border bg-white shadow-sm
p-4 sm:p-6
">
<div className="
flex flex-col sm:flex-row
sm:items-center sm:justify-between
gap-3 sm:gap-4
">
{/* Header */}
<div className="flex-1">
<div className="flex items-center justify-between mb-2">
<h3 className="font-semibold">{token.name}</h3>
<StatusBadge status={token.status} />
</div>
{/* Permissions - desktop */}
<div className="hidden sm:block text-sm text-gray-600">
{formatPermissions(token.permissions)}
</div>
{/* Permissions - mobile (compact) */}
<div className="sm:hidden space-y-1">
{token.permissions.slice(0, 2).map(p => (
<div key={p} className="text-xs text-gray-600">
{p}
</div>
))}
{token.permissions.length > 2 && (
<div className="text-xs text-gray-500">
+{token.permissions.length - 2} more
</div>
)}
</div>
{/* Metadata */}
<div className="
mt-2 flex flex-col sm:flex-row sm:gap-4
text-xs sm:text-sm text-gray-500
">
<span>Created: {formatDate(token.createdAt)}</span>
<span>Last used: {formatRelativeTime(token.lastUsedAt)}</span>
<span>Expires: {formatExpiry(token.expiresAt)}</span>
</div>
</div>
{/* Actions */}
<div className="
flex gap-2
flex-col sm:flex-row
sm:ml-auto
">
<Button
variant="secondary"
size="sm"
className="w-full sm:w-auto"
>
View Details
</Button>
<Button
variant="danger"
size="sm"
className="w-full sm:w-auto"
>
Revoke
</Button>
</div>
</div>
</div>
```
---
### Permission Matrix Mobile Adaptation
#### Desktop
```
┌──────────────────────────────────────────────────┐
│ Resource │ Read │Create│Update│Delete│Search │
│───────────┼──────┼──────┼──────┼──────┼────────│
│ Projects │ ✓ │ │ │ │ ✓ │
│ Issues │ ✓ │ ✓ │ ✓ │ │ ✓ │
│ Documents │ ✓ │ ✓ │ │ │ ✓ │
└──────────────────────────────────────────────────┘
```
- Full table view
- All columns visible
- Checkboxes
#### Mobile (< md)
```
┌─────────────────────────┐
│ [Projects ▼] │
│ ☑ Read │
│ ☐ Create │
│ ☐ Update │
│ ☐ Delete │
│ ☑ Search │
├─────────────────────────┤
│ [Issues ▼] │
│ ☑ Read │
│ ☑ Create │
│ ☑ Update │
│ ☐ Delete │
│ ☑ Search │
└─────────────────────────┘
```
- Accordion view
- One resource at a time
- Larger touch targets
- Checkbox list
**Implementation:**
```tsx
// Desktop view
<table className="hidden md:table w-full">
<thead>
<tr>
<th>Resource</th>
<th>Read</th>
<th>Create</th>
<th>Update</th>
<th>Delete</th>
<th>Search</th>
</tr>
</thead>
<tbody>
{resources.map(resource => (
<tr key={resource}>
<td>{resource}</td>
{operations.map(op => (
<td key={op}>
<Checkbox checked={hasPermission(resource, op)} />
</td>
))}
</tr>
))}
</tbody>
</table>
// Mobile view (accordion)
<div className="md:hidden space-y-2">
{resources.map(resource => (
<Accordion key={resource}>
<AccordionTrigger>
{resource}
<span className="text-xs text-gray-500 ml-2">
({selectedCount(resource)} selected)
</span>
</AccordionTrigger>
<AccordionContent>
<div className="space-y-2 pt-2">
{operations.map(op => (
<label key={op} className="flex items-center gap-3 p-2">
<Checkbox checked={hasPermission(resource, op)} />
<span>{op}</span>
</label>
))}
</div>
</AccordionContent>
</Accordion>
))}
</div>
```
---
### Audit Log Table Mobile Adaptation
#### Desktop
```
┌────────────────────────────────────────────────────┐
│ Timestamp Action Resource Result IP │
│────────────────────────────────────────────────────│
│ Nov 3, 08:15 Read Issue #123 Success 192.168 │
│ Nov 3, 08:10 Create Issue #456 Success 192.168 │
└────────────────────────────────────────────────────┘
```
- Table layout
- All columns visible
- Horizontal scroll if needed
#### Mobile
```
┌────────────────────────┐
│ Nov 3, 08:15 AM │
│ Read Issue #123 │
│ Success • 192.168.1.1 │
├────────────────────────┤
│ Nov 3, 08:10 AM │
│ Create Issue #456 │
│ Success • 192.168.1.1 │
└────────────────────────┘
```
- Card layout
- Stacked information
- Tap to expand details
**Implementation:**
```tsx
// Desktop table
<table className="hidden sm:table w-full">
<thead>
<tr>
<th>Timestamp</th>
<th>Action</th>
<th>Resource</th>
<th>Result</th>
<th>IP Address</th>
</tr>
</thead>
<tbody>
{logs.map(log => (
<tr key={log.id}>
<td>{formatTimestamp(log.timestamp)}</td>
<td>{log.action}</td>
<td>{log.resource}</td>
<td><StatusBadge status={log.result} /></td>
<td>{log.ipAddress}</td>
</tr>
))}
</tbody>
</table>
// Mobile cards
<div className="sm:hidden space-y-2">
{logs.map(log => (
<button
key={log.id}
className="w-full text-left p-4 bg-white rounded border"
onClick={() => showLogDetails(log)}
>
<div className="text-sm text-gray-500 mb-1">
{formatTimestamp(log.timestamp)}
</div>
<div className="font-medium mb-1">
{log.action} {log.resource}
</div>
<div className="flex items-center gap-2 text-sm text-gray-600">
<StatusBadge status={log.result} size="sm" />
<span></span>
<span>{log.ipAddress}</span>
</div>
</button>
))}
</div>
```
---
## Component Adaptations
### Modal to Bottom Sheet
On mobile, full-screen modals become bottom sheets for better UX.
#### Desktop Modal
```
[Backdrop]
┌──────────────┐
│ Modal │
│ Content │
│ │
│ [Actions] │
└──────────────┘
```
#### Mobile Bottom Sheet
```
┌──────────────────┐
│ │
│ Page content │
│ │
├──────────────────┤ <- Swipe up
│ [Handle] │
│ │
│ Sheet Content │
│ │
│ [Actions] │
└──────────────────┘
```
**Implementation:**
```tsx
<Dialog
className="
fixed inset-0 // Desktop: centered
sm:flex sm:items-center sm:justify-center
// Mobile: bottom sheet
flex items-end
sm:items-center
"
>
<DialogContent
className="
w-full max-w-lg // Desktop: max-width
// Mobile: bottom sheet styling
rounded-t-2xl sm:rounded-lg // Round top only on mobile
max-h-[90vh] // Don't cover entire screen
overflow-y-auto
"
>
{/* Drag handle (mobile only) */}
<div className="
sm:hidden
w-12 h-1 bg-gray-300 rounded-full
mx-auto my-3
" />
{content}
</DialogContent>
</Dialog>
```
---
### Dropdown to Drawer
Complex dropdowns become side drawers on mobile.
#### Desktop Dropdown
```
[Select Provider ▼]
├─ Azure AD
├─ Google
├─ Okta
└─ SAML
```
#### Mobile Drawer
```
┌──────────────────┐
│ │
│ Page │
│ │
│ [Select ▼] │
│ │
└──────────────────┘
┌──────────────────┐
│ [× ] Provider │
├──────────────────┤
│ │
│ ○ Azure AD │
│ ○ Google │
│ ○ Okta │
│ ● SAML │
│ │
│ [Confirm] │
└──────────────────┘
```
**Implementation:**
```tsx
// Desktop: native select or dropdown
<Select className="hidden sm:block">
{options.map(opt => (
<option key={opt.value}>{opt.label}</option>
))}
</Select>
// Mobile: drawer
<button
className="sm:hidden"
onClick={() => setDrawerOpen(true)}
>
{selectedOption.label}
</button>
<Drawer open={drawerOpen} onClose={() => setDrawerOpen(false)}>
<DrawerContent>
<DrawerHeader>
Select Provider
</DrawerHeader>
<div className="space-y-2 p-4">
{options.map(opt => (
<button
key={opt.value}
className="w-full text-left p-3 rounded hover:bg-gray-100"
onClick={() => {
setSelectedOption(opt);
setDrawerOpen(false);
}}
>
{opt.label}
</button>
))}
</div>
</DrawerContent>
</Drawer>
```
---
## Performance Considerations
### Image Optimization
```tsx
import Image from 'next/image';
<Image
src="/logo.svg"
alt="ColaFlow"
width={120}
height={40}
sizes="(max-width: 640px) 100px, 120px" // Smaller on mobile
priority={true} // Above the fold
/>
```
### Lazy Loading
```tsx
import dynamic from 'next/dynamic';
// Load heavy components only when needed
const PermissionMatrix = dynamic(
() => import('@/components/mcp-tokens/PermissionMatrix'),
{ loading: () => <Skeleton /> }
);
// Mobile-specific components
const MobileDrawer = dynamic(
() => import('@/components/shared/MobileDrawer'),
{ ssr: false } // Client-side only
);
```
### Conditional Rendering
```tsx
// Don't render desktop components on mobile
const isMobile = useMediaQuery('(max-width: 640px)');
return (
<>
{isMobile ? <MobileView /> : <DesktopView />}
</>
);
```
### Font Loading
```tsx
// next.config.js
module.exports = {
optimizeFonts: true,
// Font subsets for faster loading
experimental: {
optimizeFonts: ['latin', 'latin-ext'],
},
};
```
### CSS Optimization
```css
/* Critical CSS inline in <head> */
/* Non-critical CSS lazy-loaded */
/* Reduce animations on mobile for performance */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
/* Disable hover effects on touch devices */
@media (hover: none) {
.hover-effect:hover {
/* No hover effect */
}
}
```
---
## Testing Guidelines
### Responsive Testing Checklist
- [ ] Test on real devices (not just browser DevTools)
- [ ] iOS Safari (iPhone 13, 14, 15)
- [ ] Android Chrome (Samsung, Pixel)
- [ ] Tablet: iPad Pro, Android tablet
- [ ] Foldable devices (Galaxy Fold, Surface Duo)
- [ ] Landscape and portrait orientations
- [ ] Text zoom (up to 200%)
- [ ] Touch target sizes (min 44x44px)
- [ ] Keyboard navigation on tablets
- [ ] Screen reader compatibility
### Breakpoint Testing Script
```typescript
// utils/breakpoints.test.ts
import { render } from '@testing-library/react';
import { useMediaQuery } from '@/hooks/useMediaQuery';
describe('Responsive Breakpoints', () => {
const breakpoints = [320, 480, 640, 768, 1024, 1280, 1536];
breakpoints.forEach(width => {
test(`Renders correctly at ${width}px`, () => {
window.innerWidth = width;
window.dispatchEvent(new Event('resize'));
const { container } = render(<YourComponent />);
expect(container).toMatchSnapshot();
});
});
});
```
---
## Conclusion
This responsive design guide ensures ColaFlow provides an optimal experience across all device sizes. By following mobile-first principles and adapting components appropriately, we maintain usability and performance on every screen.
**Key Takeaways:**
1. Always start with mobile design
2. Use appropriate breakpoints for content, not devices
3. Simplify UI on small screens
4. Optimize performance for mobile networks
5. Test on real devices
**Next Steps:**
1. Implement responsive components
2. Conduct device testing
3. Measure performance metrics
4. Gather user feedback
5. Iterate and improve
**Questions:** Contact UX/UI team at ux@colaflow.com