@nqlib/nqui 0.3.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -1
- package/dist/nqui.cjs.js +1 -1
- package/dist/nqui.es.js +3 -3
- package/dist/pages/ComponentShowcase.d.ts.map +1 -1
- package/dist/styles.css +0 -8
- package/docs/components/README.md +119 -0
- package/docs/components/nqui-accordion.md +20 -0
- package/docs/components/nqui-alert-dialog.md +31 -0
- package/docs/components/nqui-alert.md +19 -0
- package/docs/components/nqui-aspect-ratio.md +17 -0
- package/docs/components/nqui-avatar.md +18 -0
- package/docs/components/nqui-badge.md +42 -0
- package/docs/components/nqui-breadcrumb.md +24 -0
- package/docs/components/nqui-button-group.md +31 -0
- package/docs/components/nqui-button.md +56 -0
- package/docs/components/nqui-calendar.md +46 -0
- package/docs/components/nqui-card.md +31 -0
- package/docs/components/nqui-carousel.md +22 -0
- package/docs/components/nqui-checkbox.md +34 -0
- package/docs/components/nqui-code-block.md +39 -0
- package/docs/components/nqui-code-editor.md +21 -0
- package/docs/components/nqui-collapsible.md +18 -0
- package/docs/components/nqui-color-picker.md +38 -0
- package/docs/components/nqui-color-slider.md +23 -0
- package/docs/components/nqui-combobox.md +65 -0
- package/docs/components/nqui-command-palette.md +29 -0
- package/docs/components/nqui-command.md +39 -0
- package/docs/components/nqui-context-menu.md +33 -0
- package/docs/components/nqui-dialog.md +36 -0
- package/docs/components/nqui-drawer.md +27 -0
- package/docs/components/nqui-dropdown-menu.md +56 -0
- package/docs/components/nqui-empty.md +22 -0
- package/docs/components/nqui-field.md +42 -0
- package/docs/components/nqui-frosted-glass.md +19 -0
- package/docs/components/nqui-hover-card.md +18 -0
- package/docs/components/nqui-input-group.md +22 -0
- package/docs/components/nqui-input-otp.md +23 -0
- package/docs/components/nqui-input.md +25 -0
- package/docs/components/nqui-item.md +25 -0
- package/docs/components/nqui-kbd.md +25 -0
- package/docs/components/nqui-label.md +16 -0
- package/docs/components/nqui-logo.md +16 -0
- package/docs/components/nqui-menubar.md +22 -0
- package/docs/components/nqui-native-select.md +28 -0
- package/docs/components/nqui-navigation-menu.md +25 -0
- package/docs/components/nqui-pagination.md +25 -0
- package/docs/components/nqui-popover.md +34 -0
- package/docs/components/nqui-progress.md +22 -0
- package/docs/components/nqui-radio-group.md +34 -0
- package/docs/components/nqui-rating.md +35 -0
- package/docs/components/nqui-resizable.md +23 -0
- package/docs/components/nqui-sandbox.md +27 -0
- package/docs/components/nqui-scroll-area.md +32 -0
- package/docs/components/nqui-segmented-control.md +18 -0
- package/docs/components/nqui-select.md +50 -0
- package/docs/components/nqui-separator.md +16 -0
- package/docs/components/nqui-sheet.md +27 -0
- package/docs/components/nqui-sidebar.md +45 -0
- package/docs/components/nqui-skeleton.md +15 -0
- package/docs/components/nqui-slider.md +16 -0
- package/docs/components/nqui-snippet.md +28 -0
- package/docs/components/nqui-sortable.md +46 -0
- package/docs/components/nqui-spinner.md +16 -0
- package/docs/components/nqui-switch.md +15 -0
- package/docs/components/nqui-table-of-contents.md +37 -0
- package/docs/components/nqui-tabs.md +35 -0
- package/docs/components/nqui-textarea.md +15 -0
- package/docs/components/nqui-toaster.md +44 -0
- package/docs/components/nqui-toggle-group.md +21 -0
- package/docs/components/nqui-toggle.md +15 -0
- package/docs/components/nqui-tooltip.md +24 -0
- package/docs/components/nqui-tracker.md +38 -0
- package/docs/internal-notes/BUILD_VERIFICATION.md +174 -0
- package/docs/internal-notes/DASHBOARD_LAYOUT_DESIGN.md +1429 -0
- package/docs/internal-notes/FROSTED_GLASS_FIX.md +50 -0
- package/docs/internal-notes/PUBLISHING.md +339 -0
- package/docs/internal-notes/layoutdesign.md +616 -0
- package/docs/internal-notes/progress.md +348 -0
- package/docs/internal-notes/stacked-avatar-implementation.md +38 -0
- package/package.json +2 -1
- /package/{INSTALLATION.md → docs/internal-notes/INSTALLATION.md} +0 -0
|
@@ -0,0 +1,1429 @@
|
|
|
1
|
+
# Universal Three-Panel Dashboard Layout System
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A reusable, scalable dashboard layout system implementing a three-panel navigation pattern that works universally across different applications and content types. This design provides consistent navigation, contextual options, and responsive behavior regardless of the underlying content or domain.
|
|
6
|
+
|
|
7
|
+
## Universal Application
|
|
8
|
+
|
|
9
|
+
This layout system is designed to be **content-agnostic** and can be applied to any dashboard-style application:
|
|
10
|
+
|
|
11
|
+
- **Content Management Systems** (CMS)
|
|
12
|
+
- **Email/Calendar Applications**
|
|
13
|
+
- **Project Management Tools**
|
|
14
|
+
- **Analytics Dashboards**
|
|
15
|
+
- **E-commerce Admin Panels**
|
|
16
|
+
- **Developer Tools & IDEs**
|
|
17
|
+
- **Design/Prototyping Tools**
|
|
18
|
+
|
|
19
|
+
## Core Architecture
|
|
20
|
+
|
|
21
|
+
### Three-Panel Navigation Pattern
|
|
22
|
+
|
|
23
|
+
The layout follows a universal three-panel pattern applicable to any application:
|
|
24
|
+
|
|
25
|
+
1. **Primary Sidebar** (left): Icon-only global navigation menu
|
|
26
|
+
2. **Secondary Sidebar** (left, conditional): Context-specific tools/options/filters
|
|
27
|
+
3. **Main Content Area** (center): Flexible workspace/canvas area
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
┌─────────────────┬─────────────────┬─────────────────┐
|
|
31
|
+
│ │ │ │
|
|
32
|
+
│ Global │ Context │ Main │
|
|
33
|
+
│ Navigation │ Tools │ Workspace │
|
|
34
|
+
│ (Icons) │ (Filters) │ (Content) │
|
|
35
|
+
│ │ │ │
|
|
36
|
+
└─────────────────┴─────────────────┴─────────────────┘
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Content Type Adaptations
|
|
40
|
+
|
|
41
|
+
The same layout pattern adapts to different content types by changing the secondary sidebar content:
|
|
42
|
+
|
|
43
|
+
**📧 Communication Apps (Email, Chat, Calendar):**
|
|
44
|
+
- Primary: Mailboxes, contacts, calendar views
|
|
45
|
+
- Secondary: Message list, contact filters, calendar filters
|
|
46
|
+
- Main: Message content, conversation threads, calendar events
|
|
47
|
+
|
|
48
|
+
**📊 Data Applications (Analytics, Reports):**
|
|
49
|
+
- Primary: Dashboard, reports, data sources
|
|
50
|
+
- Secondary: Filters, date ranges, metrics selector
|
|
51
|
+
- Main: Charts, tables, data visualizations
|
|
52
|
+
|
|
53
|
+
**🛠️ Creation Tools (Editors, Designers):**
|
|
54
|
+
- Primary: File browser, tools, views
|
|
55
|
+
- Secondary: Tool palette, layers, properties
|
|
56
|
+
- Main: Canvas, editor workspace, design area
|
|
57
|
+
|
|
58
|
+
**📋 Management Apps (Tasks, Projects):**
|
|
59
|
+
- Primary: Projects, teams, views
|
|
60
|
+
- Secondary: Task filters, project phases, team members
|
|
61
|
+
- Main: Task boards, timelines, project details
|
|
62
|
+
|
|
63
|
+
### Responsive States
|
|
64
|
+
|
|
65
|
+
**Desktop (> 768px):**
|
|
66
|
+
- All three panels visible simultaneously
|
|
67
|
+
- Primary sidebar collapsible to icon-only (22rem → 3rem)
|
|
68
|
+
- Secondary sidebar adapts content based on primary selection
|
|
69
|
+
|
|
70
|
+
**Tablet (768px):**
|
|
71
|
+
- Primary sidebar reduces to icons
|
|
72
|
+
- Secondary sidebar becomes overlay/modal
|
|
73
|
+
- Main content remains full-width workspace
|
|
74
|
+
|
|
75
|
+
**Mobile (< 768px):**
|
|
76
|
+
- Single-panel view with drawer navigation
|
|
77
|
+
- Secondary content in modal sheets
|
|
78
|
+
- Touch-optimized interactions with swipe gestures
|
|
79
|
+
|
|
80
|
+
## Universal Component Architecture
|
|
81
|
+
|
|
82
|
+
### LayoutProvider (Universal Root Component)
|
|
83
|
+
|
|
84
|
+
**Purpose:** Application-wide layout state management and responsive behavior
|
|
85
|
+
|
|
86
|
+
**Core Interface:**
|
|
87
|
+
```tsx
|
|
88
|
+
interface LayoutConfig {
|
|
89
|
+
primarySidebar: {
|
|
90
|
+
width: string
|
|
91
|
+
iconWidth: string
|
|
92
|
+
collapsible: boolean
|
|
93
|
+
}
|
|
94
|
+
secondarySidebar: {
|
|
95
|
+
width: string
|
|
96
|
+
contentType: 'filters' | 'tools' | 'navigation' | 'properties'
|
|
97
|
+
}
|
|
98
|
+
responsive: {
|
|
99
|
+
mobileBreakpoint: number
|
|
100
|
+
tabletBreakpoint: number
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
interface LayoutContextValue {
|
|
105
|
+
// Sidebar states
|
|
106
|
+
primaryCollapsed: boolean
|
|
107
|
+
secondaryVisible: boolean
|
|
108
|
+
|
|
109
|
+
// Content management
|
|
110
|
+
activePrimaryItem: string | null
|
|
111
|
+
activeSecondaryItem: string | null
|
|
112
|
+
|
|
113
|
+
// Responsive state
|
|
114
|
+
isMobile: boolean
|
|
115
|
+
isTablet: boolean
|
|
116
|
+
|
|
117
|
+
// Actions
|
|
118
|
+
togglePrimarySidebar: () => void
|
|
119
|
+
setActivePrimaryItem: (item: string) => void
|
|
120
|
+
showSecondaryContent: (content: React.ReactNode) => void
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### PrimarySidebar (Global Navigation)
|
|
125
|
+
|
|
126
|
+
**Universal Structure:**
|
|
127
|
+
```tsx
|
|
128
|
+
interface NavigationItem {
|
|
129
|
+
id: string
|
|
130
|
+
label: string
|
|
131
|
+
icon: React.ComponentType
|
|
132
|
+
badge?: string | number
|
|
133
|
+
disabled?: boolean
|
|
134
|
+
requiresAuth?: boolean
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface PrimarySidebarProps {
|
|
138
|
+
items: NavigationItem[]
|
|
139
|
+
activeItem: string | null
|
|
140
|
+
onItemSelect: (itemId: string) => void
|
|
141
|
+
collapsed?: boolean
|
|
142
|
+
className?: string
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Implementation Pattern:**
|
|
147
|
+
```tsx
|
|
148
|
+
<PrimarySidebar
|
|
149
|
+
items={[
|
|
150
|
+
{ id: 'dashboard', label: 'Dashboard', icon: HomeIcon },
|
|
151
|
+
{ id: 'projects', label: 'Projects', icon: FolderIcon },
|
|
152
|
+
{ id: 'team', label: 'Team', icon: UsersIcon },
|
|
153
|
+
{ id: 'settings', label: 'Settings', icon: SettingsIcon }
|
|
154
|
+
]}
|
|
155
|
+
activeItem={activePrimaryItem}
|
|
156
|
+
onItemSelect={handlePrimaryNavigation}
|
|
157
|
+
/>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### SecondarySidebar (Contextual Tools)
|
|
161
|
+
|
|
162
|
+
**Content Type Variants:**
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
type SecondaryContentType =
|
|
166
|
+
| 'filters' // Data filtering, search options
|
|
167
|
+
| 'tools' // Tool palettes, widgets
|
|
168
|
+
| 'navigation' // Hierarchical navigation, breadcrumbs
|
|
169
|
+
| 'properties' // Object properties, settings
|
|
170
|
+
| 'list' // Item lists, collections
|
|
171
|
+
| 'preview' // Content previews, thumbnails
|
|
172
|
+
|
|
173
|
+
interface SecondarySidebarProps {
|
|
174
|
+
contentType: SecondaryContentType
|
|
175
|
+
content: React.ReactNode
|
|
176
|
+
title?: string
|
|
177
|
+
searchable?: boolean
|
|
178
|
+
collapsible?: boolean
|
|
179
|
+
onClose?: () => void
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### MainContent (Workspace Area)
|
|
184
|
+
|
|
185
|
+
**Flexible Layout System:**
|
|
186
|
+
```tsx
|
|
187
|
+
interface MainContentProps {
|
|
188
|
+
children: React.ReactNode
|
|
189
|
+
header?: React.ReactNode
|
|
190
|
+
toolbar?: React.ReactNode
|
|
191
|
+
footer?: React.ReactNode
|
|
192
|
+
scrollable?: boolean
|
|
193
|
+
className?: string
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Usage Patterns:**
|
|
198
|
+
```tsx
|
|
199
|
+
// Content-focused layout
|
|
200
|
+
<MainContent header={<PageHeader />}>
|
|
201
|
+
<ContentGrid />
|
|
202
|
+
</MainContent>
|
|
203
|
+
|
|
204
|
+
// Canvas/workspace layout
|
|
205
|
+
<MainContent scrollable={false}>
|
|
206
|
+
<CanvasArea />
|
|
207
|
+
</MainContent>
|
|
208
|
+
|
|
209
|
+
// Data table layout
|
|
210
|
+
<MainContent
|
|
211
|
+
toolbar={<DataToolbar />}
|
|
212
|
+
footer={<PaginationControls />}
|
|
213
|
+
>
|
|
214
|
+
<DataTable />
|
|
215
|
+
</MainContent>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### ResponsiveContainer (Mobile Adaptation)
|
|
219
|
+
|
|
220
|
+
**Universal Mobile Handling:**
|
|
221
|
+
```tsx
|
|
222
|
+
interface ResponsiveContainerProps {
|
|
223
|
+
primarySidebar: React.ReactNode
|
|
224
|
+
secondarySidebar: React.ReactNode
|
|
225
|
+
mainContent: React.ReactNode
|
|
226
|
+
header?: React.ReactNode
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Automatically handles:
|
|
230
|
+
// - Drawer behavior on mobile
|
|
231
|
+
// - Sheet overlays for secondary content
|
|
232
|
+
// - Touch gesture support
|
|
233
|
+
// - Keyboard shortcuts
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Universal Responsive Design System
|
|
237
|
+
|
|
238
|
+
### Device Breakpoints (Configurable)
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
interface ResponsiveBreakpoints {
|
|
242
|
+
mobile: number // Default: 768px
|
|
243
|
+
tablet: number // Default: 1024px
|
|
244
|
+
desktop: number // Default: 1440px
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Usage in any application
|
|
248
|
+
const BREAKPOINTS = {
|
|
249
|
+
mobile: 768,
|
|
250
|
+
tablet: 1024,
|
|
251
|
+
desktop: 1440
|
|
252
|
+
} as const
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Responsive Hook (Universal)
|
|
256
|
+
|
|
257
|
+
**Device Detection:**
|
|
258
|
+
```tsx
|
|
259
|
+
// Universal hook for any application
|
|
260
|
+
export function useDeviceType(breakpoints = BREAKPOINTS) {
|
|
261
|
+
const [device, setDevice] = React.useState<{
|
|
262
|
+
isMobile: boolean
|
|
263
|
+
isTablet: boolean
|
|
264
|
+
isDesktop: boolean
|
|
265
|
+
width: number
|
|
266
|
+
}>({
|
|
267
|
+
isMobile: false,
|
|
268
|
+
isTablet: false,
|
|
269
|
+
isDesktop: true,
|
|
270
|
+
width: typeof window !== 'undefined' ? window.innerWidth : 1440
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
React.useEffect(() => {
|
|
274
|
+
const updateDevice = () => {
|
|
275
|
+
const width = window.innerWidth
|
|
276
|
+
setDevice({
|
|
277
|
+
isMobile: width < breakpoints.mobile,
|
|
278
|
+
isTablet: width >= breakpoints.mobile && width < breakpoints.tablet,
|
|
279
|
+
isDesktop: width >= breakpoints.tablet,
|
|
280
|
+
width
|
|
281
|
+
})
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
updateDevice()
|
|
285
|
+
window.addEventListener('resize', updateDevice)
|
|
286
|
+
return () => window.removeEventListener('resize', updateDevice)
|
|
287
|
+
}, [breakpoints])
|
|
288
|
+
|
|
289
|
+
return device
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Universal Layout Dimensions
|
|
294
|
+
|
|
295
|
+
```css
|
|
296
|
+
/* Configurable CSS Variables */
|
|
297
|
+
:root {
|
|
298
|
+
/* Primary sidebar */
|
|
299
|
+
--sidebar-primary-width: 22rem;
|
|
300
|
+
--sidebar-primary-width-collapsed: 3rem;
|
|
301
|
+
|
|
302
|
+
/* Secondary sidebar */
|
|
303
|
+
--sidebar-secondary-width: 20rem;
|
|
304
|
+
--sidebar-secondary-width-mobile: 18rem;
|
|
305
|
+
|
|
306
|
+
/* Responsive breakpoints */
|
|
307
|
+
--breakpoint-mobile: 768px;
|
|
308
|
+
--breakpoint-tablet: 1024px;
|
|
309
|
+
--breakpoint-desktop: 1440px;
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Responsive Behavior Patterns
|
|
314
|
+
|
|
315
|
+
**Three Layout States:**
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
interface LayoutState {
|
|
319
|
+
// Desktop: All panels visible
|
|
320
|
+
desktop: {
|
|
321
|
+
primarySidebar: 'expanded' | 'collapsed'
|
|
322
|
+
secondarySidebar: 'visible' | 'hidden'
|
|
323
|
+
mainContent: 'full' | 'constrained'
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Tablet: Primary collapsed, secondary overlay
|
|
327
|
+
tablet: {
|
|
328
|
+
primarySidebar: 'icons-only'
|
|
329
|
+
secondarySidebar: 'overlay' | 'hidden'
|
|
330
|
+
mainContent: 'full'
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Mobile: Single panel with drawers
|
|
334
|
+
mobile: {
|
|
335
|
+
primarySidebar: 'drawer'
|
|
336
|
+
secondarySidebar: 'modal' | 'drawer'
|
|
337
|
+
mainContent: 'full'
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**Conditional Rendering (Universal):**
|
|
343
|
+
```tsx
|
|
344
|
+
function ResponsiveLayout({ device, children }) {
|
|
345
|
+
if (device.isMobile) {
|
|
346
|
+
return <MobileLayout>{children}</MobileLayout>
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (device.isTablet) {
|
|
350
|
+
return <TabletLayout>{children}</TabletLayout>
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return <DesktopLayout>{children}</DesktopLayout>
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
**Overlay/Modal Patterns:**
|
|
358
|
+
```tsx
|
|
359
|
+
// Universal sheet for secondary content
|
|
360
|
+
function SecondaryContentSheet({ open, onOpen, content }) {
|
|
361
|
+
return (
|
|
362
|
+
<Sheet open={open} onOpenChange={onOpen}>
|
|
363
|
+
<SheetContent side="right" className="w-full sm:max-w-[400px]">
|
|
364
|
+
{content}
|
|
365
|
+
</SheetContent>
|
|
366
|
+
</Sheet>
|
|
367
|
+
)
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Universal drawer for primary navigation
|
|
371
|
+
function PrimaryNavigationDrawer({ open, onOpen, navigation }) {
|
|
372
|
+
return (
|
|
373
|
+
<Drawer open={open} onOpenChange={onOpen}>
|
|
374
|
+
<DrawerContent>
|
|
375
|
+
<DrawerHeader>
|
|
376
|
+
<DrawerTitle>Navigation</DrawerTitle>
|
|
377
|
+
</DrawerHeader>
|
|
378
|
+
{navigation}
|
|
379
|
+
</DrawerContent>
|
|
380
|
+
</Drawer>
|
|
381
|
+
)
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## Universal Content Patterns
|
|
386
|
+
|
|
387
|
+
### Pattern 1: List-Detail Navigation
|
|
388
|
+
|
|
389
|
+
**Use Case:** Email, tasks, documents, contacts, calendar events
|
|
390
|
+
|
|
391
|
+
**Navigation Flow:** Click primary item → show filtered list → display selected item details
|
|
392
|
+
|
|
393
|
+
```tsx
|
|
394
|
+
interface ListDetailPattern {
|
|
395
|
+
primaryItems: Array<{ id: string, label: string, count?: number }>
|
|
396
|
+
listFilters: Array<{ type: 'search' | 'status' | 'date' | 'tags' }>
|
|
397
|
+
detailView: (item: any) => React.ReactNode
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Example: Email Application
|
|
401
|
+
const emailPattern: ListDetailPattern = {
|
|
402
|
+
primaryItems: [
|
|
403
|
+
{ id: 'inbox', label: 'Inbox', count: 12 },
|
|
404
|
+
{ id: 'sent', label: 'Sent', count: 5 },
|
|
405
|
+
{ id: 'drafts', label: 'Drafts', count: 2 }
|
|
406
|
+
],
|
|
407
|
+
listFilters: [
|
|
408
|
+
{ type: 'search' },
|
|
409
|
+
{ type: 'status' },
|
|
410
|
+
{ type: 'date' }
|
|
411
|
+
]
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Example: Task Management
|
|
415
|
+
const taskPattern: ListDetailPattern = {
|
|
416
|
+
primaryItems: [
|
|
417
|
+
{ id: 'today', label: 'Today', count: 8 },
|
|
418
|
+
{ id: 'week', label: 'This Week', count: 23 },
|
|
419
|
+
{ id: 'projects', label: 'Projects', count: 5 }
|
|
420
|
+
],
|
|
421
|
+
listFilters: [
|
|
422
|
+
{ type: 'search' },
|
|
423
|
+
{ type: 'tags' },
|
|
424
|
+
{ type: 'assignee' }
|
|
425
|
+
]
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Pattern 2: Hierarchical Content Navigation
|
|
430
|
+
|
|
431
|
+
**Use Case:** Documentation, file systems, category browsing, knowledge bases
|
|
432
|
+
|
|
433
|
+
**Navigation Flow:** Click primary section → show table of contents → navigate to content sections
|
|
434
|
+
|
|
435
|
+
```tsx
|
|
436
|
+
interface HierarchicalPattern {
|
|
437
|
+
primarySections: Array<{ id: string, label: string, icon: string }>
|
|
438
|
+
contentHierarchy: {
|
|
439
|
+
[sectionId: string]: Array<{
|
|
440
|
+
id: string
|
|
441
|
+
title: string
|
|
442
|
+
level: number
|
|
443
|
+
scrollTarget?: string
|
|
444
|
+
}>
|
|
445
|
+
}
|
|
446
|
+
scrollSpy?: boolean
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Example: Documentation Site
|
|
450
|
+
const docsPattern: HierarchicalPattern = {
|
|
451
|
+
primarySections: [
|
|
452
|
+
{ id: 'getting-started', label: 'Getting Started', icon: '🚀' },
|
|
453
|
+
{ id: 'api-reference', label: 'API Reference', icon: '📚' },
|
|
454
|
+
{ id: 'examples', label: 'Examples', icon: '💡' }
|
|
455
|
+
],
|
|
456
|
+
contentHierarchy: {
|
|
457
|
+
'getting-started': [
|
|
458
|
+
{ id: 'installation', title: 'Installation', level: 1 },
|
|
459
|
+
{ id: 'quick-start', title: 'Quick Start', level: 1 },
|
|
460
|
+
{ id: 'basic-usage', title: 'Basic Usage', level: 2 }
|
|
461
|
+
]
|
|
462
|
+
},
|
|
463
|
+
scrollSpy: true
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Example: File System Browser
|
|
467
|
+
const fileSystemPattern: HierarchicalPattern = {
|
|
468
|
+
primarySections: [
|
|
469
|
+
{ id: 'documents', label: 'Documents', icon: '📄' },
|
|
470
|
+
{ id: 'images', label: 'Images', icon: '🖼️' },
|
|
471
|
+
{ id: 'videos', label: 'Videos', icon: '🎥' }
|
|
472
|
+
]
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### Pattern 3: Tool-Based Creation
|
|
477
|
+
|
|
478
|
+
**Use Case:** Design tools, code editors, form builders, canvas applications
|
|
479
|
+
|
|
480
|
+
**Navigation Flow:** Click primary tool → show tool palette → create/edit in workspace
|
|
481
|
+
|
|
482
|
+
```tsx
|
|
483
|
+
interface CreationPattern {
|
|
484
|
+
primaryTools: Array<{ id: string, label: string, icon: string }>
|
|
485
|
+
toolPalette: {
|
|
486
|
+
[toolId: string]: Array<{
|
|
487
|
+
id: string
|
|
488
|
+
name: string
|
|
489
|
+
icon: string
|
|
490
|
+
category: string
|
|
491
|
+
}>
|
|
492
|
+
}
|
|
493
|
+
workspaceType: 'canvas' | 'editor' | 'form' | 'diagram'
|
|
494
|
+
propertiesPanel?: boolean
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Example: Design Tool
|
|
498
|
+
const designPattern: CreationPattern = {
|
|
499
|
+
primaryTools: [
|
|
500
|
+
{ id: 'shapes', label: 'Shapes', icon: '⬜' },
|
|
501
|
+
{ id: 'text', label: 'Text', icon: '📝' },
|
|
502
|
+
{ id: 'components', label: 'Components', icon: '🧩' }
|
|
503
|
+
],
|
|
504
|
+
toolPalette: {
|
|
505
|
+
'shapes': [
|
|
506
|
+
{ id: 'rectangle', name: 'Rectangle', icon: '▭', category: 'basic' },
|
|
507
|
+
{ id: 'circle', name: 'Circle', icon: '○', category: 'basic' }
|
|
508
|
+
]
|
|
509
|
+
},
|
|
510
|
+
workspaceType: 'canvas',
|
|
511
|
+
propertiesPanel: true
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Example: Form Builder
|
|
515
|
+
const formBuilderPattern: CreationPattern = {
|
|
516
|
+
primaryTools: [
|
|
517
|
+
{ id: 'inputs', label: 'Input Fields', icon: '📝' },
|
|
518
|
+
{ id: 'layout', label: 'Layout', icon: '📐' },
|
|
519
|
+
{ id: 'logic', label: 'Logic', icon: '⚡' }
|
|
520
|
+
],
|
|
521
|
+
toolPalette: {
|
|
522
|
+
'inputs': [
|
|
523
|
+
{ id: 'text-input', name: 'Text Input', icon: '📝', category: 'basic' },
|
|
524
|
+
{ id: 'select', name: 'Select', icon: '▼', category: 'choice' }
|
|
525
|
+
]
|
|
526
|
+
},
|
|
527
|
+
workspaceType: 'form',
|
|
528
|
+
propertiesPanel: true
|
|
529
|
+
}
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### Pattern 4: Data Dashboard
|
|
533
|
+
|
|
534
|
+
**Use Case:** Analytics, reporting, monitoring, business intelligence
|
|
535
|
+
|
|
536
|
+
**Navigation Flow:** Click primary metric → show filters/controls → display data visualizations
|
|
537
|
+
|
|
538
|
+
```tsx
|
|
539
|
+
interface DashboardPattern {
|
|
540
|
+
primaryMetrics: Array<{ id: string, label: string, icon: string }>
|
|
541
|
+
filterControls: Array<{
|
|
542
|
+
type: 'date-range' | 'dropdown' | 'slider' | 'checkbox'
|
|
543
|
+
label: string
|
|
544
|
+
options?: string[]
|
|
545
|
+
}>
|
|
546
|
+
visualizationTypes: Array<'chart' | 'table' | 'map' | 'gauge'>
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Example: Analytics Dashboard
|
|
550
|
+
const analyticsPattern: DashboardPattern = {
|
|
551
|
+
primaryMetrics: [
|
|
552
|
+
{ id: 'overview', label: 'Overview', icon: '📊' },
|
|
553
|
+
{ id: 'users', label: 'Users', icon: '👥' },
|
|
554
|
+
{ id: 'revenue', label: 'Revenue', icon: '💰' }
|
|
555
|
+
],
|
|
556
|
+
filterControls: [
|
|
557
|
+
{ type: 'date-range', label: 'Date Range' },
|
|
558
|
+
{ type: 'dropdown', label: 'Region', options: ['US', 'EU', 'Asia'] },
|
|
559
|
+
{ type: 'checkbox', label: 'Compare with previous period' }
|
|
560
|
+
],
|
|
561
|
+
visualizationTypes: ['chart', 'table', 'gauge']
|
|
562
|
+
}
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
## Z-Index Elevation System
|
|
566
|
+
|
|
567
|
+
### Layer Hierarchy
|
|
568
|
+
|
|
569
|
+
```css
|
|
570
|
+
/* styles/elevation.css */
|
|
571
|
+
--z-base: 0
|
|
572
|
+
--z-background: 0
|
|
573
|
+
--z-content: 10
|
|
574
|
+
--z-sticky-content: 15
|
|
575
|
+
--z-sticky-page: 20
|
|
576
|
+
--z-floating: 30
|
|
577
|
+
--z-modal-backdrop: 40
|
|
578
|
+
--z-modal: 50
|
|
579
|
+
--z-popover: 60
|
|
580
|
+
--z-tooltip: 70
|
|
581
|
+
--z-debug: 9999
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
### Usage Examples
|
|
585
|
+
|
|
586
|
+
**Page Headers:**
|
|
587
|
+
```tsx
|
|
588
|
+
<header className="sticky top-0 z-[var(--z-sticky-page)]">
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
**Modal Overlays:**
|
|
592
|
+
```tsx
|
|
593
|
+
<div className="z-[var(--z-modal)]">
|
|
594
|
+
<div className="z-[var(--z-modal-backdrop)]" />
|
|
595
|
+
<div className="z-[var(--z-modal)]" />
|
|
596
|
+
</div>
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
## Scroll Management
|
|
600
|
+
|
|
601
|
+
### Container Isolation
|
|
602
|
+
|
|
603
|
+
**AppLayout Scroll Container:**
|
|
604
|
+
```tsx
|
|
605
|
+
<div
|
|
606
|
+
ref={scrollContainerRef}
|
|
607
|
+
className={cn(
|
|
608
|
+
"flex-1 min-h-0 flex flex-col",
|
|
609
|
+
isAppBuilder ? "overflow-hidden" : "overflow-y-auto overflow-x-hidden"
|
|
610
|
+
)}
|
|
611
|
+
>
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
**Context-based Scrolling:**
|
|
615
|
+
```tsx
|
|
616
|
+
// ScrollContainerContext for main content
|
|
617
|
+
// PageContentContext for page-specific content
|
|
618
|
+
// TableOfContents integrates with both
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
### Scroll Prevention
|
|
622
|
+
|
|
623
|
+
**Body Scroll Lock:**
|
|
624
|
+
```tsx
|
|
625
|
+
React.useEffect(() => {
|
|
626
|
+
// Disable browser scroll restoration
|
|
627
|
+
if ('scrollRestoration' in history) {
|
|
628
|
+
history.scrollRestoration = 'manual'
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Prevent body/html from scrolling
|
|
632
|
+
document.body.style.overflow = 'hidden'
|
|
633
|
+
document.documentElement.style.overflow = 'hidden'
|
|
634
|
+
|
|
635
|
+
return () => {
|
|
636
|
+
// Restore on cleanup
|
|
637
|
+
document.body.style.overflow = ''
|
|
638
|
+
document.documentElement.style.overflow = ''
|
|
639
|
+
}
|
|
640
|
+
}, [])
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
## Universal Implementation Guide
|
|
644
|
+
|
|
645
|
+
### Step 1: Choose Your Content Pattern
|
|
646
|
+
|
|
647
|
+
Based on your application type, select the appropriate pattern:
|
|
648
|
+
|
|
649
|
+
```tsx
|
|
650
|
+
// For a task management app
|
|
651
|
+
const APP_CONFIG = {
|
|
652
|
+
pattern: 'list-detail',
|
|
653
|
+
primaryItems: ['inbox', 'today', 'projects'],
|
|
654
|
+
secondaryType: 'filters',
|
|
655
|
+
mainContentType: 'task-board'
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// For a design tool
|
|
659
|
+
const APP_CONFIG = {
|
|
660
|
+
pattern: 'creation',
|
|
661
|
+
primaryItems: ['shapes', 'text', 'components'],
|
|
662
|
+
secondaryType: 'tools',
|
|
663
|
+
mainContentType: 'canvas'
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// For analytics dashboard
|
|
667
|
+
const APP_CONFIG = {
|
|
668
|
+
pattern: 'dashboard',
|
|
669
|
+
primaryItems: ['overview', 'users', 'revenue'],
|
|
670
|
+
secondaryType: 'filters',
|
|
671
|
+
mainContentType: 'charts'
|
|
672
|
+
}
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
### Step 2: Set Up Core Layout Components
|
|
676
|
+
|
|
677
|
+
**Create the Layout Provider:**
|
|
678
|
+
```tsx
|
|
679
|
+
// src/contexts/LayoutContext.tsx
|
|
680
|
+
import { createContext, useContext, useState, ReactNode } from 'react'
|
|
681
|
+
|
|
682
|
+
interface LayoutContextType {
|
|
683
|
+
activePrimaryItem: string | null
|
|
684
|
+
activeSecondaryItem: string | null
|
|
685
|
+
secondaryContent: ReactNode | null
|
|
686
|
+
isMobile: boolean
|
|
687
|
+
setActivePrimaryItem: (item: string) => void
|
|
688
|
+
setSecondaryContent: (content: ReactNode) => void
|
|
689
|
+
toggleSecondarySidebar: () => void
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
const LayoutContext = createContext<LayoutContextType | null>(null)
|
|
693
|
+
|
|
694
|
+
export function LayoutProvider({ children, config }) {
|
|
695
|
+
const [activePrimaryItem, setActivePrimaryItem] = useState(null)
|
|
696
|
+
const [secondaryContent, setSecondaryContent] = useState(null)
|
|
697
|
+
const [isMobile] = useDeviceType()
|
|
698
|
+
|
|
699
|
+
const value = {
|
|
700
|
+
activePrimaryItem,
|
|
701
|
+
secondaryContent,
|
|
702
|
+
isMobile,
|
|
703
|
+
setActivePrimaryItem,
|
|
704
|
+
setSecondaryContent,
|
|
705
|
+
toggleSecondarySidebar: () => setSecondaryContent(null)
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
return (
|
|
709
|
+
<LayoutContext.Provider value={value}>
|
|
710
|
+
{children}
|
|
711
|
+
</LayoutContext.Provider>
|
|
712
|
+
)
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
export const useLayout = () => {
|
|
716
|
+
const context = useContext(LayoutContext)
|
|
717
|
+
if (!context) throw new Error('useLayout must be used within LayoutProvider')
|
|
718
|
+
return context
|
|
719
|
+
}
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
**Create Layout Components:**
|
|
723
|
+
```tsx
|
|
724
|
+
// src/components/layout/Layout.tsx
|
|
725
|
+
export function Layout({ config, children }) {
|
|
726
|
+
return (
|
|
727
|
+
<LayoutProvider config={config}>
|
|
728
|
+
<div className="flex h-screen bg-background">
|
|
729
|
+
<PrimarySidebar config={config.primary} />
|
|
730
|
+
<SecondarySidebar config={config.secondary} />
|
|
731
|
+
<MainContent config={config.main}>
|
|
732
|
+
{children}
|
|
733
|
+
</MainContent>
|
|
734
|
+
</div>
|
|
735
|
+
</LayoutProvider>
|
|
736
|
+
)
|
|
737
|
+
}
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
### Step 3: Implement Pattern-Specific Components
|
|
741
|
+
|
|
742
|
+
**For List-Detail Pattern:**
|
|
743
|
+
```tsx
|
|
744
|
+
// src/components/patterns/ListDetailPattern.tsx
|
|
745
|
+
export function ListDetailPattern({ config, data }) {
|
|
746
|
+
const { setSecondaryContent, isMobile } = useLayout()
|
|
747
|
+
|
|
748
|
+
const handlePrimarySelect = (itemId) => {
|
|
749
|
+
const filteredData = filterData(data, itemId)
|
|
750
|
+
const listComponent = (
|
|
751
|
+
<DataList
|
|
752
|
+
items={filteredData}
|
|
753
|
+
onItemSelect={(item) => setSecondaryContent(
|
|
754
|
+
<ItemDetailView item={item} />
|
|
755
|
+
)}
|
|
756
|
+
/>
|
|
757
|
+
)
|
|
758
|
+
|
|
759
|
+
if (isMobile) {
|
|
760
|
+
// Show as modal on mobile
|
|
761
|
+
setSecondaryContent(
|
|
762
|
+
<Sheet open={true} onOpenChange={() => setSecondaryContent(null)}>
|
|
763
|
+
<SheetContent>{listComponent}</SheetContent>
|
|
764
|
+
</Sheet>
|
|
765
|
+
)
|
|
766
|
+
} else {
|
|
767
|
+
setSecondaryContent(listComponent)
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
return (
|
|
772
|
+
<PrimaryNavigation
|
|
773
|
+
items={config.primaryItems}
|
|
774
|
+
onSelect={handlePrimarySelect}
|
|
775
|
+
/>
|
|
776
|
+
)
|
|
777
|
+
}
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
**For Creation Pattern:**
|
|
781
|
+
```tsx
|
|
782
|
+
// src/components/patterns/CreationPattern.tsx
|
|
783
|
+
export function CreationPattern({ config }) {
|
|
784
|
+
const { setSecondaryContent } = useLayout()
|
|
785
|
+
|
|
786
|
+
const handlePrimarySelect = (toolId) => {
|
|
787
|
+
const paletteComponent = (
|
|
788
|
+
<ToolPalette
|
|
789
|
+
tools={config.toolPalette[toolId]}
|
|
790
|
+
onToolSelect={(tool) => {
|
|
791
|
+
// Add tool to canvas
|
|
792
|
+
canvasActions.addTool(tool)
|
|
793
|
+
}}
|
|
794
|
+
/>
|
|
795
|
+
)
|
|
796
|
+
|
|
797
|
+
setSecondaryContent(paletteComponent)
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
return (
|
|
801
|
+
<>
|
|
802
|
+
<PrimaryNavigation
|
|
803
|
+
items={config.primaryTools}
|
|
804
|
+
onSelect={handlePrimarySelect}
|
|
805
|
+
/>
|
|
806
|
+
<Canvas workspaceType={config.workspaceType} />
|
|
807
|
+
{config.propertiesPanel && <PropertiesPanel />}
|
|
808
|
+
</>
|
|
809
|
+
)
|
|
810
|
+
}
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
### Step 4: Configure Your Application
|
|
814
|
+
|
|
815
|
+
**Create App Configuration:**
|
|
816
|
+
```tsx
|
|
817
|
+
// src/config/appConfig.ts
|
|
818
|
+
export const APP_CONFIG = {
|
|
819
|
+
// Application metadata
|
|
820
|
+
name: 'My Dashboard App',
|
|
821
|
+
version: '1.0.0',
|
|
822
|
+
|
|
823
|
+
// Layout configuration
|
|
824
|
+
layout: {
|
|
825
|
+
breakpoints: {
|
|
826
|
+
mobile: 768,
|
|
827
|
+
tablet: 1024,
|
|
828
|
+
desktop: 1440
|
|
829
|
+
},
|
|
830
|
+
dimensions: {
|
|
831
|
+
primarySidebar: '22rem',
|
|
832
|
+
secondarySidebar: '20rem',
|
|
833
|
+
iconWidth: '3rem'
|
|
834
|
+
}
|
|
835
|
+
},
|
|
836
|
+
|
|
837
|
+
// Content pattern
|
|
838
|
+
pattern: 'list-detail', // or 'creation', 'dashboard', 'hierarchical'
|
|
839
|
+
|
|
840
|
+
// Primary navigation items
|
|
841
|
+
primaryNavigation: [
|
|
842
|
+
{ id: 'dashboard', label: 'Dashboard', icon: 'HomeIcon' },
|
|
843
|
+
{ id: 'projects', label: 'Projects', icon: 'FolderIcon' },
|
|
844
|
+
{ id: 'team', label: 'Team', icon: 'UsersIcon' },
|
|
845
|
+
{ id: 'settings', label: 'Settings', icon: 'SettingsIcon' }
|
|
846
|
+
],
|
|
847
|
+
|
|
848
|
+
// Secondary content configuration
|
|
849
|
+
secondaryContent: {
|
|
850
|
+
type: 'filters', // 'filters', 'tools', 'navigation', 'properties'
|
|
851
|
+
searchable: true,
|
|
852
|
+
collapsible: true
|
|
853
|
+
},
|
|
854
|
+
|
|
855
|
+
// Main content configuration
|
|
856
|
+
mainContent: {
|
|
857
|
+
type: 'workspace', // 'workspace', 'canvas', 'dashboard'
|
|
858
|
+
scrollable: true,
|
|
859
|
+
header: true,
|
|
860
|
+
footer: false
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
### Step 5: Integrate with Your App
|
|
866
|
+
|
|
867
|
+
**Update Your Root Component:**
|
|
868
|
+
```tsx
|
|
869
|
+
// src/App.tsx
|
|
870
|
+
import { Layout } from '@/components/layout/Layout'
|
|
871
|
+
import { APP_CONFIG } from '@/config/appConfig'
|
|
872
|
+
import { DashboardView } from '@/views/DashboardView'
|
|
873
|
+
import { ProjectsView } from '@/views/ProjectsView'
|
|
874
|
+
// ... other views
|
|
875
|
+
|
|
876
|
+
function AppContent() {
|
|
877
|
+
const { activePrimaryItem } = useLayout()
|
|
878
|
+
|
|
879
|
+
switch (activePrimaryItem) {
|
|
880
|
+
case 'dashboard':
|
|
881
|
+
return <DashboardView />
|
|
882
|
+
case 'projects':
|
|
883
|
+
return <ProjectsView />
|
|
884
|
+
case 'team':
|
|
885
|
+
return <TeamView />
|
|
886
|
+
case 'settings':
|
|
887
|
+
return <SettingsView />
|
|
888
|
+
default:
|
|
889
|
+
return <DashboardView />
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
export function App() {
|
|
894
|
+
return (
|
|
895
|
+
<Layout config={APP_CONFIG}>
|
|
896
|
+
<AppContent />
|
|
897
|
+
</Layout>
|
|
898
|
+
)
|
|
899
|
+
}
|
|
900
|
+
```
|
|
901
|
+
|
|
902
|
+
### Step 6: Add Responsive Behavior
|
|
903
|
+
|
|
904
|
+
**Mobile Optimizations:**
|
|
905
|
+
```tsx
|
|
906
|
+
// src/hooks/useResponsiveLayout.ts
|
|
907
|
+
export function useResponsiveLayout() {
|
|
908
|
+
const { isMobile, isTablet } = useDeviceType()
|
|
909
|
+
const { setSecondaryContent } = useLayout()
|
|
910
|
+
|
|
911
|
+
const adaptToMobile = (content) => {
|
|
912
|
+
if (isMobile) {
|
|
913
|
+
return (
|
|
914
|
+
<Sheet>
|
|
915
|
+
<SheetContent side="right" className="w-full">
|
|
916
|
+
{content}
|
|
917
|
+
</SheetContent>
|
|
918
|
+
</Sheet>
|
|
919
|
+
)
|
|
920
|
+
}
|
|
921
|
+
return content
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
const adaptNavigation = (navigation) => {
|
|
925
|
+
if (isMobile) {
|
|
926
|
+
return (
|
|
927
|
+
<Drawer>
|
|
928
|
+
<DrawerContent>
|
|
929
|
+
{navigation}
|
|
930
|
+
</DrawerContent>
|
|
931
|
+
</Drawer>
|
|
932
|
+
)
|
|
933
|
+
}
|
|
934
|
+
return navigation
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
return { adaptToMobile, adaptNavigation, isMobile, isTablet }
|
|
938
|
+
}
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
### Step 7: Testing & Validation
|
|
942
|
+
|
|
943
|
+
**Cross-Device Testing Checklist:**
|
|
944
|
+
- [ ] Desktop (1440px+): All panels visible, collapsible primary sidebar
|
|
945
|
+
- [ ] Tablet (768px-1024px): Primary sidebar icons-only, secondary overlay
|
|
946
|
+
- [ ] Mobile (<768px): Single panel, drawer navigation, modal secondary content
|
|
947
|
+
- [ ] Touch targets: Minimum 44px for mobile interactions
|
|
948
|
+
- [ ] Keyboard navigation: Tab order, shortcuts, focus management
|
|
949
|
+
- [ ] Content overflow: Proper scrolling in constrained layouts
|
|
950
|
+
|
|
951
|
+
## Future Scaling Considerations
|
|
952
|
+
|
|
953
|
+
### Modular Sidebar System
|
|
954
|
+
|
|
955
|
+
**Component Registry Pattern:**
|
|
956
|
+
```tsx
|
|
957
|
+
interface SidebarConfig {
|
|
958
|
+
route: string
|
|
959
|
+
component: React.ComponentType
|
|
960
|
+
header?: React.ComponentType
|
|
961
|
+
requiresAuth?: boolean
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// Registry-based sidebar rendering
|
|
965
|
+
const sidebarConfigs: SidebarConfig[] = [
|
|
966
|
+
{ route: "/inbox", component: MailboxSidebar },
|
|
967
|
+
{ route: "/charts", component: TocSidebar },
|
|
968
|
+
{ route: "/app-builder", component: WidgetPalette },
|
|
969
|
+
]
|
|
970
|
+
```
|
|
971
|
+
|
|
972
|
+
### Advanced State Management
|
|
973
|
+
|
|
974
|
+
**Global Layout Context:**
|
|
975
|
+
```tsx
|
|
976
|
+
interface LayoutContextValue {
|
|
977
|
+
primarySidebar: {
|
|
978
|
+
collapsed: boolean
|
|
979
|
+
width: number
|
|
980
|
+
}
|
|
981
|
+
secondarySidebar: {
|
|
982
|
+
visible: boolean
|
|
983
|
+
content: React.ReactNode
|
|
984
|
+
}
|
|
985
|
+
breadcrumbs: BreadcrumbItem[]
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
const LayoutContext = React.createContext<LayoutContextValue | null>(null)
|
|
989
|
+
```
|
|
990
|
+
|
|
991
|
+
### Performance Optimizations
|
|
992
|
+
|
|
993
|
+
**Lazy Loading Sidebars:**
|
|
994
|
+
```tsx
|
|
995
|
+
const LazyMailboxSidebar = React.lazy(() => import('./sidebars/MailboxSidebar'))
|
|
996
|
+
const LazyTocSidebar = React.lazy(() => import('./sidebars/TocSidebar'))
|
|
997
|
+
|
|
998
|
+
<Suspense fallback={<Skeleton />}>
|
|
999
|
+
{isMailboxRoute && <LazyMailboxSidebar />}
|
|
1000
|
+
{isShowcaseRoute && <LazyTocSidebar />}
|
|
1001
|
+
</Suspense>
|
|
1002
|
+
```
|
|
1003
|
+
|
|
1004
|
+
### Accessibility Enhancements
|
|
1005
|
+
|
|
1006
|
+
**ARIA Landmark Pattern:**
|
|
1007
|
+
```tsx
|
|
1008
|
+
<aside aria-label="Primary navigation" role="navigation">
|
|
1009
|
+
{/* Primary sidebar */}
|
|
1010
|
+
</aside>
|
|
1011
|
+
|
|
1012
|
+
<aside aria-label="Secondary content" role="complementary">
|
|
1013
|
+
{/* Secondary sidebar */}
|
|
1014
|
+
</aside>
|
|
1015
|
+
|
|
1016
|
+
<main role="main" aria-label="Main content">
|
|
1017
|
+
{/* Main content */}
|
|
1018
|
+
</main>
|
|
1019
|
+
```
|
|
1020
|
+
|
|
1021
|
+
### Theme & Customization
|
|
1022
|
+
|
|
1023
|
+
**Dynamic Sidebar Widths:**
|
|
1024
|
+
```tsx
|
|
1025
|
+
const sidebarWidth = useThemePreference('sidebar.width') || '22rem'
|
|
1026
|
+
|
|
1027
|
+
style={{
|
|
1028
|
+
'--sidebar-width': sidebarWidth
|
|
1029
|
+
}}
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
## Migration Guide
|
|
1033
|
+
|
|
1034
|
+
### From Single Sidebar to Multi-Level
|
|
1035
|
+
|
|
1036
|
+
1. Wrap existing sidebar in nested structure
|
|
1037
|
+
2. Add collapsible behavior to primary sidebar
|
|
1038
|
+
3. Implement conditional rendering for secondary content
|
|
1039
|
+
4. Update responsive breakpoints
|
|
1040
|
+
5. Add scroll container management
|
|
1041
|
+
|
|
1042
|
+
### From Fixed to Flexible Layout
|
|
1043
|
+
|
|
1044
|
+
1. Replace fixed widths with CSS variables
|
|
1045
|
+
2. Implement flex-based layout
|
|
1046
|
+
3. Add responsive breakpoints
|
|
1047
|
+
4. Update z-index usage
|
|
1048
|
+
5. Add scroll management
|
|
1049
|
+
|
|
1050
|
+
## Testing Strategy
|
|
1051
|
+
|
|
1052
|
+
### Layout Testing Checklist
|
|
1053
|
+
|
|
1054
|
+
- [ ] Desktop: All panels visible, collapsible
|
|
1055
|
+
- [ ] Tablet: Primary sidebar icons, secondary overlay
|
|
1056
|
+
- [ ] Mobile: Single panel, drawer navigation
|
|
1057
|
+
- [ ] Keyboard: Tab navigation, shortcuts work
|
|
1058
|
+
- [ ] Touch: Swipe gestures, touch targets adequate
|
|
1059
|
+
- [ ] Performance: Smooth animations, no layout thrashing
|
|
1060
|
+
- [ ] Accessibility: Screen readers, focus management
|
|
1061
|
+
|
|
1062
|
+
### Component Testing
|
|
1063
|
+
|
|
1064
|
+
```tsx
|
|
1065
|
+
// Test responsive behavior
|
|
1066
|
+
describe('AppSidebar', () => {
|
|
1067
|
+
it('shows secondary sidebar on desktop', () => {
|
|
1068
|
+
// Mock desktop viewport
|
|
1069
|
+
// Assert secondary sidebar visible
|
|
1070
|
+
})
|
|
1071
|
+
|
|
1072
|
+
it('hides secondary sidebar on mobile', () => {
|
|
1073
|
+
// Mock mobile viewport
|
|
1074
|
+
// Assert secondary sidebar hidden
|
|
1075
|
+
})
|
|
1076
|
+
})
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
## Universal Scaling Architecture
|
|
1080
|
+
|
|
1081
|
+
### Content-Agnostic Component Registry
|
|
1082
|
+
|
|
1083
|
+
**Plugin-Based Sidebar System:**
|
|
1084
|
+
```tsx
|
|
1085
|
+
interface SidebarPlugin {
|
|
1086
|
+
id: string
|
|
1087
|
+
name: string
|
|
1088
|
+
pattern: ContentPattern
|
|
1089
|
+
primaryItems: NavigationItem[]
|
|
1090
|
+
secondaryRenderer: (context: any) => React.ReactNode
|
|
1091
|
+
mainRenderer: (context: any) => React.ReactNode
|
|
1092
|
+
config: PluginConfig
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// Registry for different application types
|
|
1096
|
+
const PLUGIN_REGISTRY = {
|
|
1097
|
+
'email-client': emailPlugin,
|
|
1098
|
+
'task-manager': taskManagerPlugin,
|
|
1099
|
+
'design-tool': designToolPlugin,
|
|
1100
|
+
'analytics-dashboard': analyticsPlugin,
|
|
1101
|
+
'cms': contentManagementPlugin
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
// Dynamic layout based on plugin
|
|
1105
|
+
function DynamicLayout({ pluginId, context }) {
|
|
1106
|
+
const plugin = PLUGIN_REGISTRY[pluginId]
|
|
1107
|
+
|
|
1108
|
+
return (
|
|
1109
|
+
<LayoutProvider config={plugin.config}>
|
|
1110
|
+
<PrimarySidebar items={plugin.primaryItems} />
|
|
1111
|
+
<SecondarySidebar>
|
|
1112
|
+
{plugin.secondaryRenderer(context)}
|
|
1113
|
+
</SecondarySidebar>
|
|
1114
|
+
<MainContent>
|
|
1115
|
+
{plugin.mainRenderer(context)}
|
|
1116
|
+
</MainContent>
|
|
1117
|
+
</LayoutProvider>
|
|
1118
|
+
)
|
|
1119
|
+
}
|
|
1120
|
+
```
|
|
1121
|
+
|
|
1122
|
+
### Advanced State Management Patterns
|
|
1123
|
+
|
|
1124
|
+
**Universal Layout State:**
|
|
1125
|
+
```tsx
|
|
1126
|
+
interface UniversalLayoutState {
|
|
1127
|
+
// Navigation state
|
|
1128
|
+
navigation: {
|
|
1129
|
+
primary: string | null
|
|
1130
|
+
secondary: string | null
|
|
1131
|
+
breadcrumbs: BreadcrumbItem[]
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
// Content state
|
|
1135
|
+
content: {
|
|
1136
|
+
type: ContentType
|
|
1137
|
+
data: any
|
|
1138
|
+
filters: Record<string, any>
|
|
1139
|
+
selection: any[]
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// UI state
|
|
1143
|
+
ui: {
|
|
1144
|
+
device: DeviceType
|
|
1145
|
+
theme: ThemeConfig
|
|
1146
|
+
preferences: UserPreferences
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
// Actions
|
|
1150
|
+
actions: {
|
|
1151
|
+
navigate: (primary: string, secondary?: string) => void
|
|
1152
|
+
updateFilters: (filters: Record<string, any>) => void
|
|
1153
|
+
selectItems: (items: any[]) => void
|
|
1154
|
+
toggleSidebar: (sidebar: 'primary' | 'secondary') => void
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
```
|
|
1158
|
+
|
|
1159
|
+
### Performance Optimization Strategies
|
|
1160
|
+
|
|
1161
|
+
**Component Virtualization:**
|
|
1162
|
+
```tsx
|
|
1163
|
+
// For large lists in secondary sidebar
|
|
1164
|
+
import { FixedSizeList as List } from 'react-window'
|
|
1165
|
+
|
|
1166
|
+
function VirtualizedItemList({ items, itemHeight = 50 }) {
|
|
1167
|
+
return (
|
|
1168
|
+
<List
|
|
1169
|
+
height={400}
|
|
1170
|
+
itemCount={items.length}
|
|
1171
|
+
itemSize={itemHeight}
|
|
1172
|
+
>
|
|
1173
|
+
{({ index, style }) => (
|
|
1174
|
+
<div style={style}>
|
|
1175
|
+
<ItemComponent item={items[index]} />
|
|
1176
|
+
</div>
|
|
1177
|
+
)}
|
|
1178
|
+
</List>
|
|
1179
|
+
)
|
|
1180
|
+
}
|
|
1181
|
+
```
|
|
1182
|
+
|
|
1183
|
+
**Lazy Loading by Pattern:**
|
|
1184
|
+
```tsx
|
|
1185
|
+
const PATTERN_COMPONENTS = {
|
|
1186
|
+
'list-detail': React.lazy(() => import('./patterns/ListDetailPattern')),
|
|
1187
|
+
'creation': React.lazy(() => import('./patterns/CreationPattern')),
|
|
1188
|
+
'dashboard': React.lazy(() => import('./patterns/DashboardPattern')),
|
|
1189
|
+
'hierarchical': React.lazy(() => import('./patterns/HierarchicalPattern'))
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
function LazyPatternRenderer({ pattern, ...props }) {
|
|
1193
|
+
const PatternComponent = PATTERN_COMPONENTS[pattern]
|
|
1194
|
+
|
|
1195
|
+
return (
|
|
1196
|
+
<Suspense fallback={<PatternSkeleton />}>
|
|
1197
|
+
<PatternComponent {...props} />
|
|
1198
|
+
</Suspense>
|
|
1199
|
+
)
|
|
1200
|
+
}
|
|
1201
|
+
```
|
|
1202
|
+
|
|
1203
|
+
### Accessibility & Internationalization
|
|
1204
|
+
|
|
1205
|
+
**Universal ARIA Implementation:**
|
|
1206
|
+
```tsx
|
|
1207
|
+
function AccessibleLayout({ config }) {
|
|
1208
|
+
return (
|
|
1209
|
+
<div role="application" aria-label={config.name}>
|
|
1210
|
+
<aside
|
|
1211
|
+
role="navigation"
|
|
1212
|
+
aria-label="Primary navigation"
|
|
1213
|
+
aria-expanded={!config.collapsed}
|
|
1214
|
+
>
|
|
1215
|
+
<PrimarySidebar {...config.primary} />
|
|
1216
|
+
</aside>
|
|
1217
|
+
|
|
1218
|
+
<aside
|
|
1219
|
+
role="complementary"
|
|
1220
|
+
aria-label={`${config.secondary.type} panel`}
|
|
1221
|
+
aria-hidden={config.isMobile && !config.secondary.open}
|
|
1222
|
+
>
|
|
1223
|
+
<SecondarySidebar {...config.secondary} />
|
|
1224
|
+
</aside>
|
|
1225
|
+
|
|
1226
|
+
<main
|
|
1227
|
+
role="main"
|
|
1228
|
+
aria-label="Main content area"
|
|
1229
|
+
tabIndex={-1}
|
|
1230
|
+
>
|
|
1231
|
+
<MainContent {...config.main} />
|
|
1232
|
+
</main>
|
|
1233
|
+
</div>
|
|
1234
|
+
)
|
|
1235
|
+
}
|
|
1236
|
+
```
|
|
1237
|
+
|
|
1238
|
+
**Internationalization Support:**
|
|
1239
|
+
```tsx
|
|
1240
|
+
interface I18nLayoutConfig {
|
|
1241
|
+
locale: string
|
|
1242
|
+
direction: 'ltr' | 'rtl'
|
|
1243
|
+
translations: {
|
|
1244
|
+
navigation: Record<string, string>
|
|
1245
|
+
secondaryContent: Record<string, string>
|
|
1246
|
+
actions: Record<string, string>
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
// RTL-aware layout adjustments
|
|
1251
|
+
function RTLLayout({ children, direction }) {
|
|
1252
|
+
return (
|
|
1253
|
+
<div dir={direction} className={direction === 'rtl' ? 'rtl-layout' : ''}>
|
|
1254
|
+
{children}
|
|
1255
|
+
</div>
|
|
1256
|
+
)
|
|
1257
|
+
}
|
|
1258
|
+
```
|
|
1259
|
+
|
|
1260
|
+
### Theme & Customization System
|
|
1261
|
+
|
|
1262
|
+
**Dynamic Theming:**
|
|
1263
|
+
```tsx
|
|
1264
|
+
interface ThemeConfig {
|
|
1265
|
+
colors: {
|
|
1266
|
+
primary: string
|
|
1267
|
+
secondary: string
|
|
1268
|
+
sidebar: string
|
|
1269
|
+
background: string
|
|
1270
|
+
}
|
|
1271
|
+
spacing: {
|
|
1272
|
+
sidebarWidth: string
|
|
1273
|
+
contentPadding: string
|
|
1274
|
+
}
|
|
1275
|
+
typography: {
|
|
1276
|
+
fontFamily: string
|
|
1277
|
+
fontSize: string
|
|
1278
|
+
}
|
|
1279
|
+
animations: {
|
|
1280
|
+
duration: string
|
|
1281
|
+
easing: string
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
function ThemedLayout({ theme, children }) {
|
|
1286
|
+
// Apply CSS variables dynamically
|
|
1287
|
+
useEffect(() => {
|
|
1288
|
+
Object.entries(theme).forEach(([category, values]) => {
|
|
1289
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
1290
|
+
document.documentElement.style.setProperty(
|
|
1291
|
+
`--theme-${category}-${key}`,
|
|
1292
|
+
value
|
|
1293
|
+
)
|
|
1294
|
+
})
|
|
1295
|
+
})
|
|
1296
|
+
}, [theme])
|
|
1297
|
+
|
|
1298
|
+
return <div className="themed-layout">{children}</div>
|
|
1299
|
+
}
|
|
1300
|
+
```
|
|
1301
|
+
|
|
1302
|
+
## Universal Migration Strategy
|
|
1303
|
+
|
|
1304
|
+
### Pattern Migration Matrix
|
|
1305
|
+
|
|
1306
|
+
| Current App Type | Recommended Pattern | Migration Steps |
|
|
1307
|
+
|------------------|-------------------|-----------------|
|
|
1308
|
+
| Email Client | List-Detail | 1. Extract message list to secondary sidebar<br>2. Convert primary nav to mailbox selector<br>3. Move message view to main content |
|
|
1309
|
+
| Task Manager | List-Detail | 1. Primary: Today/Week/Projects<br>2. Secondary: Task filters & lists<br>3. Main: Task details & boards |
|
|
1310
|
+
| Design Tool | Creation | 1. Primary: Tool categories<br>2. Secondary: Tool palettes<br>3. Main: Canvas workspace |
|
|
1311
|
+
| Analytics | Dashboard | 1. Primary: Metric categories<br>2. Secondary: Date/filter controls<br>3. Main: Charts & visualizations |
|
|
1312
|
+
| File Manager | Hierarchical | 1. Primary: Drive shortcuts<br>2. Secondary: Folder tree<br>3. Main: File content viewer |
|
|
1313
|
+
| CMS | Hierarchical | 1. Primary: Content types<br>2. Secondary: Content list<br>3. Main: Content editor |
|
|
1314
|
+
|
|
1315
|
+
### Step-by-Step Migration Process
|
|
1316
|
+
|
|
1317
|
+
1. **Analyze Current Layout:**
|
|
1318
|
+
- Identify primary navigation items
|
|
1319
|
+
- Map secondary content/filtering
|
|
1320
|
+
- Determine main content type
|
|
1321
|
+
|
|
1322
|
+
2. **Choose Appropriate Pattern:**
|
|
1323
|
+
- Match against pattern matrix
|
|
1324
|
+
- Consider user workflows
|
|
1325
|
+
- Evaluate complexity vs. benefits
|
|
1326
|
+
|
|
1327
|
+
3. **Implement Core Layout:**
|
|
1328
|
+
- Set up LayoutProvider
|
|
1329
|
+
- Create responsive components
|
|
1330
|
+
- Configure breakpoints
|
|
1331
|
+
|
|
1332
|
+
4. **Migrate Content Components:**
|
|
1333
|
+
- Adapt existing components to new structure
|
|
1334
|
+
- Implement pattern-specific logic
|
|
1335
|
+
- Add responsive behavior
|
|
1336
|
+
|
|
1337
|
+
5. **Testing & Refinement:**
|
|
1338
|
+
- Cross-device testing
|
|
1339
|
+
- Performance optimization
|
|
1340
|
+
- User experience validation
|
|
1341
|
+
|
|
1342
|
+
## Quality Assurance Framework
|
|
1343
|
+
|
|
1344
|
+
### Automated Testing Suite
|
|
1345
|
+
|
|
1346
|
+
**Layout Component Tests:**
|
|
1347
|
+
```tsx
|
|
1348
|
+
describe('Universal Layout System', () => {
|
|
1349
|
+
describe('Responsive Behavior', () => {
|
|
1350
|
+
it('adapts to mobile layout', () => {
|
|
1351
|
+
// Mock mobile viewport
|
|
1352
|
+
const { result } = renderHook(() => useDeviceType(), {
|
|
1353
|
+
wrapper: ({ children }) => (
|
|
1354
|
+
<div style={{ width: '375px' }}>{children}</div>
|
|
1355
|
+
)
|
|
1356
|
+
})
|
|
1357
|
+
|
|
1358
|
+
expect(result.current.isMobile).toBe(true)
|
|
1359
|
+
})
|
|
1360
|
+
|
|
1361
|
+
it('maintains state across device changes', () => {
|
|
1362
|
+
// Test layout state persistence
|
|
1363
|
+
})
|
|
1364
|
+
})
|
|
1365
|
+
|
|
1366
|
+
describe('Pattern Implementation', () => {
|
|
1367
|
+
it('renders list-detail pattern correctly', () => {
|
|
1368
|
+
const config = { pattern: 'list-detail' }
|
|
1369
|
+
render(<Layout config={config} />)
|
|
1370
|
+
|
|
1371
|
+
expect(screen.getByRole('navigation')).toBeInTheDocument()
|
|
1372
|
+
expect(screen.getByRole('complementary')).toBeInTheDocument()
|
|
1373
|
+
expect(screen.getByRole('main')).toBeInTheDocument()
|
|
1374
|
+
})
|
|
1375
|
+
})
|
|
1376
|
+
|
|
1377
|
+
describe('Accessibility', () => {
|
|
1378
|
+
it('provides proper ARIA labels', () => {
|
|
1379
|
+
render(<AccessibleLayout config={mockConfig} />)
|
|
1380
|
+
|
|
1381
|
+
expect(screen.getByLabelText('Primary navigation')).toBeInTheDocument()
|
|
1382
|
+
expect(screen.getByLabelText('Main content area')).toBeInTheDocument()
|
|
1383
|
+
})
|
|
1384
|
+
})
|
|
1385
|
+
})
|
|
1386
|
+
```
|
|
1387
|
+
|
|
1388
|
+
### Performance Benchmarks
|
|
1389
|
+
|
|
1390
|
+
**Layout Rendering Performance:**
|
|
1391
|
+
- Desktop: < 16ms initial render
|
|
1392
|
+
- Mobile: < 32ms initial render
|
|
1393
|
+
- Sidebar transitions: < 8ms
|
|
1394
|
+
- Content switches: < 50ms
|
|
1395
|
+
|
|
1396
|
+
### User Experience Metrics
|
|
1397
|
+
|
|
1398
|
+
**Key Performance Indicators:**
|
|
1399
|
+
- Time to interactive: < 2 seconds
|
|
1400
|
+
- Layout shift: < 0.1 cumulative
|
|
1401
|
+
- Touch target accuracy: > 95%
|
|
1402
|
+
- Keyboard navigation: Full WCAG compliance
|
|
1403
|
+
|
|
1404
|
+
## Conclusion
|
|
1405
|
+
|
|
1406
|
+
This universal three-panel layout system provides a **content-agnostic foundation** for building any dashboard-style application. The design patterns are proven, the implementation is flexible, and the architecture scales from simple prototypes to complex enterprise applications.
|
|
1407
|
+
|
|
1408
|
+
### Key Universal Principles:
|
|
1409
|
+
|
|
1410
|
+
1. **Content Pattern Matching**: Choose the right pattern for your content type
|
|
1411
|
+
2. **Progressive Enhancement**: Desktop-first, mobile-optimized
|
|
1412
|
+
3. **Component Modularity**: Reusable components across applications
|
|
1413
|
+
4. **Responsive Consistency**: Same behavior patterns across devices
|
|
1414
|
+
5. **Accessibility First**: WCAG compliance built-in
|
|
1415
|
+
6. **Performance Focused**: Optimized for real-world usage
|
|
1416
|
+
7. **Themeable & Customizable**: Adaptable to any design system
|
|
1417
|
+
|
|
1418
|
+
### Implementation Checklist:
|
|
1419
|
+
|
|
1420
|
+
- [ ] Choose appropriate content pattern
|
|
1421
|
+
- [ ] Set up universal layout components
|
|
1422
|
+
- [ ] Configure responsive breakpoints
|
|
1423
|
+
- [ ] Implement pattern-specific logic
|
|
1424
|
+
- [ ] Add accessibility features
|
|
1425
|
+
- [ ] Test across devices and screen sizes
|
|
1426
|
+
- [ ] Optimize for performance
|
|
1427
|
+
- [ ] Document customizations
|
|
1428
|
+
|
|
1429
|
+
This system enables you to build the same architectural excellence across different applications, ensuring consistent user experience and developer productivity regardless of the underlying content or domain.
|