ketekny-ui-kit 1.0.102 → 1.0.104

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,7 +1,7 @@
1
1
  {
2
2
  "name": "ketekny-ui-kit",
3
3
  "type": "module",
4
- "version": "1.0.102",
4
+ "version": "1.0.104",
5
5
  "description": "A Vue 3 UI component library with Tailwind CSS styling",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -1,5 +1,15 @@
1
1
  <template>
2
2
  <main class="flex min-h-screen w-full max-w-none flex-col bg-slate-100">
3
+ <div
4
+ v-if="showHeaderExtraBeforeTitle"
5
+ class="sticky z-30 border-b border-t border-slate-200 bg-slate-50 px-4 backdrop-blur sm:px-6 lg:px-8"
6
+ :style="{ top: headerExtraTop }"
7
+ >
8
+ <div class="mx-auto flex w-full max-w-none items-center">
9
+ <slot name="header-extra" />
10
+ </div>
11
+ </div>
12
+
3
13
  <section class="bg-white px-4 pb-4 pb-0 pt-8 sm:px-6 lg:px-8">
4
14
  <div class="mx-auto flex w-full max-w-none flex-col gap-5">
5
15
  <div
@@ -31,7 +41,11 @@
31
41
  </div>
32
42
  </section>
33
43
 
34
- <div class="sticky top-0 z-30 border-b border-t border-slate-200 bg-slate-50 px-4 backdrop-blur sm:px-6 lg:px-8">
44
+ <div
45
+ v-if="showHeaderExtraAfterTitle"
46
+ class="sticky z-30 border-b border-t border-slate-200 bg-slate-50 px-4 backdrop-blur sm:px-6 lg:px-8"
47
+ :style="{ top: headerExtraTop }"
48
+ >
35
49
  <div class="mx-auto flex w-full max-w-none items-center">
36
50
  <slot name="header-extra" />
37
51
  </div>
@@ -69,8 +83,22 @@ export default {
69
83
  type: String,
70
84
  default: '',
71
85
  },
86
+ headerExtraTop: {
87
+ type: String,
88
+ default: '0px',
89
+ },
90
+ headerExtraBeforeTitle: {
91
+ type: Boolean,
92
+ default: false,
93
+ },
72
94
  },
