@rakeyshgidwani/roger-ui-bank-theme-harvey 0.2.52 → 0.3.1

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.
Files changed (131) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/dist/components/ui/button.d.ts +3 -1
  3. package/dist/components/ui/button.d.ts.map +1 -1
  4. package/dist/components/ui/button.esm.js +3 -2
  5. package/dist/components/ui/button.js +3 -2
  6. package/dist/components/ui/layout/container.d.ts +57 -0
  7. package/dist/components/ui/layout/container.d.ts.map +1 -0
  8. package/dist/components/ui/layout/container.esm.js +173 -0
  9. package/dist/components/ui/layout/container.js +173 -0
  10. package/dist/components/ui/layout/index.d.ts +9 -0
  11. package/dist/components/ui/layout/index.d.ts.map +1 -0
  12. package/dist/components/ui/layout/index.esm.js +6 -0
  13. package/dist/components/ui/layout/index.js +6 -0
  14. package/dist/components/ui/layout/responsive-grid.d.ts +93 -0
  15. package/dist/components/ui/layout/responsive-grid.d.ts.map +1 -0
  16. package/dist/components/ui/layout/responsive-grid.esm.js +124 -0
  17. package/dist/components/ui/layout/responsive-grid.js +124 -0
  18. package/dist/components/ui/layouts/adaptive-layout.d.ts +1 -0
  19. package/dist/components/ui/layouts/adaptive-layout.d.ts.map +1 -1
  20. package/dist/components/ui/layouts/adaptive-layout.esm.js +2 -2
  21. package/dist/components/ui/layouts/adaptive-layout.js +2 -2
  22. package/dist/components/ui/navigation/index.d.ts +2 -1
  23. package/dist/components/ui/navigation/index.d.ts.map +1 -1
  24. package/dist/components/ui/navigation/index.esm.js +1 -0
  25. package/dist/components/ui/navigation/index.js +1 -0
  26. package/dist/components/ui/navigation/progressive-navigation.d.ts +37 -0
  27. package/dist/components/ui/navigation/progressive-navigation.d.ts.map +1 -0
  28. package/dist/components/ui/navigation/progressive-navigation.esm.js +145 -0
  29. package/dist/components/ui/navigation/progressive-navigation.js +145 -0
  30. package/dist/components/ui/navigation/types.d.ts +21 -0
  31. package/dist/components/ui/navigation/types.d.ts.map +1 -1
  32. package/dist/hooks/use-adaptive-layout.d.ts +2 -1
  33. package/dist/hooks/use-adaptive-layout.d.ts.map +1 -1
  34. package/dist/hooks/use-adaptive-layout.esm.js +13 -8
  35. package/dist/hooks/use-adaptive-layout.js +13 -8
  36. package/dist/hooks/use-device.d.ts +3 -1
  37. package/dist/hooks/use-device.d.ts.map +1 -1
  38. package/dist/hooks/use-device.esm.js +14 -7
  39. package/dist/hooks/use-device.js +14 -7
  40. package/dist/index.d.ts +19 -4
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.esm.js +9 -4
  43. package/dist/index.js +9 -4
  44. package/dist/plugins/css-purge-optimizer.d.ts +25 -0
  45. package/dist/plugins/css-purge-optimizer.d.ts.map +1 -0
  46. package/dist/plugins/css-purge-optimizer.esm.js +414 -0
  47. package/dist/plugins/css-purge-optimizer.js +414 -0
  48. package/dist/plugins/performance-monitor.d.ts +29 -0
  49. package/dist/plugins/performance-monitor.d.ts.map +1 -0
  50. package/dist/plugins/performance-monitor.esm.js +221 -0
  51. package/dist/plugins/performance-monitor.js +221 -0
  52. package/dist/plugins/progressive-css-loader.d.ts +21 -0
  53. package/dist/plugins/progressive-css-loader.d.ts.map +1 -0
  54. package/dist/plugins/progressive-css-loader.esm.js +227 -0
  55. package/dist/plugins/progressive-css-loader.js +227 -0
  56. package/dist/plugins/theme-css-generator.d.ts.map +1 -1
  57. package/dist/plugins/theme-css-generator.esm.js +19 -6
  58. package/dist/plugins/theme-css-generator.js +19 -6
  59. package/dist/styles.css +1027 -112
  60. package/dist/theme.d.ts.map +1 -1
  61. package/dist/theme.esm.js +4 -1
  62. package/dist/theme.js +4 -1
  63. package/dist/themes/phase1-constants.d.ts +23 -0
  64. package/dist/themes/phase1-constants.d.ts.map +1 -0
  65. package/dist/themes/phase1-constants.esm.js +180 -0
  66. package/dist/themes/phase1-constants.js +180 -0
  67. package/dist/themes/themes/default.d.ts.map +1 -1
  68. package/dist/themes/themes/default.esm.js +4 -1
  69. package/dist/themes/themes/default.js +4 -1
  70. package/dist/themes/themes/harvey.d.ts.map +1 -1
  71. package/dist/themes/themes/harvey.esm.js +4 -1
  72. package/dist/themes/themes/harvey.js +4 -1
  73. package/dist/themes/types.d.ts +62 -0
  74. package/dist/themes/types.d.ts.map +1 -1
  75. package/dist/themes/validation.d.ts +17 -0
  76. package/dist/themes/validation.d.ts.map +1 -1
  77. package/dist/themes/validation.esm.js +218 -0
  78. package/dist/themes/validation.js +218 -0
  79. package/dist/types.d.ts +62 -0
  80. package/dist/types.d.ts.map +1 -1
  81. package/dist/utils/progressive-css-injector.d.ts +80 -0
  82. package/dist/utils/progressive-css-injector.d.ts.map +1 -0
  83. package/dist/utils/progressive-css-injector.esm.js +217 -0
  84. package/dist/utils/progressive-css-injector.js +217 -0
  85. package/package.json +1 -1
  86. package/src/components/ui/button.tsx +9 -6
  87. package/src/components/ui/layout/container.tsx +312 -0
  88. package/src/components/ui/layout/index.ts +10 -0
  89. package/src/components/ui/layout/responsive-grid.tsx +286 -0
  90. package/src/components/ui/layouts/adaptive-layout.tsx +3 -1
  91. package/src/components/ui/navigation/index.ts +2 -0
  92. package/src/components/ui/navigation/progressive-navigation.tsx +453 -0
  93. package/src/components/ui/navigation/types.ts +41 -0
  94. package/src/hooks/use-adaptive-layout.ts +13 -9
  95. package/src/hooks/use-device.tsx +17 -10
  96. package/src/index.ts +19 -4
  97. package/src/plugins/css-purge-optimizer.ts +491 -0
  98. package/src/plugins/performance-monitor.ts +292 -0
  99. package/src/plugins/progressive-css-loader.ts +269 -0
  100. package/src/plugins/theme-css-generator.ts +22 -6
  101. package/src/styles/components/base/badge.css +2 -2
  102. package/src/styles/components/base/button.css +238 -35
  103. package/src/styles/components/base/card.css +2 -2
  104. package/src/styles/components/base/checkbox.css +3 -3
  105. package/src/styles/components/base/label.css +3 -3
  106. package/src/styles/components/feedback/skeleton.css +1 -1
  107. package/src/styles/components/feedback/toast.css +1 -1
  108. package/src/styles/components/index.css +3 -0
  109. package/src/styles/components/layout/container.css +466 -0
  110. package/src/styles/components/layout/index.css +5 -0
  111. package/src/styles/components/layout/responsive-grid.css +422 -0
  112. package/src/styles/components/navigation/breadcrumb.css +1 -1
  113. package/src/styles/components/navigation/index.css +1 -0
  114. package/src/styles/components/navigation/menu.css +2 -2
  115. package/src/styles/components/navigation/pagination.css +4 -4
  116. package/src/styles/components/navigation/progressive-navigation.css +633 -0
  117. package/src/styles/components/navigation/sidebar.css +4 -4
  118. package/src/styles/components/navigation/stepper.css +2 -2
  119. package/src/styles/components/navigation/tabs.css +1 -1
  120. package/src/styles/components/ui/theme-toggle.css +2 -2
  121. package/src/styles/progressive.css +17 -0
  122. package/src/styles/themes/harvey.css +103 -19
  123. package/src/styles/utilities/semantic-input-system.css +7 -13
  124. package/src/theme.ts +5 -1
  125. package/src/themes/phase1-constants.ts +189 -0
  126. package/src/themes/themes/default.ts +5 -1
  127. package/src/themes/themes/harvey.ts +5 -1
  128. package/src/themes/types.ts +77 -1
  129. package/src/themes/validation.ts +249 -0
  130. package/src/types.ts +77 -1
  131. package/src/utils/progressive-css-injector.ts +254 -0
