@farming-labs/nuxt-theme 0.1.54 → 0.1.56

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/nuxt-theme",
3
- "version": "0.1.54",
3
+ "version": "0.1.56",
4
4
  "description": "Nuxt/Vue UI components for @farming-labs/docs — layout, sidebar, TOC, search, and theme toggle",
5
5
  "keywords": [
6
6
  "docs",
@@ -81,7 +81,7 @@
81
81
  },
82
82
  "dependencies": {
83
83
  "sugar-high": "^0.9.5",
84
- "@farming-labs/docs": "0.1.54"
84
+ "@farming-labs/docs": "0.1.56"
85
85
  },
86
86
  "peerDependencies": {
87
87
  "nuxt": ">=3.0.0",
@@ -58,7 +58,6 @@ function withLang(url?: string | null) {
58
58
  const resolvedTitle = computed(() => props.title ?? props.config?.nav?.title ?? "Docs");
59
59
  const resolvedTitleUrl = computed(() => withLang(props.titleUrl ?? props.config?.nav?.url ?? "/docs"));
60
60
  const localizedApi = computed(() => withLang("/api/docs"));
61
-
62
61
  const showThemeToggle = computed(() => {
63
62
  const toggle = props.config?.themeToggle;
64
63
  if (toggle === undefined || toggle === true) return true;
@@ -208,6 +207,24 @@ function closeSearch() {
208
207
  searchOpen.value = false;
209
208
  }
210
209
 
210
+ function suppressFolderSummaryToggle(event: MouseEvent) {
211
+ event.preventDefault();
212
+ }
213
+
214
+ function keepFolderLinkNavigation(event: MouseEvent) {
215
+ event.stopPropagation();
216
+ closeSidebar();
217
+ }
218
+
219
+ function toggleFolder(event: MouseEvent) {
220
+ event.preventDefault();
221
+ event.stopPropagation();
222
+ const details = (event.currentTarget as HTMLElement | null)?.closest("details");
223
+ if (details) {
224
+ details.open = !details.open;
225
+ }
226
+ }
227
+
211
228
  function isActive(url: string) {
212
229
  const current = route.path;
213
230
  const normalised = (url ?? "").replace(/\/$/, "") || "/";
@@ -363,7 +380,45 @@ const showFloatingAI = computed(
363
380
  :class="{ 'fd-sidebar-first-item': i === 0 }"
364
381
  open
365
382
  >
366
- <summary class="fd-sidebar-folder-trigger">
383
+ <summary
384
+ v-if="node.index"
385
+ class="fd-sidebar-folder-trigger fd-sidebar-folder-trigger-link"
386
+ @click="suppressFolderSummaryToggle"
387
+ >
388
+ <NuxtLink
389
+ :to="withLang(node.index.url)"
390
+ class="fd-sidebar-link fd-sidebar-folder-parent-link"
391
+ :class="{ 'fd-sidebar-link-active': isActive(node.index.url) }"
392
+ :data-active="isActive(node.index.url) || undefined"
393
+ @click="keepFolderLinkNavigation"
394
+ >
395
+ <span
396
+ v-if="getIcon(node.icon)"
397
+ class="fd-sidebar-icon"
398
+ v-html="getIcon(node.icon)"
399
+ />
400
+ {{ node.name }}
401
+ </NuxtLink>
402
+ <button
403
+ type="button"
404
+ class="fd-sidebar-folder-toggle"
405
+ :aria-label="`Toggle ${node.name}`"
406
+ @click="toggleFolder"
407
+ >
408
+ <svg
409
+ class="fd-sidebar-chevron"
410
+ width="14"
411
+ height="14"
412
+ viewBox="0 0 24 24"
413
+ fill="none"
414
+ stroke="currentColor"
415
+ stroke-width="2"
416
+ >
417
+ <polyline points="6 9 12 15 18 9" />
418
+ </svg>
419
+ </button>
420
+ </summary>
421
+ <summary v-else class="fd-sidebar-folder-trigger">
367
422
  <span class="fd-sidebar-folder-label">
368
423
  <span
369
424
  v-if="getIcon(node.icon)"
@@ -385,15 +440,6 @@ const showFloatingAI = computed(
385
440
  </svg>
386
441
  </summary>
387
442
  <div class="fd-sidebar-folder-content">
388
- <NuxtLink
389
- v-if="node.index"
390
- :to="withLang(node.index.url)"
391
- class="fd-sidebar-link fd-sidebar-child-link"
392
- :class="{ 'fd-sidebar-link-active': isActive(node.index.url) }"
393
- @click="closeSidebar"
394
- >
395
- {{ node.index.name }}
396
- </NuxtLink>
397
443
  <template
398
444
  v-for="child in node.children"
399
445
  :key="child.name + ((child as any).url ?? '')"
@@ -412,7 +458,40 @@ const showFloatingAI = computed(
412
458
  class="fd-sidebar-folder fd-sidebar-nested-folder"
413
459
  open
414
460
  >
415
- <summary class="fd-sidebar-folder-trigger">
461
+ <summary
462
+ v-if="(child as any).index"
463
+ class="fd-sidebar-folder-trigger fd-sidebar-folder-trigger-link"
464
+ @click="suppressFolderSummaryToggle"
465
+ >
466
+ <NuxtLink
467
+ :to="withLang((child as any).index.url)"
468
+ class="fd-sidebar-link fd-sidebar-folder-parent-link"
469
+ :class="{ 'fd-sidebar-link-active': isActive((child as any).index.url) }"
470
+ :data-active="isActive((child as any).index.url) || undefined"
471
+ @click="keepFolderLinkNavigation"
472
+ >
473
+ {{ child.name }}
474
+ </NuxtLink>
475
+ <button
476
+ type="button"
477
+ class="fd-sidebar-folder-toggle"
478
+ :aria-label="`Toggle ${child.name}`"
479
+ @click="toggleFolder"
480
+ >
481
+ <svg
482
+ class="fd-sidebar-chevron"
483
+ width="14"
484
+ height="14"
485
+ viewBox="0 0 24 24"
486
+ fill="none"
487
+ stroke="currentColor"
488
+ stroke-width="2"
489
+ >
490
+ <polyline points="6 9 12 15 18 9" />
491
+ </svg>
492
+ </button>
493
+ </summary>
494
+ <summary v-else class="fd-sidebar-folder-trigger">
416
495
  <span class="fd-sidebar-folder-label">{{ child.name }}</span>
417
496
  <svg
418
497
  class="fd-sidebar-chevron"
@@ -427,15 +506,6 @@ const showFloatingAI = computed(
427
506
  </svg>
428
507
  </summary>
429
508
  <div class="fd-sidebar-folder-content">
430
- <NuxtLink
431
- v-if="(child as any).index"
432
- :to="withLang((child as any).index.url)"
433
- class="fd-sidebar-link fd-sidebar-child-link"
434
- :class="{ 'fd-sidebar-link-active': isActive((child as any).index.url) }"
435
- @click="closeSidebar"
436
- >
437
- {{ (child as any).index.name }}
438
- </NuxtLink>
439
509
  <NuxtLink
440
510
  v-for="grandchild in (child as any).children"
441
511
  v-if="grandchild.type === 'page'"
package/styles/docs.css CHANGED
@@ -373,13 +373,44 @@ samp {
373
373
  background: var(--color-fd-accent);
374
374
  }
375
375
 
376
+ .fd-sidebar-folder-trigger-link {
377
+ gap: 8px;
378
+ }
379
+
380
+ .fd-sidebar-folder-parent-link {
381
+ min-width: 0;
382
+ flex: 1;
383
+ padding: 0;
384
+ color: inherit;
385
+ background: transparent !important;
386
+ }
387
+
388
+ .fd-sidebar-folder-parent-link:hover {
389
+ color: inherit;
390
+ background: transparent !important;
391
+ }
392
+
393
+ .fd-sidebar-folder-toggle {
394
+ display: inline-flex;
395
+ align-items: center;
396
+ justify-content: center;
397
+ margin: 0;
398
+ padding: 0;
399
+ border: 0;
400
+ background: transparent;
401
+ color: inherit;
402
+ cursor: pointer;
403
+ flex-shrink: 0;
404
+ }
405
+
376
406
  .fd-sidebar-chevron {
377
407
  transition: transform 0.2s;
378
408
  flex-shrink: 0;
379
409
  opacity: 0.5;
380
410
  }
381
411
 
382
- .fd-sidebar-folder[open] > .fd-sidebar-folder-trigger .fd-sidebar-chevron {
412
+ .fd-sidebar-folder[open] > .fd-sidebar-folder-trigger .fd-sidebar-chevron,
413
+ .fd-sidebar-folder[open] > .fd-sidebar-folder-trigger-link .fd-sidebar-chevron {
383
414
  transform: rotate(180deg);
384
415
  }
385
416