73
95
  computed: {
96
+ showHeaderExtraBeforeTitle() {
97
+ return this.headerExtraBeforeTitle && Boolean(this.$slots['header-extra'])
98
+ },
99
+ showHeaderExtraAfterTitle() {
100
+ return !this.headerExtraBeforeTitle && Boolean(this.$slots['header-extra'])
101
+ },
74
102
  externalUrlLabel() {
75
103
  const target = String(this.externalUrl || '').trim()
76
104
  if (!target) return ''
@@ -13,10 +13,11 @@ import {
13
13
  } from '@lucide/vue'
14
14
  import SidebarMenuItem from './SidebarMenuItem.vue'
15
15
  import kMenu from '../../ui/kMenu.vue'
16
- import demoAvatarUrl from '../../../dark-sidebar-menu-design/public/placeholder-user.jpg'
16
+ import demoAvatarUrl from '../assets/placeholder-user.jpg'
17
17
 
18
18
  const FAVORITES_STORAGE_KEY = 'ketekny-ui-sidebar-favorites'
19
19
  const MENU_TAB_STORAGE_KEY = 'ketekny-ui-sidebar-menu-tab'
20
+ const LOGO_BASE_URL = 'https://s3.ketekny.gr/public/web-apps/logos'
20
21
 
21
22
  export default {
22
23
  name: 'MultilevelSidebar',
@@ -71,6 +72,11 @@ export default {
71
72
  type: Boolean,
72
73
  default: false,
73
74
  },
75
+ theme: {
76
+ type: String,
77
+ default: 'dark',
78
+ validator: value => ['dark', 'light'].includes(value),
79
+ },
74
80
  },
75
81
  emits: ['select', 'logo-click', 'signin', 'signup', 'signout', 'edit-profile', 'item-click'],
76
82
  data() {
@@ -95,6 +101,17 @@ export default {
95
101
  width: this.collapsed ? this.collapsedWidth : this.width,
96
102
  }
97
103
  },
104
+ themeClass() {
105
+ return this.theme === 'light' ? 'sidebar-theme-light' : 'sidebar-theme-dark'
106
+ },
107
+ activeExpandedLogoSrc() {
108
+ if (this.theme === 'light') return `${LOGO_BASE_URL}/logo-light.png`
109
+ return `${LOGO_BASE_URL}/logo-dark.png`
110
+ },
111
+ activeCollapsedLogoSrc() {
112
+ if (this.theme === 'light') return `${LOGO_BASE_URL}/logo_icon.jpg`
113
+ return `${LOGO_BASE_URL}/logo-icon-dark.png`
114
+ },
98
115
  collapsedTitle() {
99
116
  if (!this.title) return ''
100
117
  const words = this.title.trim().split(/\s+/).filter(Boolean)
@@ -395,16 +412,17 @@ export default {
395
412
 
396
413
  <template>
397
414
  <aside
398
- class="group/sidebar fixed inset-y-0 left-0 z-40 flex h-full shrink-0 flex-col border-r border-sidebar-border bg-sidebar text-sidebar-foreground transition-[width,transform] duration-200 ease-out lg:static lg:translate-x-0"
415
+ class="group/sidebar fixed inset-y-0 left-0 z-40 flex h-full shrink-0 flex-col border-r border-[var(--sidebar-border)] bg-[var(--sidebar-bg)] text-[var(--sidebar-text)] transition-[width,transform] duration-200 ease-out lg:static lg:translate-x-0"
399
416
  :style="sidebarWidthStyle"
400
417
  :class="[
418
+ themeClass,
401
419
  mobileOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0',
402
420
  ]"
403
421
  >
404
422
  <button
405
423
  type="button"
406
424
  v-tooltip.right="collapsed ? 'Ανάπτυξη πλαϊνού μενού' : 'Σύμπτυξη πλαϊνού μενού'"
407
- class="absolute right-0 top-1/2 z-50 hidden h-14 w-6 -translate-y-1/2 translate-x-1/2 items-center justify-center rounded-r-md border border-sidebar-border bg-sidebar-accent text-sidebar-muted opacity-70 shadow-lg shadow-black/30 transition-[color,opacity] hover:opacity-100 hover:text-sidebar-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand lg:inline-flex"
425
+ class="absolute right-0 top-1/2 z-50 hidden h-14 w-6 -translate-y-1/2 translate-x-1/2 items-center justify-center rounded-r-md border border-[var(--sidebar-border)] bg-[var(--sidebar-surface)] text-[var(--sidebar-text-muted)] opacity-85 shadow-lg shadow-[var(--sidebar-shadow)] transition-[color,opacity,background-color] hover:bg-[var(--sidebar-hover)] hover:opacity-100 hover:text-[var(--sidebar-text)] focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand lg:inline-flex"
408
426
  :aria-label="collapsed ? 'Ανάπτυξη πλαϊνού μενού' : 'Σύμπτυξη πλαϊνού μενού'"
409
427
  @click="toggleCollapsed"
410
428
  >
@@ -415,14 +433,14 @@ export default {
415
433
  <div class="relative flex items-center px-4 py-4" :class="collapsed ? 'justify-center' : 'gap-2.5'">
416
434
  <img
417
435
  v-if="collapsed"
418
- src="https://s3.ketekny.gr/public/web-apps/logos/logo-icon-dark.png"
436
+ :src="activeCollapsedLogoSrc"
419
437
  alt="Ketekny logo"
420
438
  class="size-9 shrink-0 rounded-lg object-contain cursor-pointer"
421
439
  @click="handleLogoClick"
422
440
  />
423
441
  <img
424
442
  v-else
425
- src="https://support.ketekny.gr/logo-dark.png"
443
+ :src="activeExpandedLogoSrc"
426
444
  alt="Ketekny logo"
427
445
  class="min-w-0 flex-1 object-contain cursor-pointer"
428
446
  @click="handleLogoClick"
@@ -430,7 +448,7 @@ export default {
430
448
  </div>
431
449
 
432
450
  <div v-if="title && !collapsed" class="px-4 pb-2">
433
- <p class="text-xl font-bold text-center text-sidebar-foreground">
451
+ <p class="text-xl font-bold text-center text-[var(--sidebar-text)]">
434
452
  {{ title }}
435
453
  </p>
436
454
  </div>
@@ -438,7 +456,7 @@ export default {
438
456
  <div v-else-if="(title || appIcon) && collapsed" class="flex justify-center px-3 pb-2">
439
457
  <div
440
458
  v-tooltip.right="title"
441
- class="flex h-10 w-10 items-center justify-center rounded-md border border-sidebar-border/30 bg-sidebar-accent/30 text-[10px] font-bold tracking-[0.18em] text-sidebar-muted"
459
+ class="flex h-10 w-10 items-center justify-center rounded-md border border-[var(--sidebar-border)] bg-[var(--sidebar-surface-muted)] text-[10px] font-bold tracking-[0.18em] text-[var(--sidebar-text-muted)]"
442
460
  >
443
461
  <img
444
462
  v-if="appIcon"
@@ -458,13 +476,13 @@ export default {
458
476
  aria-label="Main navigation"
459
477
  >
460
478
  <div v-if="showMenuTabs" class="mb-3 px-1">
461
- <div class="inline-flex w-full rounded-lg bg-sidebar-accent/35 p-1">
479
+ <div class="inline-flex w-full rounded-lg bg-[var(--sidebar-surface-muted)] p-1">
462
480
  <button
463
481
  type="button"
464
482
  class="flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors"
465
483
  :class="activeMenuTab === 'all'
466
- ? 'bg-sidebar text-sidebar-foreground shadow-sm'
467
- : 'text-sidebar-muted hover:text-sidebar-foreground'"
484
+ ? 'bg-[var(--sidebar-surface)] text-[var(--sidebar-text)] shadow-sm'
485
+ : 'text-[var(--sidebar-text-muted)] hover:text-[var(--sidebar-text)]'"
468
486
  @click="activeMenuTab = 'all'"
469
487
  >
470
488
  Όλα
@@ -473,8 +491,8 @@ export default {
473
491
  type="button"
474
492
  class="flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors"
475
493
  :class="activeMenuTab === 'favorites'
476
- ? 'bg-sidebar text-sidebar-foreground shadow-sm'
477
- : 'text-sidebar-muted hover:text-sidebar-foreground'"
494
+ ? 'bg-[var(--sidebar-surface)] text-[var(--sidebar-text)] shadow-sm'
495
+ : 'text-[var(--sidebar-text-muted)] hover:text-[var(--sidebar-text)]'"
478
496
  @click="activeMenuTab = 'favorites'"
479
497
  >
480
498
  Αγαπημένα
@@ -485,7 +503,7 @@ export default {
485
503
  <div v-if="!collapsed && (!showMenuTabs || activeMenuTab === 'all')" class="px-1 pb-3">
486
504
  <div class="relative">
487
505
  <Search
488
- class="pointer-events-none absolute left-2.5 top-1/2 size-4 -translate-y-1/2 text-sidebar-muted"
506
+ class="pointer-events-none absolute left-2.5 top-1/2 size-4 -translate-y-1/2 text-[var(--sidebar-text-muted)]"
489
507
  :stroke-width="2"
490
508
  />
491
509
  <input
@@ -493,12 +511,12 @@ export default {
493
511
  type="text"
494
512
  placeholder="Αναζήτηση μενού..."
495
513
  aria-label="Αναζήτηση μενού"
496
- class="w-full border rounded-md border-sidebar-border/35 bg-sidebar-accent/40 py-2 pl-8 pr-9 text-sidebar-foreground placeholder:text-sidebar-muted focus:border-white/15 focus:outline-none focus:ring-1 focus:ring-white/10"
514
+ class="w-full rounded-md border border-[var(--sidebar-border)] bg-[var(--sidebar-surface)] py-2 pl-8 pr-9 text-[var(--sidebar-text)] placeholder:text-[var(--sidebar-text-muted)] focus:border-[var(--sidebar-border-strong)] focus:outline-none focus:ring-1 focus:ring-[var(--sidebar-border-strong)]"
497
515
  />
498
516
  <button
499
517
  v-if="query"
500
518
  type="button"
501
- class="absolute right-2 top-1/2 inline-flex size-6 -translate-y-1/2 items-center justify-center rounded-md text-sidebar-muted transition-colors hover:bg-sidebar-accent hover:text-sidebar-foreground"
519
+ class="absolute right-2 top-1/2 inline-flex size-6 -translate-y-1/2 items-center justify-center rounded-md text-[var(--sidebar-text-muted)] transition-colors hover:bg-[var(--sidebar-hover)] hover:text-[var(--sidebar-text)]"
502
520
  aria-label="Καθαρισμός αναζήτησης"
503
521
  @click="clearQuery"
504
522
  >
@@ -517,6 +535,7 @@ export default {
517
535
  :open-ids="effectiveOpenIds"
518
536
  :collapsed="collapsed"
519
537
  :favorites="favoriteIds"
538
+ :theme="theme"
520
539
  @select="handleMenuSelect"
521
540
  @toggle="toggle"
522
541
  @toggle-favorite="toggleFavorite"
@@ -524,13 +543,13 @@ export default {
524
543
  </ul>
525
544
  <p
526
545
  v-if="!collapsed && displayedMenuItems.length === 0"
527
- class="px-3 py-6 text-center text-sidebar-muted"
546
+ class="px-3 py-6 text-center text-[var(--sidebar-text-muted)]"
528
547
  >
529
548
  Δεν βρέθηκαν αποτελέσματα.
530
549
  </p>
531
550
  </nav>
532
551
 
533
- <div class="mt-auto border-t border-sidebar-border px-3 pb-3 pt-4">
552
+ <div class="mt-auto border-t border-[var(--sidebar-border)] px-3 pb-3 pt-4">
534
553
  <div
535
554
  :class="collapsed
536
555
  ? 'flex flex-col items-center gap-1'
@@ -548,8 +567,8 @@ export default {
548
567
  activeId === link.id
549
568
  ? 'bg-brand text-brand-foreground font-medium'
550
569
  : link.id === 'sign-out'
551
- ? 'text-orange-300 hover:bg-orange-500/10 hover:text-orange-200'
552
- : 'text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-foreground',
570
+ ? 'text-[var(--sidebar-danger)] hover:bg-[var(--sidebar-danger-bg)] hover:text-[var(--sidebar-danger-hover)]'
571
+ : 'text-[var(--sidebar-text-soft)] hover:bg-[var(--sidebar-hover)] hover:text-[var(--sidebar-text)]',
553
572
  ]"
554
573
  :aria-label="link.label"
555
574
  @click="handleFooterSelect(link.id)"
@@ -561,8 +580,8 @@ export default {
561
580
  activeId === link.id
562
581
  ? 'text-brand-foreground'
563
582
  : link.id === 'sign-out'
564
- ? 'text-orange-400'
565
- : 'text-sidebar-muted'
583
+ ? 'text-[var(--sidebar-danger)]'
584
+ : 'text-[var(--sidebar-text-muted)]'
566
585
  "
567
586
  :stroke-width="2"
568
587
  />
@@ -575,7 +594,7 @@ export default {
575
594
  aria-label="Account options"
576
595
  >
577
596
  <template #trigger>
578
- <div class="flex w-full items-center gap-2 rounded-lg px-1 py-1 text-sidebar-foreground/90 transition-colors duration-150">
597
+ <div class="flex w-full items-center gap-2 rounded-lg px-1 py-1 text-[var(--sidebar-text-strong)] transition-colors duration-150">
579
598
  <div class="sidebar-footer-item flex min-h-[44px] flex-1 items-center gap-2.5 rounded-lg bg-transparent px-1.5 py-1.5 text-left font-medium">
580
599
  <img
581
600
  :src="demoAvatarUrl"
@@ -584,12 +603,12 @@ export default {
584
603
  />
585
604
  <span class="min-w-0 flex-1">
586
605
  <span class="block truncate text-sm font-semibold">{{ accountDisplayName || 'Το προφίλ μου' }}</span>
587
- <span class="block truncate text-xs font-normal text-sidebar-muted">{{ accountEmail }}</span>
606
+ <span class="block truncate text-xs font-normal text-[var(--sidebar-text-muted)]">{{ accountEmail }}</span>
588
607
  </span>
589
608
  </div>
590
609
 
591
610
  <span
592
- class="inline-flex size-9 items-center justify-center rounded-lg text-sidebar-muted"
611
+ class="inline-flex size-9 items-center justify-center rounded-lg text-[var(--sidebar-text-muted)]"
593
612
  aria-hidden="true"
594
613
  >
595
614
  <Ellipsis class="size-4" :stroke-width="2" />
@@ -602,23 +621,23 @@ export default {
602
621
 
603
622
  <div
604
623
  v-if="!collapsed"
605
- class="mt-3 border-t border-sidebar-border/70 px-2 pt-2 text-[11px] leading-snug text-sidebar-foreground/90"
624
+ class="mt-3 border-t border-[var(--sidebar-border)] px-2 pt-2 text-[11px] leading-snug text-[var(--sidebar-text-strong)]"
606
625
  >
607
- <div class="flex items-center gap-1.5 text-sidebar-foreground">
608
- <Building2 class="size-3 shrink-0 text-sidebar-muted" :stroke-width="2" />
626
+ <div class="flex items-center gap-1.5 text-[var(--sidebar-text)]">
627
+ <Building2 class="size-3 shrink-0 text-[var(--sidebar-text-muted)]" :stroke-width="2" />
609
628
  <p class="font-semibold uppercase tracking-[0.28em]">KETEKNY AE</p>
610
629
  </div>
611
630
  <div class="mt-1.5 pl-[18px]">
612
631
  <p class="truncate ">Βερανζέρου 13, 10677, Αθήνα
613
632
  <span>&nbsp;</span>
614
- <a href="tel:+302103648337" class="transition-colors hover:text-sidebar-foreground">
633
+ <a href="tel:+302103648337" class="transition-colors hover:text-[var(--sidebar-text)]">
615
634
  210 3648 337
616
635
  </a></p>
617
636
 
618
637
  <div class="flex flex-wrap items-center gap-x-3">
619
638
  <a
620
639
  :href="`mailto:${contactEmail}`"
621
- class="transition-colors hover:text-sidebar-foreground"
640
+ class="transition-colors hover:text-[var(--sidebar-text)]"
622
641
  >
623
642
  {{ contactEmail }}
624
643
  </a>
@@ -626,7 +645,7 @@ export default {
626
645
  :href="helpUrl || 'https://help.ketekny.gr'"
627
646
  target="_blank"
628
647
  rel="noreferrer"
629
- class="truncate transition-colors hover:text-sidebar-foreground"
648
+ class="truncate transition-colors hover:text-[var(--sidebar-text)]"
630
649
  >
631
650
  {{ helpUrl || 'https://help.ketekny.gr' }}
632
651
  </a>
@@ -636,3 +655,39 @@ export default {
636
655
  </div>
637
656
  </aside>
638
657
  </template>
658
+
659
+ <style scoped>
660
+ .sidebar-theme-dark {
661
+ --sidebar-bg: #0b0c0f;
662
+ --sidebar-surface: #161a22;
663
+ --sidebar-surface-muted: rgba(255, 255, 255, 0.06);
664
+ --sidebar-text: #eef2f7;
665
+ --sidebar-text-soft: rgba(238, 242, 247, 0.8);
666
+ --sidebar-text-strong: rgba(238, 242, 247, 0.9);
667
+ --sidebar-text-muted: #8a92a1;
668
+ --sidebar-border: rgba(255, 255, 255, 0.08);
669
+ --sidebar-border-strong: rgba(255, 255, 255, 0.16);
670
+ --sidebar-hover: rgba(255, 255, 255, 0.08);
671
+ --sidebar-shadow: rgba(0, 0, 0, 0.3);
672
+ --sidebar-danger: #f59e0b;
673
+ --sidebar-danger-hover: #fbbf24;
674
+ --sidebar-danger-bg: rgba(245, 158, 11, 0.12);
675
+ }
676
+
677
+ .sidebar-theme-light {
678
+ --sidebar-bg: #f8fafc;
679
+ --sidebar-surface: #ffffff;
680
+ --sidebar-surface-muted: #eef4fb;
681
+ --sidebar-text: #0f172a;
682
+ --sidebar-text-soft: rgba(15, 23, 42, 0.8);
683
+ --sidebar-text-strong: rgba(15, 23, 42, 0.9);
684
+ --sidebar-text-muted: #64748b;
685
+ --sidebar-border: rgba(148, 163, 184, 0.28);
686
+ --sidebar-border-strong: rgba(100, 116, 139, 0.4);
687
+ --sidebar-hover: #e2e8f0;
688
+ --sidebar-shadow: rgba(15, 23, 42, 0.12);
689
+ --sidebar-danger: #ea580c;
690
+ --sidebar-danger-hover: #c2410c;
691
+ --sidebar-danger-bg: #ffedd5;
692
+ }
693
+ </style>
@@ -16,6 +16,7 @@ export default {
16
16
  openIds: { type: Object, required: true },
17
17
  collapsed: { type: Boolean, default: false },
18
18
  favorites: { type: Object, default: null },
19
+ theme: { type: String, default: 'dark' },
19
20
  },
20
21
  emits: ['select', 'toggle', 'toggle-favorite'],
21
22
  computed: {
@@ -100,8 +101,8 @@ export default {
100
101
  isActiveLeaf || (isCollapsedTop && isActive)
101
102
  ? 'bg-brand text-brand-foreground font-medium'
102
103
  : isActiveTrail
103
- ? 'text-sidebar-foreground'
104
- : 'text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-foreground',
104
+ ? 'text-[var(--sidebar-text)]'
105
+ : 'text-[var(--sidebar-text-soft)] hover:bg-[var(--sidebar-hover)] hover:text-[var(--sidebar-text)]',
105
106
  ]"
106
107
  :aria-expanded="hasChildren && !isCollapsedTop ? isOpen : undefined"
107
108
  :aria-label="isCollapsedTop ? item.label : undefined"
@@ -120,7 +121,7 @@ export default {
120
121
  :class="[
121
122
  isActiveLeaf || (isCollapsedTop && isActive)
122
123
  ? 'text-brand-foreground'
123
- : 'text-sidebar-muted group-hover:text-sidebar-foreground',
124
+ : 'text-[var(--sidebar-text-muted)] group-hover:text-[var(--sidebar-text)]',
124
125
  ]"
125
126
  :stroke-width="2"
126
127
  />
@@ -131,7 +132,7 @@ export default {
131
132
  <span
132
133
  v-if="item.badge != null"
133
134
  class="ml-auto rounded-full px-1.5 py-0.5 text-xs font-medium tabular-nums"
134
- :class="isActiveLeaf ? 'bg-brand-foreground/20 text-brand-foreground' : 'bg-sidebar-accent text-sidebar-muted'"
135
+ :class="isActiveLeaf ? 'bg-brand-foreground/20 text-brand-foreground' : 'bg-[var(--sidebar-surface-muted)] text-[var(--sidebar-text-muted)]'"
135
136
  >
136
137
  {{ item.badge }}
137
138
  </span>
@@ -139,14 +140,14 @@ export default {
139
140
  <ExternalLink
140
141
  v-if="isExternalLink"
141
142
  class="size-3.5 shrink-0"
142
- :class="isActiveLeaf ? 'text-brand-foreground' : 'text-sidebar-muted'"
143
+ :class="isActiveLeaf ? 'text-brand-foreground' : 'text-[var(--sidebar-text-muted)]'"
143
144
  :stroke-width="2"
144
145
  />
145
146
 
146
147
  <button
147
148
  v-if="!hasChildren"
148
149
  type="button"
149
- class="inline-flex size-7 shrink-0 items-center justify-center rounded-md text-sidebar-muted opacity-0 transition-all duration-150 group-hover:opacity-100 hover:bg-sidebar-accent hover:text-sidebar-foreground focus-visible:opacity-100 focus-visible:outline-none"
150
+ class="inline-flex size-7 shrink-0 items-center justify-center rounded-md text-[var(--sidebar-text-muted)] opacity-0 transition-all duration-150 group-hover:opacity-100 hover:bg-[var(--sidebar-hover)] hover:text-[var(--sidebar-text)] focus-visible:opacity-100 focus-visible:outline-none"
150
151
  :class="isFavorite ? 'opacity-100 text-amber-400 hover:text-amber-300' : ''"
151
152
  :aria-label="isFavorite ? 'Remove from favorites' : 'Add to favorites'"
152
153
  @click="toggleFavorite"
@@ -160,7 +161,7 @@ export default {
160
161
 
161
162
  <ChevronRight
162
163
  v-if="hasChildren"
163
- class="size-4 shrink-0 text-sidebar-muted transition-transform duration-200"
164
+ class="size-4 shrink-0 text-[var(--sidebar-text-muted)] transition-transform duration-200"
164
165
  :class="isOpen ? 'rotate-90' : ''"
165
166
  :stroke-width="2"
166
167
  />
@@ -169,7 +170,7 @@ export default {
169
170
  <span
170
171
  v-if="isCollapsedTop && hasChildren"
171
172
  class="absolute right-1.5 top-1.5 size-1.5 rounded-full"
172
- :class="isActive ? 'bg-brand-foreground/80' : 'bg-sidebar-muted/60'"
173
+ :class="isActive ? 'bg-brand-foreground/80' : 'bg-[var(--sidebar-text-muted)]/60'"
173
174
  aria-hidden="true"
174
175
  />
175
176
  </button>
@@ -182,7 +183,7 @@ export default {
182
183
  >
183
184
  <ul
184
185
  v-if="hasChildren && isOpen"
185
- class="overflow-hidden border-l border-sidebar-border/25 ml-4 pl-2 transition-[height] duration-200 ease-out"
186
+ class="overflow-hidden border-l border-[var(--sidebar-border)] ml-4 pl-2 transition-[height] duration-200 ease-out"
186
187
  >
187
188
  <SidebarMenuItem
188
189
  v-for="child in item.children"
@@ -193,6 +194,7 @@ export default {
193
194
  :open-ids="openIds"
194
195
  :collapsed="collapsed"
195
196
  :favorites="favorites"
197
+ :theme="theme"
196
198
  @select="$emit('select', $event)"
197
199
  @toggle="$emit('toggle', $event)"
198
200
  @toggle-favorite="$emit('toggle-favorite', $event)"
@@ -205,14 +207,14 @@ export default {
205
207
  class="invisible absolute left-full top-0 z-50 pl-2 opacity-0 transition-opacity duration-150 group-hover/fly:visible group-hover/fly:opacity-100"
206
208
  >
207
209
  <div
208
- class="min-w-56 rounded-lg border border-sidebar-border bg-sidebar p-2 shadow-xl shadow-black/40"
210
+ class="min-w-56 rounded-lg border border-[var(--sidebar-border)] bg-[var(--sidebar-surface)] p-2 shadow-xl shadow-[var(--sidebar-shadow)]"
209
211
  role="menu"
210
212
  :aria-label="item.label"
211
213
  >
212
214
  <button
213
215
  type="button"
214
216
  class="mb-1 flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left font-semibold"
215
- :class="isActive ? 'text-brand' : 'text-sidebar-foreground hover:bg-sidebar-accent'"
217
+ :class="isActive ? 'text-brand' : 'text-[var(--sidebar-text)] hover:bg-[var(--sidebar-hover)]'"
216
218
  @click="!hasChildren && $emit('select', item)"
217
219
  >
218
220
  <component
@@ -224,7 +226,7 @@ export default {
224
226
  <span class="truncate">{{ item.label }}</span>
225
227
  <ExternalLink
226
228
  v-if="isExternalLink"
227
- class="ml-auto size-3.5 shrink-0 text-sidebar-muted"
229
+ class="ml-auto size-3.5 shrink-0 text-[var(--sidebar-text-muted)]"
228
230
  :stroke-width="2"
229
231
  />
230
232
  </button>
@@ -239,6 +241,7 @@ export default {
239
241
  :open-ids="openIds"
240
242
  :collapsed="false"
241
243
  :favorites="favorites"
244
+ :theme="theme"
242
245
  @select="$emit('select', $event)"
243
246
  @toggle="$emit('toggle', $event)"
244
247
  @toggle-favorite="$emit('toggle-favorite', $event)"
@@ -3,6 +3,7 @@
3
3
  <div v-if="mobileMenuOpen" class="fixed inset-0 z-30 bg-slate-950/50 backdrop-blur-[1px] lg:hidden" @click="closeMenu" />
4
4
 
5
5
  <MultilevelSidebar
6
+ :theme="theme"
6
7
  :title="title"
7
8
  :app-icon="appIcon"
8
9
  :width="width"
@@ -21,14 +22,23 @@
21
22
  @select="handleSelect"
22
23
  />
23
24
 
24
- <main class="flex flex-col flex-1 overflow-y-auto">
25
+ <main class="flex min-h-0 flex-1 flex-col overflow-y-auto">
26
+ <div
27
+ v-if="$slots.header"
28
+ class="sticky top-0 z-20 shrink-0"
29
+ >
30
+ <slot name="header" />
31
+ </div>
25
32
  <slot />
26
33
  </main>
27
34
 
28
35
  <button
29
- v-if="showBurger && !mobileMenuOpen"
36
+ v-if="!mobileMenuOpen"
30
37
  type="button"
31
- class="fixed z-50 inline-flex items-center justify-center text-white transition-colors rounded-full shadow-lg bottom-5 left-5 size-14 bg-sidebar shadow-black/25 hover:bg-sidebar-accent lg:hidden"
38
+ class="fixed bottom-5 left-5 z-50 inline-flex size-14 items-center justify-center rounded-full transition-colors lg:hidden"
39
+ :class="theme === 'light'
40
+ ? 'border border-slate-200 bg-white text-slate-700 shadow-lg shadow-slate-900/10 hover:bg-slate-100'
41
+ : 'bg-sidebar text-white shadow-lg shadow-black/25 hover:bg-sidebar-accent'"
32
42
  aria-label="Open menu"
33
43
  @click="toggleMenu">
34
44
  <Menu class="size-6" :stroke-width="2.25" />
@@ -79,9 +89,10 @@ export default {
79
89
  type: String,
80
90
  default: "https://help.ketekny.gr",
81
91
  },
82
- showBurger: {
83
- type: Boolean,
84
- default: true,
92
+ theme: {
93
+ type: String,
94
+ default: "dark",
95
+ validator: value => ["dark", "light"].includes(value),
85
96
  },
86
97
  },
87
98
  emits: ["select-menu", "logo-click", "signin", "signup", "signout", "edit-profile", "item-click"],