@@ -0,0 +1,453 @@
1
+ /**
2
+ * Progressive Navigation Component
3
+ * Implements Phase 2 progressive navigation patterns as defined in the implementation plan
4
+ *
5
+ * Navigation Patterns:
6
+ * - mobile (xs-sm): hamburger menu pattern with 56px height
7
+ * - tablet (md): horizontal-compact pattern with 64px height
8
+ * - desktop (lg+): horizontal-full pattern with 72px height
9
+ */
10
+
11
+ 'use client'
12
+
13
+ import * as React from 'react';
14
+ import { useState, useCallback, useRef, useEffect } from 'react';
15
+ import { NavigationItem, NavigationGroup } from './types.js';
16
+
17
+ // Simple icon components for navigation
18
+ const HamburgerIcon: React.FC<{ className?: string }> = ({ className = '' }) => (
19
+ <svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
20
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
21
+ </svg>
22
+ );
23
+
24
+ const XMarkIcon: React.FC<{ className?: string }> = ({ className = '' }) => (
25
+ <svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
26
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
27
+ </svg>
28
+ );
29
+
30
+ const ChevronDownIcon: React.FC<{ className?: string }> = ({ className = '' }) => (
31
+ <svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
32
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
33
+ </svg>
34
+ );
35
+
36
+ export interface ProgressiveNavigationProps {
37
+ // Navigation content
38
+ items?: NavigationItem[];
39
+ groups?: NavigationGroup[];
40
+
41
+ // Logo configuration
42
+ logo?: React.ReactNode;
43
+ logoHref?: string;
44
+
45
+ // Mobile hamburger configuration
46
+ hamburgerHeight?: string; // Default: 56px
47
+ mobileLogoSize?: 'sm' | 'md' | 'lg'; // Default: sm
48
+ mobileTouchTarget?: string; // Default: 48px
49
+
50
+ // Tablet horizontal-compact configuration
51
+ tabletHeight?: string; // Default: 64px
52
+ tabletLogoSize?: 'sm' | 'md' | 'lg'; // Default: md
53
+
54
+ // Desktop horizontal-full configuration
55
+ desktopHeight?: string; // Default: 72px
56
+ desktopLogoSize?: 'sm' | 'md' | 'lg'; // Default: lg
57
+ showSecondaryActions?: boolean; // Default: true
58
+ secondaryActions?: React.ReactNode[];
59
+
60
+ // Responsive behavior
61
+ mobileBreakpoint?: string; // Default: 640px (sm) - Controls mobile/tablet cutoff
62
+ tabletBreakpoint?: string; // Default: 768px (md) - Reserved for future tablet sub-patterns
63
+ desktopBreakpoint?: string; // Default: 1024px (lg) - Controls tablet/desktop cutoff
64
+
65
+ // Event handlers
66
+ onItemClick?: (item: NavigationItem) => void;
67
+ onLogoClick?: () => void;
68
+
69
+ // Accessibility
70
+ 'aria-label'?: string;
71
+ 'data-testid'?: string;
72
+
73
+ // Styling
74
+ className?: string;
75
+ }
76
+
77
+ export const ProgressiveNavigation: React.FC<ProgressiveNavigationProps> = ({
78
+ items = [],
79
+ groups = [],
80
+ logo,
81
+ logoHref,
82
+ hamburgerHeight = '56px',
83
+ mobileLogoSize = 'sm',
84
+ mobileTouchTarget = '48px',
85
+ tabletHeight = '64px',
86
+ tabletLogoSize = 'md',
87
+ desktopHeight = '72px',
88
+ desktopLogoSize = 'lg',
89
+ showSecondaryActions = true,
90
+ secondaryActions = [],
91
+ mobileBreakpoint = '640px',
92
+ tabletBreakpoint = '768px', // Currently unused - reserved for future tablet sub-patterns
93
+ desktopBreakpoint = '1024px',
94
+ onItemClick,
95
+ onLogoClick,
96
+ 'aria-label': ariaLabel = 'Main navigation',
97
+ 'data-testid': testId = 'progressive-navigation',
98
+ className = '',
99
+ }) => {
100
+ // Suppress unused variable warning for tabletBreakpoint (reserved for future use)
101
+ void tabletBreakpoint;
102
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
103
+ const [activeDropdown, setActiveDropdown] = useState<string | null>(null);
104
+ const [screenSize, setScreenSize] = useState<'mobile' | 'tablet' | 'desktop'>('desktop');
105
+ const navRef = useRef<HTMLElement>(null);
106
+
107
+ // Determine current screen size based on configurable breakpoints
108
+ // Default: mobile < 640px, tablet 640-1023px, desktop >= 1024px
109
+ // This ensures sm range (640-767px) uses tablet-compact pattern, not hamburger
110
+ useEffect(() => {
111
+ const handleResize = () => {
112
+ const width = window.innerWidth;
113
+ if (width < parseInt(mobileBreakpoint)) {
114
+ setScreenSize('mobile'); // < 640px: hamburger menu
115
+ } else if (width < parseInt(desktopBreakpoint)) {
116
+ setScreenSize('tablet'); // 640-1023px: horizontal-compact
117
+ } else {
118
+ setScreenSize('desktop'); // >= 1024px: horizontal-full
119
+ }
120
+ };
121
+
122
+ handleResize();
123
+ window.addEventListener('resize', handleResize);
124
+ return () => window.removeEventListener('resize', handleResize);
125
+ }, [mobileBreakpoint, desktopBreakpoint]);
126
+
127
+ // Close mobile menu on escape key
128
+ useEffect(() => {
129
+ const handleEscape = (event: KeyboardEvent) => {
130
+ if (event.key === 'Escape' && isMobileMenuOpen) {
131
+ setIsMobileMenuOpen(false);
132
+ }
133
+ };
134
+
135
+ if (isMobileMenuOpen) {
136
+ document.addEventListener('keydown', handleEscape);
137
+ }
138
+
139
+ return () => {
140
+ document.removeEventListener('keydown', handleEscape);
141
+ };
142
+ }, [isMobileMenuOpen]);
143
+
144
+ const handleItemClick = useCallback((item: NavigationItem) => {
145
+ if (item.disabled) return;
146
+
147
+ if (onItemClick) {
148
+ onItemClick(item);
149
+ }
150
+
151
+ if (item.onClick) {
152
+ item.onClick();
153
+ }
154
+
155
+ // Close mobile menu after item click
156
+ if (screenSize === 'mobile') {
157
+ setIsMobileMenuOpen(false);
158
+ }
159
+
160
+ // Close dropdown if open
161
+ setActiveDropdown(null);
162
+ }, [onItemClick, screenSize]);
163
+
164
+ const handleDropdownToggle = useCallback((groupId: string) => {
165
+ setActiveDropdown(activeDropdown === groupId ? null : groupId);
166
+ }, [activeDropdown]);
167
+
168
+ const handleLogoClick = useCallback(() => {
169
+ if (onLogoClick) {
170
+ onLogoClick();
171
+ }
172
+ }, [onLogoClick]);
173
+
174
+ const getNavigationHeight = () => {
175
+ switch (screenSize) {
176
+ case 'mobile':
177
+ return hamburgerHeight;
178
+ case 'tablet':
179
+ return tabletHeight;
180
+ case 'desktop':
181
+ return desktopHeight;
182
+ default:
183
+ return desktopHeight;
184
+ }
185
+ };
186
+
187
+ const getLogoSize = () => {
188
+ switch (screenSize) {
189
+ case 'mobile':
190
+ return mobileLogoSize;
191
+ case 'tablet':
192
+ return tabletLogoSize;
193
+ case 'desktop':
194
+ return desktopLogoSize;
195
+ default:
196
+ return desktopLogoSize;
197
+ }
198
+ };
199
+
200
+ const renderLogo = () => {
201
+ const logoContent = (
202
+ <div className={`progressive-nav__logo progressive-nav__logo--${getLogoSize()}`}>
203
+ {logo}
204
+ </div>
205
+ );
206
+
207
+ if (logoHref) {
208
+ return (
209
+ <a
210
+ href={logoHref}
211
+ className="progressive-nav__logo-link"
212
+ onClick={handleLogoClick}
213
+ >
214
+ {logoContent}
215
+ </a>
216
+ );
217
+ }
218
+
219
+ return logoContent;
220
+ };
221
+
222
+ const renderNavigationItems = () => {
223
+ const allItems = groups.length > 0
224
+ ? groups.flatMap(group => group.items)
225
+ : items;
226
+
227
+ return allItems.map((item) => (
228
+ <button
229
+ key={item.id}
230
+ onClick={() => handleItemClick(item)}
231
+ disabled={item.disabled}
232
+ className={`progressive-nav__item ${
233
+ item.active ? 'progressive-nav__item--active' : ''
234
+ } ${item.disabled ? 'progressive-nav__item--disabled' : ''}`}
235
+ >
236
+ {item.icon && (
237
+ <span className="progressive-nav__item-icon">
238
+ {item.icon}
239
+ </span>
240
+ )}
241
+ <span className="progressive-nav__item-label">{item.label}</span>
242
+ {item.badge && (
243
+ <span className="progressive-nav__item-badge">{item.badge}</span>
244
+ )}
245
+ </button>
246
+ ));
247
+ };
248
+
249
+ const renderDropdownItems = (groupItems: NavigationItem[]) => {
250
+ return groupItems.map((item) => (
251
+ <button
252
+ key={item.id}
253
+ onClick={() => handleItemClick(item)}
254
+ disabled={item.disabled}
255
+ className={`progressive-nav__dropdown-item ${
256
+ item.active ? 'progressive-nav__dropdown-item--active' : ''
257
+ } ${item.disabled ? 'progressive-nav__dropdown-item--disabled' : ''}`}
258
+ >
259
+ {item.icon && (
260
+ <span className="progressive-nav__dropdown-item-icon">
261
+ {item.icon}
262
+ </span>
263
+ )}
264
+ <span className="progressive-nav__dropdown-item-label">{item.label}</span>
265
+ {item.badge && (
266
+ <span className="progressive-nav__dropdown-item-badge">{item.badge}</span>
267
+ )}
268
+ </button>
269
+ ));
270
+ };
271
+
272
+ const renderNavigationGroups = () => {
273
+ return groups.map((group) => (
274
+ <div key={group.id} className="progressive-nav__group">
275
+ <button
276
+ onClick={() => handleDropdownToggle(group.id)}
277
+ className={`progressive-nav__group-trigger ${
278
+ activeDropdown === group.id ? 'progressive-nav__group-trigger--active' : ''
279
+ }`}
280
+ >
281
+ <span className="progressive-nav__group-title">{group.title}</span>
282
+ <ChevronDownIcon
283
+ className={`progressive-nav__group-arrow ${
284
+ activeDropdown === group.id ? 'progressive-nav__group-arrow--expanded' : ''
285
+ }`}
286
+ />
287
+ </button>
288
+
289
+ {activeDropdown === group.id && (
290
+ <div className="progressive-nav__dropdown">
291
+ {renderDropdownItems(group.items)}
292
+ </div>
293
+ )}
294
+ </div>
295
+ ));
296
+ };
297
+
298
+ const renderSecondaryActions = () => {
299
+ if (!showSecondaryActions || !secondaryActions.length) return null;
300
+
301
+ return (
302
+ <div className="progressive-nav__secondary-actions">
303
+ {secondaryActions.map((action, index) => (
304
+ <div key={index} className="progressive-nav__secondary-action">
305
+ {action}
306
+ </div>
307
+ ))}
308
+ </div>
309
+ );
310
+ };
311
+
312
+ // Mobile hamburger menu pattern
313
+ if (screenSize === 'mobile') {
314
+ return (
315
+ <nav
316
+ ref={navRef}
317
+ className={`progressive-nav progressive-nav--mobile ${className}`}
318
+ style={{ height: getNavigationHeight() }}
319
+ aria-label={ariaLabel}
320
+ data-testid={testId}
321
+ >
322
+ <div className="progressive-nav__mobile-container">
323
+ {/* Mobile header */}
324
+ <div className="progressive-nav__mobile-header">
325
+ {renderLogo()}
326
+
327
+ <button
328
+ onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
329
+ className="progressive-nav__mobile-toggle"
330
+ style={{
331
+ minHeight: mobileTouchTarget,
332
+ minWidth: mobileTouchTarget
333
+ }}
334
+ aria-label={isMobileMenuOpen ? 'Close menu' : 'Open menu'}
335
+ aria-expanded={isMobileMenuOpen}
336
+ >
337
+ {isMobileMenuOpen ? (
338
+ <XMarkIcon className="progressive-nav__mobile-toggle-icon" />
339
+ ) : (
340
+ <HamburgerIcon className="progressive-nav__mobile-toggle-icon" />
341
+ )}
342
+ </button>
343
+ </div>
344
+
345
+ {/* Mobile menu overlay */}
346
+ {isMobileMenuOpen && (
347
+ <>
348
+ <div
349
+ className="progressive-nav__mobile-overlay"
350
+ onClick={() => setIsMobileMenuOpen(false)}
351
+ />
352
+ <div className="progressive-nav__mobile-menu">
353
+ <div className="progressive-nav__mobile-content">
354
+ {groups.length > 0 ? (
355
+ <div className="progressive-nav__mobile-groups">
356
+ {groups.map((group) => (
357
+ <div key={group.id} className="progressive-nav__mobile-group">
358
+ {group.title && (
359
+ <div className="progressive-nav__mobile-group-title">
360
+ {group.title}
361
+ </div>
362
+ )}
363
+ <div className="progressive-nav__mobile-group-items">
364
+ {group.items.map((item) => (
365
+ <button
366
+ key={item.id}
367
+ onClick={() => handleItemClick(item)}
368
+ disabled={item.disabled}
369
+ className={`progressive-nav__mobile-item ${
370
+ item.active ? 'progressive-nav__mobile-item--active' : ''
371
+ } ${item.disabled ? 'progressive-nav__mobile-item--disabled' : ''}`}
372
+ >
373
+ {item.icon && (
374
+ <span className="progressive-nav__mobile-item-icon">
375
+ {item.icon}
376
+ </span>
377
+ )}
378
+ <span className="progressive-nav__mobile-item-label">{item.label}</span>
379
+ {item.badge && (
380
+ <span className="progressive-nav__mobile-item-badge">{item.badge}</span>
381
+ )}
382
+ </button>
383
+ ))}
384
+ </div>
385
+ </div>
386
+ ))}
387
+ </div>
388
+ ) : (
389
+ <div className="progressive-nav__mobile-items">
390
+ {renderNavigationItems()}
391
+ </div>
392
+ )}
393
+ </div>
394
+ </div>
395
+ </>
396
+ )}
397
+ </div>
398
+ </nav>
399
+ );
400
+ }
401
+
402
+ // Tablet horizontal-compact pattern
403
+ if (screenSize === 'tablet') {
404
+ return (
405
+ <nav
406
+ ref={navRef}
407
+ className={`progressive-nav progressive-nav--tablet ${className}`}
408
+ style={{ height: getNavigationHeight() }}
409
+ aria-label={ariaLabel}
410
+ data-testid={testId}
411
+ >
412
+ <div className="progressive-nav__tablet-container">
413
+ {renderLogo()}
414
+
415
+ <div className="progressive-nav__tablet-content">
416
+ {groups.length > 0 ? renderNavigationGroups() : (
417
+ <div className="progressive-nav__tablet-items">
418
+ {renderNavigationItems()}
419
+ </div>
420
+ )}
421
+ </div>
422
+ </div>
423
+ </nav>
424
+ );
425
+ }
426
+
427
+ // Desktop horizontal-full pattern
428
+ return (
429
+ <nav
430
+ ref={navRef}
431
+ className={`progressive-nav progressive-nav--desktop ${className}`}
432
+ style={{ height: getNavigationHeight() }}
433
+ aria-label={ariaLabel}
434
+ data-testid={testId}
435
+ >
436
+ <div className="progressive-nav__desktop-container">
437
+ {renderLogo()}
438
+
439
+ <div className="progressive-nav__desktop-content">
440
+ {groups.length > 0 ? renderNavigationGroups() : (
441
+ <div className="progressive-nav__desktop-items">
442
+ {renderNavigationItems()}
443
+ </div>
444
+ )}
445
+ </div>
446
+
447
+ {renderSecondaryActions()}
448
+ </div>
449
+ </nav>
450
+ );
451
+ };
452
+
453
+ export default ProgressiveNavigation;
@@ -215,6 +215,47 @@ export interface MenuProps extends NavigationBaseProps {
215
215
  onSelectionChange?: (selectedItems: string[]) => void;
216
216
  }
