lucent-ui 0.23.0 → 0.24.0

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.
@@ -0,0 +1,247 @@
1
+ export const COMPONENT_MANIFEST = {
2
+ id: 'nav-menu',
3
+ name: 'NavMenu',
4
+ tier: 'molecule',
5
+ domain: 'neutral',
6
+ specVersion: '0.1',
7
+ description: 'Multi-level navigation menu supporting vertical (sidebar) and horizontal (top bar) orientations with a sliding highlight pill, CSS-driven hover states, collapsible groups, and nested sub-menus.',
8
+ designIntent: 'NavMenu provides hierarchical navigation for sidebar and top-bar layouts. ' +
9
+ 'A single sliding highlight pill follows the active item, driven entirely from the root via DOM measurement — ' +
10
+ 'the root queries for data-active / data-active-parent attributes and positions an absolutely-placed pill ' +
11
+ 'using requestAnimationFrame. MutationObserver and ResizeObserver auto-trigger re-measurement; ' +
12
+ 'aria-hidden ancestry is used to detect collapsed items (not offsetHeight), eliminating all timeout-based coordination. ' +
13
+ 'Hover states use a CSS rule on [data-lucent-navitem] with :not() exclusions for active, parent-active, hint, and disabled states, ' +
14
+ 'rendering a 5% translucent text-primary tint that never conflicts with the accent pill. ' +
15
+ 'In vertical orientation, parent items expand inline with smooth height animation (same pattern as Collapsible) ' +
16
+ 'and children are indented by depth level. When a parent with an active child is collapsed, the pill slides ' +
17
+ 'to the parent button with a lighter visual style (12% accent tint or surface-secondary in inverse mode) ' +
18
+ 'so text remains readable without on-accent color. When re-expanded, the pill slides back to the child. ' +
19
+ 'Parent items support "self-active" mode: setting isActive on a parent with no active children ' +
20
+ 'highlights the parent with the full accent pill, useful for section-level pages that represent all children. ' +
21
+ 'Inverse mode uses surface background with accent right-border (inset -3px) and elevation shadow. ' +
22
+ 'The hasIcons prop controls left-padding alignment globally: when true, items use tighter padding (space-2) ' +
23
+ 'and group headers align with icon start; sub-menu children inherit parentHasIcon via context so their ' +
24
+ 'text aligns with the parent label text regardless of whether they have icons themselves. ' +
25
+ 'In horizontal orientation, parent items show dropdown sub-menus on hover/click with enter/exit animation ' +
26
+ 'and viewport collision detection. Groups are flattened in horizontal mode. ' +
27
+ 'Three sizes (sm/md/lg) scale font, padding, gap, and icon width via a token map. ' +
28
+ 'The compound API (NavMenu.Item, NavMenu.Group, NavMenu.Sub, NavMenu.Separator) keeps the tree declarative.',
29
+ props: [
30
+ {
31
+ name: 'orientation',
32
+ type: 'enum',
33
+ required: false,
34
+ default: '"vertical"',
35
+ description: 'Layout direction. Vertical for sidebars, horizontal for top navigation bars.',
36
+ enumValues: ['vertical', 'horizontal'],
37
+ },
38
+ {
39
+ name: 'inverse',
40
+ type: 'boolean',
41
+ required: false,
42
+ default: 'false',
43
+ description: 'Uses surface background with accent right-border and elevation shadow instead of accent fill for the active highlight pill.',
44
+ },
45
+ {
46
+ name: 'size',
47
+ type: 'enum',
48
+ required: false,
49
+ default: '"md"',
50
+ description: 'Size variant controlling font size, padding, gap, and icon width.',
51
+ enumValues: ['sm', 'md', 'lg'],
52
+ },
53
+ {
54
+ name: 'hasIcons',
55
+ type: 'boolean',
56
+ required: false,
57
+ default: 'false',
58
+ description: 'Whether items use icons. Tightens left padding on items and group headers so text aligns with icon positions. ' +
59
+ 'Sub-menu children automatically inherit parent icon awareness via context for consistent text alignment.',
60
+ },
61
+ {
62
+ name: 'aria-label',
63
+ type: 'string',
64
+ required: false,
65
+ default: '"Navigation"',
66
+ description: 'Accessible label for the root <nav> element.',
67
+ },
68
+ {
69
+ name: 'style',
70
+ type: 'object',
71
+ required: false,
72
+ description: 'Inline style overrides for the root <nav> element.',
73
+ },
74
+ ],
75
+ usageExamples: [
76
+ {
77
+ title: 'Vertical sidebar with icons',
78
+ code: `<NavMenu orientation="vertical" hasIcons>
79
+ <NavMenu.Item icon={<DashIcon />} href="/dashboard" isActive>Dashboard</NavMenu.Item>
80
+ <NavMenu.Group label="Workspace">
81
+ <NavMenu.Item icon={<FolderIcon />} href="/projects">Projects</NavMenu.Item>
82
+ <NavMenu.Item icon={<GearIcon />}>
83
+ Settings
84
+ <NavMenu.Sub>
85
+ <NavMenu.Item href="/settings/general" isActive>General</NavMenu.Item>
86
+ <NavMenu.Item href="/settings/team">Team</NavMenu.Item>
87
+ </NavMenu.Sub>
88
+ </NavMenu.Item>
89
+ </NavMenu.Group>
90
+ <NavMenu.Separator />
91
+ <NavMenu.Item icon={<HelpIcon />} href="/help">Help</NavMenu.Item>
92
+ </NavMenu>`,
93
+ description: 'Sidebar with icons, groups, and nested sub-menu. hasIcons tightens padding so group headers align with icons ' +
94
+ 'and sub-menu children align with parent text.',
95
+ },
96
+ {
97
+ title: 'Vertical sidebar without icons',
98
+ code: `<NavMenu orientation="vertical">
99
+ <NavMenu.Item href="/dashboard" isActive>Dashboard</NavMenu.Item>
100
+ <NavMenu.Group label="Workspace">
101
+ <NavMenu.Item href="/projects">Projects</NavMenu.Item>
102
+ <NavMenu.Item>
103
+ Settings
104
+ <NavMenu.Sub>
105
+ <NavMenu.Item href="/settings/general">General</NavMenu.Item>
106
+ <NavMenu.Item href="/settings/team">Team</NavMenu.Item>
107
+ </NavMenu.Sub>
108
+ </NavMenu.Item>
109
+ </NavMenu.Group>
110
+ </NavMenu>`,
111
+ description: 'Without hasIcons, items and group headers use standard padding (space-4) for comfortable text-only layout.',
112
+ },
113
+ {
114
+ title: 'Horizontal top navigation',
115
+ code: `<NavMenu orientation="horizontal">
116
+ <NavMenu.Item href="/dashboard" isActive>Dashboard</NavMenu.Item>
117
+ <NavMenu.Item href="/projects">Projects</NavMenu.Item>
118
+ <NavMenu.Item>
119
+ Settings
120
+ <NavMenu.Sub>
121
+ <NavMenu.Item href="/settings/general">General</NavMenu.Item>
122
+ <NavMenu.Item href="/settings/team">Team</NavMenu.Item>
123
+ </NavMenu.Sub>
124
+ </NavMenu.Item>
125
+ </NavMenu>`,
126
+ description: 'Top bar layout. Parent items show dropdown sub-menus on hover/click with viewport collision detection.',
127
+ },
128
+ {
129
+ title: 'Inverse mode with section groups',
130
+ code: `<NavMenu orientation="vertical" inverse>
131
+ <NavMenu.Group label="Main">
132
+ <NavMenu.Item href="/dashboard" isActive>Dashboard</NavMenu.Item>
133
+ <NavMenu.Item href="/analytics">Analytics</NavMenu.Item>
134
+ </NavMenu.Group>
135
+ <NavMenu.Separator />
136
+ <NavMenu.Group label="Admin" defaultOpen={false}>
137
+ <NavMenu.Item href="/users">Users</NavMenu.Item>
138
+ <NavMenu.Item href="/roles">Roles</NavMenu.Item>
139
+ </NavMenu.Group>
140
+ </NavMenu>`,
141
+ description: 'Inverse highlight: surface background with accent right-border and elevation shadow. Text stays text-primary.',
142
+ },
143
+ {
144
+ title: 'Self-active parent (section-level page)',
145
+ code: `<NavMenu orientation="vertical" hasIcons>
146
+ <NavMenu.Item isActive icon={<TextIcon />}>
147
+ Text & Labels
148
+ <NavMenu.Sub>
149
+ <NavMenu.Item href="/text">Text</NavMenu.Item>
150
+ <NavMenu.Item href="/badge">Badge</NavMenu.Item>
151
+ <NavMenu.Item href="/chip">Chip</NavMenu.Item>
152
+ </NavMenu.Sub>
153
+ </NavMenu.Item>
154
+ <NavMenu.Item icon={<InputIcon />}>
155
+ Input Fields
156
+ <NavMenu.Sub>
157
+ <NavMenu.Item href="/input" isActive>Input</NavMenu.Item>
158
+ <NavMenu.Item href="/select">Select</NavMenu.Item>
159
+ </NavMenu.Sub>
160
+ </NavMenu.Item>
161
+ </NavMenu>`,
162
+ description: 'Setting isActive on a parent with no active children gives it the full accent highlight. ' +
163
+ 'The sub-nav expands but no child is individually selected — the parent represents all items. ' +
164
+ 'Clicking a specific child moves the highlight to that child.',
165
+ },
166
+ {
167
+ title: 'Compact sidebar (sm size)',
168
+ code: `<NavMenu orientation="vertical" size="sm" hasIcons>
169
+ <NavMenu.Item href="/dash" icon={<DashIcon />} isActive>Dashboard</NavMenu.Item>
170
+ <NavMenu.Item href="/projects" icon={<FolderIcon />}>Projects</NavMenu.Item>
171
+ <NavMenu.Item icon={<GearIcon />}>
172
+ Settings
173
+ <NavMenu.Sub>
174
+ <NavMenu.Item href="/settings/general">General</NavMenu.Item>
175
+ <NavMenu.Item href="/settings/team">Team</NavMenu.Item>
176
+ </NavMenu.Sub>
177
+ </NavMenu.Item>
178
+ </NavMenu>`,
179
+ description: 'Small size variant for compact sidebar layouts with tighter padding and smaller font.',
180
+ },
181
+ {
182
+ title: 'Badges and disabled items',
183
+ code: `<NavMenu orientation="vertical" hasIcons>
184
+ <NavMenu.Item href="/inbox" icon={<InboxIcon />} badge={<Chip size="sm" variant="accent">3</Chip>}>Inbox</NavMenu.Item>
185
+ <NavMenu.Item href="/settings" icon={<GearIcon />} isActive>Settings</NavMenu.Item>
186
+ <NavMenu.Item href="/archive" icon={<ArchiveIcon />} disabled>Archived</NavMenu.Item>
187
+ </NavMenu>`,
188
+ description: 'Items with badge counts and disabled state. Disabled items use not-allowed cursor and muted text.',
189
+ },
190
+ {
191
+ title: 'Polymorphic items with React Router',
192
+ code: `<NavMenu orientation="vertical">
193
+ <NavMenu.Item as={Link} href="/dashboard" isActive>Dashboard</NavMenu.Item>
194
+ <NavMenu.Item as={Link} href="/projects">Projects</NavMenu.Item>
195
+ </NavMenu>`,
196
+ description: 'Using the "as" prop to render items as React Router Link components instead of anchor tags.',
197
+ },
198
+ ],
199
+ compositionGraph: [
200
+ {
201
+ componentId: 'nav-menu-item',
202
+ componentName: 'NavMenu.Item',
203
+ role: 'Individual navigation link or parent toggle. Sets data-active when self-active, data-active-parent when collapsed with an active child. Uses data-lucent-navitem for CSS hover targeting.',
204
+ required: true,
205
+ },
206
+ {
207
+ componentId: 'nav-menu-sub',
208
+ componentName: 'NavMenu.Sub',
209
+ role: 'Marker wrapper for nested sub-menu children inside a parent NavMenu.Item.',
210
+ required: false,
211
+ },
212
+ {
213
+ componentId: 'nav-menu-group',
214
+ componentName: 'NavMenu.Group',
215
+ role: 'Section grouping with optional uppercase label header and independent collapse. Header left padding responds to hasIcons context.',
216
+ required: false,
217
+ },
218
+ {
219
+ componentId: 'nav-menu-separator',
220
+ componentName: 'NavMenu.Separator',
221
+ role: 'Visual divider between sections. Horizontal line in vertical mode, vertical line in horizontal mode.',
222
+ required: false,
223
+ },
224
+ ],
225
+ accessibility: {
226
+ role: 'navigation',
227
+ ariaAttributes: [
228
+ 'aria-label on root <nav>',
229
+ 'aria-expanded on parent items with sub-menus',
230
+ 'aria-current="page" on active leaf items',
231
+ 'aria-disabled on disabled items',
232
+ 'aria-hidden on collapsed sub-menu content and the highlight pill',
233
+ 'role="separator" on dividers',
234
+ ],
235
+ keyboardInteractions: [
236
+ 'Enter / Space — toggle parent item expand/collapse',
237
+ 'ArrowRight (vertical) / ArrowDown (horizontal) — expand parent item',
238
+ 'ArrowLeft (vertical) / ArrowUp (horizontal) — collapse parent item',
239
+ 'Escape — close open sub-menu',
240
+ ],
241
+ notes: 'Parent items use aria-expanded to communicate open/closed state. ' +
242
+ 'Active leaf items use aria-current="page". Disabled items use aria-disabled with no click handler. ' +
243
+ 'Collapsed sections are marked aria-hidden="true", which the sliding highlight uses to detect ' +
244
+ 'visibility — items inside aria-hidden containers are skipped in favor of the parent fallback. ' +
245
+ 'Separators use role="separator". The highlight pill is aria-hidden.',
246
+ },
247
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lucent-ui",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "description": "An AI-first React component library with machine-readable manifests.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",