@claralight-design/abweb-navbar 0.2.0 → 0.2.2
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/NavHeader.module.css +38 -5
- package/NavHeader.tsx +114 -38
- package/package.json +1 -1
package/NavHeader.module.css
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
30
30
|
align-items: center;
|
|
31
31
|
overflow: hidden;
|
|
32
|
-
padding: 3px 6px 6px;
|
|
32
|
+
padding: 3px 6px 6px calc(6px + var(--nav-header-left-padding, 0px));
|
|
33
33
|
border-radius: 48px;
|
|
34
34
|
gap: 12px;
|
|
35
35
|
transform: translateY(0);
|
|
@@ -101,6 +101,17 @@
|
|
|
101
101
|
min-width: 0;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
.leftContentDesktop,
|
|
105
|
+
.leftContentMobile {
|
|
106
|
+
display: inline-flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
min-width: 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.leftContentMobile {
|
|
112
|
+
display: none;
|
|
113
|
+
}
|
|
114
|
+
|
|
104
115
|
.brandName {
|
|
105
116
|
color: var(--color-text);
|
|
106
117
|
font-size: 16px;
|
|
@@ -185,6 +196,12 @@
|
|
|
185
196
|
display: inline-flex;
|
|
186
197
|
}
|
|
187
198
|
|
|
199
|
+
.navCustomItem {
|
|
200
|
+
display: inline-flex;
|
|
201
|
+
align-items: center;
|
|
202
|
+
min-height: 40px;
|
|
203
|
+
}
|
|
204
|
+
|
|
188
205
|
.navLink {
|
|
189
206
|
corner-shape: unset;
|
|
190
207
|
min-height: 40px;
|
|
@@ -235,7 +252,7 @@
|
|
|
235
252
|
font-weight: 600;
|
|
236
253
|
}
|
|
237
254
|
|
|
238
|
-
.desktopLabel svg {
|
|
255
|
+
.desktopLabel svg.logotype, .desktopLabel :global(svg.logotype) {
|
|
239
256
|
max-height: 12px;
|
|
240
257
|
}
|
|
241
258
|
|
|
@@ -329,7 +346,7 @@
|
|
|
329
346
|
justify-content: center;
|
|
330
347
|
min-height: 72px;
|
|
331
348
|
height: 72px;
|
|
332
|
-
padding: 11px
|
|
349
|
+
padding: 11px 28px 11px 0px;
|
|
333
350
|
border: none;
|
|
334
351
|
border-radius: calc(var(--radius-root) * 1.55);
|
|
335
352
|
background: transparent;
|
|
@@ -338,15 +355,23 @@
|
|
|
338
355
|
box-sizing: border-box;
|
|
339
356
|
gap: 12px;
|
|
340
357
|
user-select: none;
|
|
341
|
-
transition: background 0.2s ease-out, opacity 0.2s ease, transform 0.15s ease;
|
|
358
|
+
transition: background 0.2s ease-out, opacity 0.2s ease, transform 0.15s ease, padding 0.2s ease-in-out;
|
|
342
359
|
font-size: 30px;
|
|
343
360
|
font-weight: 600;
|
|
344
361
|
cursor: pointer;
|
|
345
362
|
font-family: inherit;
|
|
346
363
|
}
|
|
347
364
|
|
|
365
|
+
.menuCustomItem {
|
|
366
|
+
width: 100%;
|
|
367
|
+
display: inline-flex;
|
|
368
|
+
align-items: center;
|
|
369
|
+
justify-content: center;
|
|
370
|
+
}
|
|
371
|
+
|
|
348
372
|
.menuLink:hover {
|
|
349
373
|
color: var(--color-text);
|
|
374
|
+
padding: 11px 11px 11px 11px;
|
|
350
375
|
}
|
|
351
376
|
|
|
352
377
|
.menuItemMarker {
|
|
@@ -428,6 +453,14 @@
|
|
|
428
453
|
.dividingLine {
|
|
429
454
|
display: none;
|
|
430
455
|
}
|
|
456
|
+
|
|
457
|
+
.leftContentDesktop {
|
|
458
|
+
display: none;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.leftContentMobile {
|
|
462
|
+
display: inline-flex;
|
|
463
|
+
}
|
|
431
464
|
}
|
|
432
465
|
|
|
433
466
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -440,4 +473,4 @@
|
|
|
440
473
|
.menuItemMarker {
|
|
441
474
|
transition: none;
|
|
442
475
|
}
|
|
443
|
-
}
|
|
476
|
+
}
|
package/NavHeader.tsx
CHANGED
|
@@ -15,6 +15,7 @@ export type NavHeaderItem = {
|
|
|
15
15
|
ariaLabel: string
|
|
16
16
|
href?: string
|
|
17
17
|
external?: boolean
|
|
18
|
+
hideInMobileMenu?: boolean
|
|
18
19
|
active?: boolean
|
|
19
20
|
matchPath?: string
|
|
20
21
|
onClick?: (
|
|
@@ -29,7 +30,10 @@ export type NavHeaderProps = {
|
|
|
29
30
|
variant?: 'default' | 'docs' | (string & {})
|
|
30
31
|
showHeaderBlur?: boolean
|
|
31
32
|
navItems?: NavHeaderItem[]
|
|
33
|
+
leftPadding?: number | string
|
|
32
34
|
leftSlot?: React.ReactNode
|
|
35
|
+
leftSlotDesktop?: React.ReactNode
|
|
36
|
+
leftSlotMobile?: React.ReactNode
|
|
33
37
|
logo?: React.ReactNode
|
|
34
38
|
brandName?: string
|
|
35
39
|
homeHref?: string
|
|
@@ -94,6 +98,14 @@ const renderDesktopItem = (
|
|
|
94
98
|
)
|
|
95
99
|
}
|
|
96
100
|
|
|
101
|
+
if (!item.onClick) {
|
|
102
|
+
return (
|
|
103
|
+
<div className={styles.navCustomItem} aria-label={item.ariaLabel}>
|
|
104
|
+
{renderItemLabel(item)}
|
|
105
|
+
</div>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
97
109
|
return (
|
|
98
110
|
<button
|
|
99
111
|
type='button'
|
|
@@ -118,7 +130,9 @@ const renderMobileItem = (
|
|
|
118
130
|
const content = (
|
|
119
131
|
<>
|
|
120
132
|
<span aria-hidden className={styles.menuItemMarker}>
|
|
121
|
-
/
|
|
133
|
+
<svg height="23" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
134
|
+
<path d="M2.21289 12H0.291016L5.73047 0H7.65234L2.21289 12Z" fill="white" fill-opacity="0.5" />
|
|
135
|
+
</svg>
|
|
122
136
|
</span>
|
|
123
137
|
<span className={styles.menuLabel}>{renderItemLabel(item)}</span>
|
|
124
138
|
</>
|
|
@@ -139,6 +153,14 @@ const renderMobileItem = (
|
|
|
139
153
|
)
|
|
140
154
|
}
|
|
141
155
|
|
|
156
|
+
if (!item.onClick) {
|
|
157
|
+
return (
|
|
158
|
+
<div className={styles.menuCustomItem} aria-label={item.ariaLabel}>
|
|
159
|
+
{renderItemLabel(item)}
|
|
160
|
+
</div>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
142
164
|
return (
|
|
143
165
|
<button
|
|
144
166
|
type='button'
|
|
@@ -156,7 +178,10 @@ const NavHeader: React.FC<NavHeaderProps> = ({
|
|
|
156
178
|
variant = 'default',
|
|
157
179
|
showHeaderBlur = true,
|
|
158
180
|
navItems = [],
|
|
181
|
+
leftPadding = 0,
|
|
159
182
|
leftSlot,
|
|
183
|
+
leftSlotDesktop,
|
|
184
|
+
leftSlotMobile,
|
|
160
185
|
logo,
|
|
161
186
|
brandName = 'Brand',
|
|
162
187
|
homeHref = '/',
|
|
@@ -167,8 +192,15 @@ const NavHeader: React.FC<NavHeaderProps> = ({
|
|
|
167
192
|
const [menuOpen, setMenuOpen] = useState(false)
|
|
168
193
|
|
|
169
194
|
const resolvedLabels = { ...DEFAULT_LABELS, ...labels }
|
|
170
|
-
const
|
|
195
|
+
const desktopNavItems = navItems
|
|
196
|
+
const mobileNavItems = navItems.filter((item) => !item.hideInMobileMenu)
|
|
197
|
+
const hasDesktopNavItems = desktopNavItems.length > 0
|
|
198
|
+
const hasMobileNavItems = mobileNavItems.length > 0
|
|
171
199
|
const resolvedLogoAriaLabel = logoAriaLabel ?? brandName
|
|
200
|
+
const resolvedLeftPadding =
|
|
201
|
+
typeof leftPadding === 'number' ? `${leftPadding}px` : leftPadding
|
|
202
|
+
const hasResponsiveLeftSlot =
|
|
203
|
+
leftSlotDesktop !== undefined || leftSlotMobile !== undefined
|
|
172
204
|
|
|
173
205
|
const brandContent = logo ?? <span className={styles.brandName}>{brandName}</span>
|
|
174
206
|
|
|
@@ -179,8 +211,15 @@ const NavHeader: React.FC<NavHeaderProps> = ({
|
|
|
179
211
|
data-variant={variant}
|
|
180
212
|
>
|
|
181
213
|
{showHeaderBlur && <BlurEffect className={styles.blurEffect} position="top" intensity={100} aria-hidden />}
|
|
182
|
-
<header
|
|
183
|
-
{
|
|
214
|
+
<header
|
|
215
|
+
className={styles.inner}
|
|
216
|
+
style={
|
|
217
|
+
{
|
|
218
|
+
'--nav-header-left-padding': resolvedLeftPadding,
|
|
219
|
+
} as React.CSSProperties
|
|
220
|
+
}
|
|
221
|
+
>
|
|
222
|
+
{hasMobileNavItems && (
|
|
184
223
|
<div className={styles.mobileMenu}>
|
|
185
224
|
<Drawer.Root
|
|
186
225
|
open={menuOpen}
|
|
@@ -224,7 +263,7 @@ const NavHeader: React.FC<NavHeaderProps> = ({
|
|
|
224
263
|
className={styles.menuNav}
|
|
225
264
|
aria-label={resolvedLabels.menu}
|
|
226
265
|
>
|
|
227
|
-
{
|
|
266
|
+
{mobileNavItems.map((item) => {
|
|
228
267
|
const key =
|
|
229
268
|
item.id ??
|
|
230
269
|
item.href ??
|
|
@@ -241,14 +280,26 @@ const NavHeader: React.FC<NavHeaderProps> = ({
|
|
|
241
280
|
)
|
|
242
281
|
)
|
|
243
282
|
|
|
283
|
+
if (item.href || item.onClick) {
|
|
284
|
+
return (
|
|
285
|
+
<Drawer.Close asChild key={key}>
|
|
286
|
+
{renderMobileItem(
|
|
287
|
+
item,
|
|
288
|
+
styles.menuLink,
|
|
289
|
+
isActive
|
|
290
|
+
)}
|
|
291
|
+
</Drawer.Close>
|
|
292
|
+
)
|
|
293
|
+
}
|
|
294
|
+
|
|
244
295
|
return (
|
|
245
|
-
<
|
|
296
|
+
<div key={key}>
|
|
246
297
|
{renderMobileItem(
|
|
247
298
|
item,
|
|
248
299
|
styles.menuLink,
|
|
249
300
|
isActive
|
|
250
301
|
)}
|
|
251
|
-
</
|
|
302
|
+
</div>
|
|
252
303
|
)
|
|
253
304
|
})}
|
|
254
305
|
</nav>
|
|
@@ -264,7 +315,32 @@ const NavHeader: React.FC<NavHeaderProps> = ({
|
|
|
264
315
|
</div>
|
|
265
316
|
)}
|
|
266
317
|
<div className={cx(styles.column, styles.left)}>
|
|
267
|
-
{
|
|
318
|
+
{hasResponsiveLeftSlot ? (
|
|
319
|
+
<>
|
|
320
|
+
{leftSlotDesktop !== undefined && (
|
|
321
|
+
<div
|
|
322
|
+
className={cx(
|
|
323
|
+
styles.leftContent,
|
|
324
|
+
styles.leftContentDesktop
|
|
325
|
+
)}
|
|
326
|
+
>
|
|
327
|
+
{leftSlotDesktop}
|
|
328
|
+
</div>
|
|
329
|
+
)}
|
|
330
|
+
{leftSlotMobile !== undefined && (
|
|
331
|
+
<div
|
|
332
|
+
className={cx(
|
|
333
|
+
styles.leftContent,
|
|
334
|
+
styles.leftContentMobile
|
|
335
|
+
)}
|
|
336
|
+
>
|
|
337
|
+
{leftSlotMobile}
|
|
338
|
+
</div>
|
|
339
|
+
)}
|
|
340
|
+
</>
|
|
341
|
+
) : (
|
|
342
|
+
leftSlot && <div className={styles.leftContent}>{leftSlot}</div>
|
|
343
|
+
)}
|
|
268
344
|
</div>
|
|
269
345
|
|
|
270
346
|
<div className={styles.centerColumn}>
|
|
@@ -280,39 +356,39 @@ const NavHeader: React.FC<NavHeaderProps> = ({
|
|
|
280
356
|
</div>
|
|
281
357
|
</div>
|
|
282
358
|
|
|
283
|
-
{
|
|
359
|
+
{hasDesktopNavItems && (
|
|
284
360
|
<>
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
361
|
+
<span className={styles.dividingLine} />
|
|
362
|
+
<nav
|
|
363
|
+
className={styles.desktopNav}
|
|
364
|
+
aria-label={resolvedLabels.menu}
|
|
365
|
+
>
|
|
366
|
+
<div className={styles.navList}>
|
|
367
|
+
{desktopNavItems.map((item) => {
|
|
368
|
+
const key = item.id ?? item.href ?? item.ariaLabel
|
|
369
|
+
const isActive =
|
|
370
|
+
item.active ??
|
|
371
|
+
Boolean(
|
|
372
|
+
item.href &&
|
|
373
|
+
!item.external &&
|
|
374
|
+
isMenuItemActive(
|
|
375
|
+
currentPath,
|
|
376
|
+
item.matchPath ?? item.href
|
|
377
|
+
)
|
|
301
378
|
)
|
|
302
|
-
)
|
|
303
379
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
380
|
+
return (
|
|
381
|
+
<div className={styles.navItem} key={key}>
|
|
382
|
+
{renderDesktopItem(
|
|
383
|
+
item,
|
|
384
|
+
styles.navLink,
|
|
385
|
+
isActive
|
|
386
|
+
)}
|
|
387
|
+
</div>
|
|
388
|
+
)
|
|
389
|
+
})}
|
|
390
|
+
</div>
|
|
391
|
+
</nav>
|
|
316
392
|
</>
|
|
317
393
|
)}
|
|
318
394
|
</div>
|