217
217
 
218
+ // ============================================================================
219
+ // PROGRESSIVE NAVIGATION COMPONENT TYPES (Phase 2 Enhancement)
220
+ // ============================================================================
221
+
222
+ export interface ProgressiveNavigationProps extends NavigationBaseProps {
223
+ // Navigation content
224
+ items?: NavigationItem[];
225
+ groups?: NavigationGroup[];
226
+
227
+ // Logo configuration
228
+ logo?: React.ReactNode;
229
+ logoHref?: string;
230
+
231
+ // Mobile hamburger configuration
232
+ hamburgerHeight?: string; // Default: 56px
233
+ mobileLogoSize?: 'sm' | 'md' | 'lg'; // Default: sm
234
+ mobileTouchTarget?: string; // Default: 48px
235
+
236
+ // Tablet horizontal-compact configuration
237
+ tabletHeight?: string; // Default: 64px
238
+ tabletLogoSize?: 'sm' | 'md' | 'lg'; // Default: md
239
+
240
+ // Desktop horizontal-full configuration
241
+ desktopHeight?: string; // Default: 72px
242
+ desktopLogoSize?: 'sm' | 'md' | 'lg'; // Default: lg
243
+ showSecondaryActions?: boolean; // Default: true
244
+ secondaryActions?: React.ReactNode[];
245
+
246
+ // Responsive behavior
247
+ mobileBreakpoint?: string; // Default: 640px (sm)
248
+ tabletBreakpoint?: string; // Default: 768px (md)
249
+ desktopBreakpoint?: string; // Default: 1024px (lg)
250
+
251
+ // Event handlers
252
+ onItemClick?: (item: NavigationItem) => void;
253
+ onLogoClick?: () => void;
254
+
255
+ // Accessibility
256
+ 'aria-label'?: string;
257
+ }
258
+
218
259
  // ============================================================================
