@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.
@@ -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 18px 11px 16px;
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 hasNavItems = navItems.length > 0
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 className={styles.inner}>
183
- {hasNavItems && (
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
- {navItems.map((item) => {
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
- <Drawer.Close asChild key={key}>
296
+ <div key={key}>
246
297
  {renderMobileItem(
247
298
  item,
248
299
  styles.menuLink,
249
300
  isActive
250
301
  )}
251
- </Drawer.Close>
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
- {leftSlot && <div className={styles.leftContent}>{leftSlot}</div>}
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
- {hasNavItems && (
359
+ {hasDesktopNavItems && (
284
360
  <>
285
- <span className={styles.dividingLine} />
286
- <nav
287
- className={styles.desktopNav}
288
- aria-label={resolvedLabels.menu}
289
- >
290
- <div className={styles.navList}>
291
- {navItems.map((item) => {
292
- const key = item.id ?? item.href ?? item.ariaLabel
293
- const isActive =
294
- item.active ??
295
- Boolean(
296
- item.href &&
297
- !item.external &&
298
- isMenuItemActive(
299
- currentPath,
300
- item.matchPath ?? item.href
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
- return (
305
- <div className={styles.navItem} key={key}>
306
- {renderDesktopItem(
307
- item,
308
- styles.navLink,
309
- isActive
310
- )}
311
- </div>
312
- )
313
- })}
314
- </div>
315
- </nav>
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>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claralight-design/abweb-navbar",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "A react components for AstroBox websites.",
5
5
  "scripts": {
6
6
  "dev": "vite",