219
260
  // SIDEBAR COMPONENT TYPES
220
261
  // ============================================================================
@@ -2,7 +2,7 @@ import { useState, useEffect, useCallback, useMemo } from 'react'
2
2
 
3
3
  export type DeviceType = 'mobile' | 'tablet' | 'desktop'
4
4
  export type Orientation = 'portrait' | 'landscape'
5
- export type ScreenSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'
5
+ export type ScreenSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl'
6
6
 
7
7
  export interface AdaptiveLayoutState {
8
8
  deviceType: DeviceType
@@ -28,6 +28,7 @@ export interface AdaptiveLayoutConfig {
28
28
  lg: number
29
29
  xl: number
30
30
  '2xl': number
31
+ '3xl': number
31
32
  }
32
33
  }
33
34
 
@@ -49,12 +50,13 @@ export const useAdaptiveLayout = (
49
50
  enableBatteryOptimization = true,
50
51
  enableMemoryOptimization = true,
51
52
  breakpoints = {
52
- xs: 0,
53
- sm: 640,
54
- md: 768,
55
- lg: 1024,
56
- xl: 1280,
57
- '2xl': 1536
53
+ xs: 475, // Phase 1: Large phones (iPhone 14 Plus, etc.)
54
+ sm: 640, // Small tablets, large phones landscape
55
+ md: 768, // Tablets (iPad Mini, etc.)
56
+ lg: 1024, // Desktop, large tablets
57
+ xl: 1280, // Large desktop (MacBook Pro 13")
58
+ '2xl': 1536, // Ultra-wide (MacBook Pro 16", external monitors)
59
+ '3xl': 1920 // Large external monitors, TV displays
58
60
  }
59
61
  } = config
60
62
 
@@ -79,12 +81,14 @@ export const useAdaptiveLayout = (
79
81
 
80
82
  // Screen size detection
81
83
  const detectScreenSize = useCallback((width: number): ScreenSize => {
82
- if (width < breakpoints.sm) return 'xs'
84
+ if (width < breakpoints.xs) return 'xs' // Small phones (< 475px)
85
+ if (width < breakpoints.sm) return 'xs' // Still xs for 475-640px range
83
86
  if (width < breakpoints.md) return 'sm'
84
87
  if (width < breakpoints.lg) return 'md'
85
88
  if (width < breakpoints.xl) return 'lg'
86
89
  if (width < breakpoints['2xl']) return 'xl'
87
- return '2xl'
90
+ if (width < breakpoints['3xl']) return '2xl'
91
+ return '3xl'
88
92
  }, [breakpoints])
89
93
 
90
94
  // Touch device detection
@@ -6,16 +6,18 @@ export interface DeviceInfo {
6
6
  isMobile: boolean
7
7
  isTablet: boolean
8
8
  isDesktop: boolean
9
- screenSize: 'mobile' | 'tablet' | 'desktop'
9
+ isLargeDisplay: boolean
10
+ screenSize: 'mobile' | 'tablet' | 'desktop' | 'largeDisplay'
10
11
  orientation: 'portrait' | 'landscape'
11
12
  touchDevice: boolean
12
13
  }
13
14
 
14
- // Breakpoints based on common device sizes
15
+ // Updated breakpoints to align with Phase 1 Enhanced Breakpoint System
16
+ // xs: 475px, sm: 640px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px, 3xl: 1920px
15
17
  const BREAKPOINTS = {
16
- mobile: 768,
17
- tablet: 1024,
18
- desktop: 1440
18
+ mobile: 768, // xs-sm range (475-768px)
19
+ tablet: 1024, // md range (768-1024px)
20
+ desktop: 1536 // lg-xl range (1024-1536px), largeDisplay starts at 1536px+ (2xl-3xl)
19
21
  } as const
20
22
 
21
23
  /**
@@ -27,6 +29,7 @@ export const useDevice = (): DeviceInfo => {
27
29
  isMobile: false,
28
30
  isTablet: false,
29
31
  isDesktop: false,
32
+ isLargeDisplay: false,
30
33
  screenSize: 'desktop',
31
34
  orientation: 'landscape',
32
35
  touchDevice: false
@@ -37,16 +40,18 @@ export const useDevice = (): DeviceInfo => {
37
40
  const width = window.innerWidth
38
41
  const height = window.innerHeight
39
42
 
40
- // Determine device type based on width
43
+ // Determine device type based on width (aligned with new breakpoint system)
41
44
  const isMobile = width < BREAKPOINTS.mobile
42
45
  const isTablet = width >= BREAKPOINTS.mobile && width < BREAKPOINTS.tablet
43
- const isDesktop = width >= BREAKPOINTS.tablet
44
-
46
+ const isDesktop = width >= BREAKPOINTS.tablet && width < BREAKPOINTS.desktop
47
+ const isLargeDisplay = width >= BREAKPOINTS.desktop
48
+
45
49
  // Determine screen size category
46
50
  let screenSize: DeviceInfo['screenSize']
47
51
  if (isMobile) screenSize = 'mobile'
48
52
  else if (isTablet) screenSize = 'tablet'
49
- else screenSize = 'desktop'
53
+ else if (isDesktop) screenSize = 'desktop'
54
+ else screenSize = 'largeDisplay'
50
55
 
51
56
  // Determine orientation
52
57
  const orientation: DeviceInfo['orientation'] = width > height ? 'landscape' : 'portrait'
@@ -61,6 +66,7 @@ export const useDevice = (): DeviceInfo => {
61
66
  isMobile,
62
67
  isTablet,
63
68
  isDesktop,
69
+ isLargeDisplay,
64
70
  screenSize,
65
71
  orientation,
66
72
  touchDevice
@@ -92,8 +98,9 @@ export const useDevice = (): DeviceInfo => {
92
98
 
93
99
  // Convenience hooks for specific use cases
94
100
  export const useIsMobile = () => useDevice().isMobile
95
- export const useIsTablet = () => useDevice().isTablet
101
+ export const useIsTablet = () => useDevice().isTablet
96
102
  export const useIsDesktop = () => useDevice().isDesktop
103
+ export const useIsLargeDisplay = () => useDevice().isLargeDisplay
97
104
  export const useOrientation = () => useDevice().orientation
98
105
  export const useIsTouchDevice = () => useDevice().touchDevice
99
106
 
package/src/index.ts CHANGED
@@ -3,11 +3,11 @@
3
3
  * Production-ready design system package with harvey theme
4
4
  *
5
5
  * Auto-generated exports for:
6
- * - 89 UI components
7
- * - 67 custom hooks
6
+ * - 90 UI components
7
+ * - 68 custom hooks
8
8
  * - 6 utility functions
9
- * - 29 theme system components
10
- * - 155 TypeScript types
9
+ * - 32 theme system components
10
+ * - 165 TypeScript types
11
11
  * - 4 design tokens
12
12
  * - 0 build plugins
13
13
  * - Complete CSS system (61+ files)
@@ -57,6 +57,7 @@ export { TouchFriendlySlider } from './components/ui/touch-friendly-interface.js
57
57
  export { Breadcrumb } from './components/ui/navigation/breadcrumb.js';
58
58
  export { Menu } from './components/ui/navigation/menu.js';
59
59
  export { Pagination } from './components/ui/navigation/pagination.js';
60
+ export { ProgressiveNavigation } from './components/ui/navigation/progressive-navigation.js';
60
61
  export { Sidebar } from './components/ui/navigation/sidebar.js';
61
62
  export { Stepper } from './components/ui/navigation/stepper.js';
62
63
  export { SubscriptionBadge } from './components/ui/navigation/subscription-badge.js';
@@ -127,6 +128,7 @@ export { useDevice } from './hooks/use-device.js';
127
128
  export { useIsMobile } from './hooks/use-device.js';
128
129
  export { useIsTablet } from './hooks/use-device.js';
129
130
  export { useIsDesktop } from './hooks/use-device.js';
131
+ export { useIsLargeDisplay } from './hooks/use-device.js';
130
132
  export { useOrientation } from './hooks/use-device.js';
131
133
  export { useIsTouchDevice } from './hooks/use-device.js';
132
134
  export { useEnterpriseMobileExperience } from './hooks/use-enterprise-mobile-experience.js';
@@ -208,6 +210,9 @@ export { KeyboardFocusManager } from './themes/keyboard-navigation.js';
208
210
  export { MotionReductionManager } from './themes/motion-reduction.js';
209
211
  export { MotionReductionUtils } from './themes/motion-reduction.js';
210
212
  export { MotionReductionHooks } from './themes/motion-reduction.js';
213
+ export { PHASE1_BREAKPOINTS } from './themes/phase1-constants.js';
214
+ export { PHASE1_CONTENT_DENSITY } from './themes/phase1-constants.js';
215
+ export { PHASE1_RESPONSIVE_TYPOGRAPHY } from './themes/phase1-constants.js';
211
216
  export { ScreenReaderOptimizer } from './themes/screen-reader.js';
212
217
  export { ScreenReaderNavigation } from './themes/screen-reader.js';
213
218
  export { SystemThemeDetector } from './themes/systemThemeDetector.js';
@@ -238,6 +243,7 @@ export type { StepperProps } from './components/ui/navigation/types.js';
238
243
  export type { StepItem } from './components/ui/navigation/types.js';
239
244
  export type { StepAction } from './components/ui/navigation/types.js';
240
245
  export type { MenuProps } from './components/ui/navigation/types.js';
246
+ export type { ProgressiveNavigationProps } from './components/ui/navigation/types.js';
241
247
  export type { SidebarProps } from './components/ui/navigation/types.js';
242
248
  export type { NavigationState } from './components/ui/navigation/types.js';
243
249
  export type { NavigationContextValue } from './components/ui/navigation/types.js';
@@ -370,6 +376,15 @@ export type { ThemeValidationError } from './themes/types.js';
370
376
  export type { ThemeValidationWarning } from './themes/types.js';
371
377
  export type { ThemeInheritance } from './themes/types.js';
372
378
  export type { CompleteThemeConfig } from './themes/types.js';
379
+ export type { BreakpointThemeConfig } from './themes/types.js';
380
+ export type { ContentDensityThemeConfig } from './themes/types.js';
381
+ export type { DensityLevel } from './themes/types.js';
382
+ export type { DensitySpacing } from './themes/types.js';
383
+ export type { DensityTypography } from './themes/types.js';
384
+ export type { DensityTouchTargets } from './themes/types.js';
385
+ export type { DensityInteractions } from './themes/types.js';
386
+ export type { ResponsiveTypographyThemeConfig } from './themes/types.js';
387
+ export type { ResponsiveTypographyScale } from './themes/types.js';
373
388
  export type { DesignToken } from './tokens/types.js';
374
389
  export type { TokenType } from './tokens/types.js';
375
390
  export type { ColorToken } from './tokens/types.js';