@stacksjs/components 0.2.53 → 0.2.63

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.
@@ -4,10 +4,19 @@ export const collapsed = $props.collapsed ?? false
4
4
  export const collapsible = $props.collapsible ?? true
5
5
  export const width = $props.width || 240
6
6
  export const minWidth = $props.minWidth || 64
7
+ export const collapseMode = $props.collapseMode || 'rail'
7
8
  export const variant = $props.variant || 'tahoe'
8
9
  export const position = $props.position || 'left'
9
10
  export const placement = $props.placement || 'fixed'
10
11
  export const bordered = $props.bordered ?? true
12
+ export const materialOpacity = $props.materialOpacity ?? (variant === 'desktop' ? 0.78 : 0.7)
13
+ export const materialDarkOpacity = $props.materialDarkOpacity ?? (variant === 'desktop' ? 0.8 : materialOpacity)
14
+ export const materialScheme = $props.materialScheme || 'system'
15
+ export const persistKey = $props.persistKey || ''
16
+ export const shellSelector = $props.shellSelector || ''
17
+ export const widthVar = $props.widthVar || '--stx-sidebar-width'
18
+ export const collapsedClass = $props.collapsedClass || ''
19
+ export const nativeMaterialCollapse = $props.nativeMaterialCollapse ?? (variant === 'desktop' && collapseMode === 'hidden')
11
20
  export const className = $props.className || ''
12
21
 
13
22
  const variantStyles = {
@@ -44,13 +53,13 @@ const variantStyles = {
44
53
  slot: 'px-5 py-5',
45
54
  },
46
55
  desktop: {
47
- bg: 'bg-white/42 dark:bg-black/32',
48
- border: 'border-white/30 dark:border-white/10',
49
- backdrop: 'backdrop-blur-3xl backdrop-saturate-200',
56
+ bg: 'bg-[#f3f3f1]/48 dark:bg-neutral-950/32',
57
+ border: 'border-white/15 dark:border-white/10',
58
+ backdrop: 'backdrop-blur-3xl backdrop-saturate-150',
50
59
  tint: false,
51
60
  shimmer: true,
52
- nav: 'px-4 py-4 space-y-1',
53
- slot: 'px-4 py-4',
61
+ nav: 'px-5 py-2 space-y-1',
62
+ slot: 'px-5 py-2',
54
63
  },
55
64
  }
56
65
 
@@ -77,7 +86,9 @@ export const containerClasses = [
77
86
  className,
78
87
  ].filter(Boolean).join(' ')
79
88
 
80
- export const collapseBtnPosition = position === 'left' ? 'right-2' : 'left-2'
89
+ export const collapseBtnPosition = variant === 'desktop'
90
+ ? (position === 'left' ? 'left-[166px]' : 'right-[166px]')
91
+ : (position === 'left' ? 'right-2' : 'left-2')
81
92
  export const navClasses = style.nav || 'px-3 py-2 space-y-1'
82
93
  export const slotClasses = style.slot || 'px-3 py-2'
83
94
  </script>
@@ -88,9 +99,18 @@ const collapsedProp = {{ collapsed }}
88
99
  const collapsibleProp = {{ collapsible }}
89
100
  const widthProp = {{ width }}
90
101
  const minWidthProp = {{ minWidth }}
102
+ const collapseModeProp = {{ collapseMode }}
91
103
  const sectionsProp = {{ sections }}
92
104
  const positionProp = {{ position }}
93
105
  const variantProp = {{ variant }}
106
+ const materialOpacityProp = {{ materialOpacity }}
107
+ const materialDarkOpacityProp = {{ materialDarkOpacity }}
108
+ const materialSchemeProp = {{ materialScheme }}
109
+ const persistKeyProp = {{ persistKey }}
110
+ const shellSelectorProp = {{ shellSelector }}
111
+ const widthVarProp = {{ widthVar }}
112
+ const collapsedClassProp = {{ collapsedClass }}
113
+ const nativeMaterialCollapseProp = {{ nativeMaterialCollapse }}
94
114
 
95
115
  const collapsed = state(collapsedProp)
96
116
  const isHovered = state(false)
@@ -98,14 +118,45 @@ const hasNativeSidebar = state(false)
98
118
 
99
119
  const showExpanded = derived(() => !collapsed() || isHovered())
100
120
  const sidebarWidth = derived(() => {
121
+ if (collapsed() && collapseModeProp === 'hidden') return '0px'
101
122
  if (collapsed() && !isHovered()) return `${minWidthProp}px`
102
123
  return `${widthProp}px`
103
124
  })
104
125
  const collapseAriaLabel = derived(() => collapsed() ? 'Expand sidebar' : 'Collapse sidebar')
105
- const collapseIconClass = derived(() => collapsed() ? 'i-hugeicons-sidebar-right' : 'i-hugeicons-sidebar-left')
126
+
127
+ function applyCollapseEffects(nextCollapsed) {
128
+ if (persistKeyProp) {
129
+ try {
130
+ window.localStorage?.setItem(persistKeyProp, nextCollapsed ? 'true' : 'false')
131
+ }
132
+ catch {}
133
+ }
134
+
135
+ if (shellSelectorProp) {
136
+ document.querySelectorAll(shellSelectorProp).forEach((shell) => {
137
+ shell.style?.setProperty?.(widthVarProp, nextCollapsed && collapseModeProp === 'hidden' ? '0px' : `${widthProp}px`)
138
+ if (shell.dataset) shell.dataset.sidebarCollapsed = nextCollapsed ? 'true' : 'false'
139
+ })
140
+ }
141
+
142
+ document.documentElement.dataset.stxSidebarCollapsed = nextCollapsed ? 'true' : 'false'
143
+ if (collapsedClassProp) {
144
+ document.documentElement.classList.toggle(collapsedClassProp, nextCollapsed)
145
+ }
146
+
147
+ if (nativeMaterialCollapseProp) {
148
+ window.craft?.window?.setWebSidebarCollapsed?.(nextCollapsed).catch?.(() => {})
149
+ }
150
+ }
151
+
152
+ function setCollapsed(nextCollapsed, shouldEmit = true) {
153
+ collapsed.set(nextCollapsed)
154
+ applyCollapseEffects(nextCollapsed)
155
+ if (shouldEmit) emit('collapse', nextCollapsed)
156
+ }
106
157
 
107
158
  function onMouseEnter() {
108
- if (collapsed() && collapsibleProp) isHovered.set(true)
159
+ if (collapsed() && collapsibleProp && collapseModeProp !== 'hidden') isHovered.set(true)
109
160
  }
110
161
 
111
162
  function onMouseLeave() {
@@ -113,8 +164,7 @@ function onMouseLeave() {
113
164
  }
114
165
 
115
166
  function toggleCollapse() {
116
- collapsed.set(!collapsed())
117
- emit('collapse', collapsed())
167
+ setCollapsed(!collapsed())
118
168
  }
119
169
 
120
170
  function onSectionToggle(sectionId) {
@@ -125,22 +175,46 @@ function onItemClick(event) {
125
175
  emit('itemClick', event.detail)
126
176
  }
127
177
 
178
+ function isCraftRuntime() {
179
+ return window.__craftNativeSidebar === true
180
+ || window.craft?.__craft_bridge_loaded === true
181
+ || !!window.craft?.window
182
+ || !!window.webkit?.messageHandlers?.craft
183
+ }
184
+
128
185
  onMount(async () => {
129
- hasNativeSidebar.set(
130
- window.__craftNativeSidebar === true
131
- || window.craft?.hasNativeSidebar?.()
132
- || (window.webkit?.messageHandlers?.craft && document.body?.dataset?.nativeSidebar === 'true'),
133
- )
134
- if (window.craft?.isCraft?.() && window.craft?.components?.createSidebar) {
186
+ if (persistKeyProp) {
187
+ try {
188
+ const saved = window.localStorage?.getItem(persistKeyProp)
189
+ if (saved === 'true' || saved === 'false') collapsed.set(saved === 'true')
190
+ }
191
+ catch {}
192
+ }
193
+
194
+ applyCollapseEffects(collapsed())
195
+
196
+ if (variantProp === 'desktop' && isCraftRuntime()) {
197
+ document.documentElement.classList.add('has-stx-sidebar-material')
198
+ if (document.body?.dataset) document.body.dataset.sidebarMaterial = 'desktop'
199
+ }
200
+
201
+ hasNativeSidebar.set(isCraftRuntime() && window.craft?.hasNativeSidebar?.() === true)
202
+
203
+ const nativeSidebarApi = window.craft?.nativeUI || window.craft?.components
204
+ if (isCraftRuntime() && nativeSidebarApi?.createSidebar) {
135
205
  try {
136
- await window.craft.components.createSidebar({
206
+ const sidebar = await nativeSidebarApi.createSidebar({
137
207
  position: positionProp,
138
208
  width: widthProp,
139
209
  minWidth: minWidthProp,
210
+ collapseMode: collapseModeProp,
140
211
  collapsible: collapsibleProp,
141
212
  variant: variantProp,
142
213
  material: variantProp === 'desktop' ? 'sidebar' : undefined,
143
- backgroundEffect: variantProp === 'desktop' ? 'shimmer' : undefined,
214
+ backgroundEffect: variantProp === 'desktop' ? 'vibrancy' : undefined,
215
+ materialOpacity: materialOpacityProp,
216
+ materialDarkOpacity: materialDarkOpacityProp,
217
+ materialScheme: materialSchemeProp,
144
218
  allowsVibrancy: variantProp === 'desktop' || variantProp === 'vibrancy' || variantProp === 'tahoe',
145
219
  sections: sectionsProp.map(s => ({
146
220
  id: s.id,
@@ -148,6 +222,7 @@ onMount(async () => {
148
222
  items: s.items?.map(i => ({ id: i.id, label: i.label, icon: i.icon, href: i.href, badge: i.badge })),
149
223
  })),
150
224
  })
225
+ if (sidebar) hasNativeSidebar.set(true)
151
226
  }
152
227
  catch (err) {
153
228
  console.warn('[Sidebar] Failed to create native sidebar, using web fallback:', err)
@@ -161,7 +236,10 @@ defineExpose({ collapsed, toggle: toggleCollapse })
161
236
  <aside
162
237
  :show="!hasNativeSidebar()"
163
238
  class="{{ containerClasses }} sidebar-container"
164
- :style="`width: ${sidebarWidth()}`"
239
+ data-sidebar-variant="{{ variant }}"
240
+ data-sidebar-material-scheme="{{ materialScheme }}"
241
+ :aria-hidden="String(collapsed() && collapseModeProp === 'hidden')"
242
+ :style="`width: ${sidebarWidth()}; --stx-sidebar-material-opacity: ${materialOpacityProp}; --stx-sidebar-material-dark-opacity: ${materialDarkOpacityProp}`"
165
243
  @mouseenter="onMouseEnter()"
166
244
  @mouseleave="onMouseLeave()"
167
245
  role="navigation"
@@ -171,7 +249,7 @@ defineExpose({ collapsed, toggle: toggleCollapse })
171
249
  <div class="absolute inset-0 pointer-events-none bg-gradient-to-b from-amber-50/30 via-orange-50/20 to-stone-100/30 dark:from-neutral-800/20 dark:via-neutral-900/10 dark:to-neutral-800/20 mix-blend-overlay"></div>
172
250
  @endif
173
251
  @if(variantShimmer)
174
- <div class="absolute inset-0 pointer-events-none bg-[radial-gradient(circle_at_18%_12%,rgba(255,255,255,0.46),transparent_28%),linear-gradient(120deg,rgba(255,255,255,0.22),rgba(255,255,255,0.04)_42%,rgba(255,255,255,0.18))] dark:bg-[radial-gradient(circle_at_18%_12%,rgba(255,255,255,0.12),transparent_30%),linear-gradient(120deg,rgba(255,255,255,0.10),rgba(255,255,255,0.02)_45%,rgba(255,255,255,0.08))]"></div>
252
+ <div class="absolute inset-0 pointer-events-none bg-[linear-gradient(112deg,rgba(255,255,255,0.20)_0%,rgba(255,255,255,0.04)_45%,rgba(226,226,222,0.16)_100%)] dark:bg-[linear-gradient(112deg,rgba(255,255,255,0.08)_0%,rgba(255,255,255,0.02)_46%,rgba(255,255,255,0.06)_100%)]"></div>
175
253
  @endif
176
254
 
177
255
  @if($slots.header)
@@ -213,13 +291,15 @@ defineExpose({ collapsed, toggle: toggleCollapse })
213
291
 
214
292
  @if(collapsible)
215
293
  <button
216
- :show="showExpanded()"
217
294
  type="button"
218
295
  class="absolute top-4 {{ collapseBtnPosition }} p-1.5 rounded-lg text-stone-400 hover:text-stone-600 hover:bg-black/5 dark:hover:text-neutral-300 dark:hover:bg-white/10 transition-colors z-20"
219
296
  @click="toggleCollapse()"
220
297
  :aria-label="collapseAriaLabel()"
298
+ data-sidebar-collapse
299
+ data-stx-sidebar-collapse-button
221
300
  >
222
- <div :class="`${collapseIconClass()} w-5 h-5`"></div>
301
+ <div :show="!collapsed()" class="i-hugeicons-sidebar-left w-5 h-5"></div>
302
+ <div :show="collapsed()" class="i-hugeicons-sidebar-right w-5 h-5"></div>
223
303
  </button>
224
304
  @endif
225
305
  </aside>
@@ -229,7 +309,21 @@ defineExpose({ collapsed, toggle: toggleCollapse })
229
309
  .overflow-y-auto::-webkit-scrollbar-track { background: transparent; }
230
310
  .overflow-y-auto::-webkit-scrollbar-thumb { background-color: rgba(0, 0, 0, 0.15); border-radius: 3px; }
231
311
  .overflow-y-auto::-webkit-scrollbar-thumb:hover { background-color: rgba(0, 0, 0, 0.25); }
312
+ .sidebar-container[data-sidebar-variant="desktop"] {
313
+ background-color: rgba(246, 246, 244, var(--stx-sidebar-material-opacity, 0.78));
314
+ backdrop-filter: blur(24px) saturate(1.08);
315
+ -webkit-backdrop-filter: blur(24px) saturate(1.08);
316
+ }
317
+ html.has-native-sidebar [data-stx-native-window-controls] {
318
+ display: none;
319
+ }
320
+ html.has-native-sidebar [data-stx-sidebar-web-chrome] {
321
+ margin-left: 202px;
322
+ }
232
323
  @media (prefers-color-scheme: dark) {
324
+ .sidebar-container[data-sidebar-variant="desktop"]:not([data-sidebar-material-scheme="light"]) {
325
+ background-color: rgba(24, 24, 23, var(--stx-sidebar-material-dark-opacity, 0.8));
326
+ }
233
327
  .overflow-y-auto::-webkit-scrollbar-thumb { background-color: rgba(255, 255, 255, 0.15); }
234
328
  .overflow-y-auto::-webkit-scrollbar-thumb:hover { background-color: rgba(255, 255, 255, 0.25); }
235
329
  }
@@ -8,6 +8,8 @@ export const searchPlaceholder = $props.searchPlaceholder || 'Search...'
8
8
  export const searchValue = $props.searchValue || ''
9
9
  export const collapsed = $props.collapsed ?? false
10
10
  export const variant = $props.variant || 'tahoe'
11
+ export const showWindowControls = $props.showWindowControls ?? (variant === 'desktop' ? 'auto' : false)
12
+ export const showNavigationControls = $props.showNavigationControls ?? variant === 'desktop'
11
13
 
12
14
  const headerVariants = {
13
15
  workspace: {
@@ -19,10 +21,13 @@ const headerVariants = {
19
21
  searchInput: 'w-full rounded-[16px] border border-zinc-200/70 bg-white/70 px-10 py-2.5 text-[15px] text-zinc-900 placeholder:text-zinc-400 focus:outline-none focus:ring-2 focus:ring-zinc-300/80 dark:border-white/10 dark:bg-white/10 dark:text-white',
20
22
  },
21
23
  desktop: {
22
- titlebar: 'h-16 flex items-center justify-between px-4',
24
+ titlebar: 'h-14 flex items-center gap-5 px-5 border-b border-black/5 dark:border-white/10',
25
+ chrome: 'flex shrink-0 items-center justify-start gap-5 min-h-7',
26
+ trafficLight: 'h-3.5 w-3.5 rounded-full shadow-[inset_0_0_0_1px_rgba(0,0,0,0.08)]',
27
+ navButton: 'inline-flex h-7 w-7 items-center justify-center rounded-full text-zinc-500/80 transition-colors hover:bg-white/35 hover:text-zinc-900 disabled:opacity-35 disabled:hover:bg-transparent disabled:hover:text-zinc-500/80 dark:text-zinc-400 dark:hover:bg-white/10 dark:hover:text-white',
23
28
  logo: 'w-9 h-9 rounded-[12px] bg-black/80 text-white flex items-center justify-center font-semibold text-sm shadow-sm dark:bg-white/14',
24
- title: 'text-[17px] font-semibold text-zinc-950 dark:text-white truncate',
25
- subtitle: 'text-sm text-zinc-500 dark:text-zinc-400 truncate',
29
+ title: 'text-[15px] leading-[22px] font-medium text-zinc-950 dark:text-white truncate',
30
+ subtitle: 'text-xs text-zinc-500 dark:text-zinc-400 truncate',
26
31
  searchWrap: 'px-4 pb-4',
27
32
  searchInput: 'w-full rounded-[16px] border border-white/40 bg-white/45 px-10 py-2.5 text-[15px] text-zinc-900 placeholder:text-zinc-500 shadow-sm focus:outline-none focus:ring-2 focus:ring-white/70 dark:border-white/10 dark:bg-white/10 dark:text-white',
28
33
  },
@@ -38,24 +43,96 @@ const headerVariants = {
38
43
 
39
44
  const headerStyle = headerVariants[variant] || headerVariants.default
40
45
  export const titlebarClasses = headerStyle.titlebar
46
+ export const chromeClasses = headerStyle.chrome || ''
47
+ export const trafficLightClasses = headerStyle.trafficLight || ''
48
+ export const navButtonClasses = headerStyle.navButton || ''
41
49
  export const logoClasses = headerStyle.logo
42
50
  export const titleClasses = headerStyle.title
43
51
  export const subtitleClasses = headerStyle.subtitle
44
52
  export const searchWrapClasses = headerStyle.searchWrap
45
53
  export const searchInputClasses = headerStyle.searchInput
54
+ export const hasDesktopChrome = variant === 'desktop' && (showWindowControls || showNavigationControls)
55
+ export const windowControlsClasses = showWindowControls === 'auto' ? 'hidden items-center gap-2' : 'flex items-center gap-2'
46
56
  </script>
47
57
 
48
58
  <script client>
49
59
  const emit = defineEmits()
50
60
 
61
+ function isCraftRuntime() {
62
+ return window.__craftNativeSidebar === true
63
+ || window.craft?.__craft_bridge_loaded === true
64
+ || !!window.craft?.window
65
+ || !!window.webkit?.messageHandlers?.craft
66
+ }
67
+
68
+ function usesCustomWindowControls() {
69
+ return window.__craftCustomWindowControls === true
70
+ || document.documentElement.classList.contains('has-custom-window-controls')
71
+ || document.body?.dataset?.customWindowControls === 'true'
72
+ }
73
+
74
+ function syncWindowControls() {
75
+ document.querySelectorAll('[data-stx-native-window-controls]').forEach((element) => {
76
+ const show = element.dataset.stxNativeWindowControls === 'auto'
77
+ ? isCraftRuntime() && usesCustomWindowControls()
78
+ : true
79
+ element.classList.toggle('hidden', !show)
80
+ element.classList.toggle('flex', show)
81
+ })
82
+ }
83
+
51
84
  function onSearchInput(event) {
52
85
  emit('search', event.target.value)
53
86
  }
87
+
88
+ function goBack() {
89
+ window.history.back()
90
+ emit('back')
91
+ }
92
+
93
+ function goForward() {
94
+ window.history.forward()
95
+ emit('forward')
96
+ }
97
+
98
+ onMount(() => {
99
+ syncWindowControls()
100
+ window.addEventListener('craft:ready', syncWindowControls)
101
+ window.addEventListener('stx:load', syncWindowControls)
102
+
103
+ return () => {
104
+ window.removeEventListener('craft:ready', syncWindowControls)
105
+ window.removeEventListener('stx:load', syncWindowControls)
106
+ }
107
+ })
54
108
  </script>
55
109
 
56
110
  <div class="flex-shrink-0">
57
111
  <!-- Title bar area -->
58
112
  <div class="{{ titlebarClasses }}">
113
+ @if(hasDesktopChrome)
114
+ <div class="{{ chromeClasses }}" data-stx-sidebar-web-chrome>
115
+ @if(showWindowControls)
116
+ <div class="{{ windowControlsClasses }}" aria-hidden="true" data-stx-native-window-controls="{{ showWindowControls === 'auto' ? 'auto' : 'always' }}">
117
+ <span class="{{ trafficLightClasses }} bg-[#ff5f57]"></span>
118
+ <span class="{{ trafficLightClasses }} bg-[#ffbd2e]"></span>
119
+ <span class="{{ trafficLightClasses }} bg-[#28c840]"></span>
120
+ </div>
121
+ @endif
122
+
123
+ @if(showNavigationControls)
124
+ <div class="flex items-center gap-2">
125
+ <button type="button" class="{{ navButtonClasses }}" @click="goBack()" aria-label="Go back">
126
+ <span class="h-5 w-5 i-hugeicons-arrow-left-02" aria-hidden="true"></span>
127
+ </button>
128
+ <button type="button" class="{{ navButtonClasses }}" @click="goForward()" aria-label="Go forward">
129
+ <span class="h-5 w-5 i-hugeicons-arrow-right-02" aria-hidden="true"></span>
130
+ </button>
131
+ </div>
132
+ @endif
133
+ </div>
134
+ @endif
135
+
59
136
  @if(!collapsed)
60
137
  <div class="flex items-center gap-3 min-w-0">
61
138
  <!-- Logo -->
@@ -11,20 +11,20 @@ export const variant = $props.variant || 'tahoe'
11
11
 
12
12
  const itemVariants = {
13
13
  workspace: {
14
- base: 'flex w-full items-center gap-3 rounded-[18px] px-4 py-3 text-[17px] leading-tight transition-colors duration-150',
14
+ base: 'flex w-full items-center gap-3 rounded-[16px] px-3.5 py-2 text-[14px] leading-tight transition-colors duration-150',
15
15
  indent: '',
16
16
  active: 'bg-[#e7e7e5] text-zinc-950',
17
17
  inactive: 'text-zinc-700 hover:bg-[#ececea] hover:text-zinc-950 dark:text-zinc-300 dark:hover:bg-white/10',
18
18
  icon: active ? 'text-zinc-900 dark:text-zinc-100' : 'text-zinc-500 dark:text-zinc-500',
19
- badge: 'ml-auto rounded-full bg-white/70 px-2.5 py-0.5 text-[13px] font-medium text-zinc-500 shadow-sm dark:bg-white/10 dark:text-zinc-400',
19
+ badge: 'ml-auto grid h-5 min-w-5 place-items-center rounded-full bg-white/70 px-1.5 text-[11px] font-medium text-zinc-500 shadow-sm dark:bg-white/10 dark:text-zinc-400',
20
20
  },
21
21
  desktop: {
22
- base: 'flex w-full items-center gap-3 rounded-[16px] px-3.5 py-2.5 text-[15px] leading-tight transition-colors duration-150',
22
+ base: 'flex w-full items-center gap-3 rounded-[14px] px-3 py-1.5 text-[13.5px] leading-tight transition-colors duration-150',
23
23
  indent: '',
24
- active: 'bg-white/55 text-zinc-950 shadow-sm ring-1 ring-white/50 dark:bg-white/12 dark:text-white dark:ring-white/10',
25
- inactive: 'text-zinc-700 hover:bg-white/34 hover:text-zinc-950 dark:text-zinc-300 dark:hover:bg-white/10',
26
- icon: active ? 'text-zinc-900 dark:text-white' : 'text-zinc-500 dark:text-zinc-400',
27
- badge: 'ml-auto rounded-full bg-white/55 px-2.5 py-0.5 text-xs font-medium text-zinc-500 shadow-sm dark:bg-white/10 dark:text-zinc-400',
24
+ active: 'bg-[#e8e8e6]/90 text-zinc-950 dark:bg-white/12 dark:text-white',
25
+ inactive: 'text-zinc-700 hover:bg-white/38 hover:text-zinc-950 dark:text-zinc-300 dark:hover:bg-white/10',
26
+ icon: active ? 'text-zinc-900 dark:text-white' : 'text-zinc-600 dark:text-zinc-400',
27
+ badge: 'ml-auto grid h-5 min-w-5 place-items-center rounded-full bg-white/72 px-1.5 text-[11px] font-medium text-zinc-500 shadow-sm dark:bg-white/10 dark:text-zinc-400',
28
28
  },
29
29
  default: {
30
30
  base: 'flex items-center gap-2.5 px-2.5 py-1.5 rounded-md text-[13px] transition-all duration-150',
@@ -41,7 +41,7 @@ const baseItemList = [itemStyle.base, itemStyle.indent]
41
41
  const stateClasses = disabled ? 'opacity-50 cursor-not-allowed' : active ? itemStyle.active : itemStyle.inactive
42
42
 
43
43
  export const itemClasses = [...baseItemList, stateClasses].filter(Boolean).join(' ')
44
- export const iconClasses = `${icon} w-5 h-5 flex-shrink-0 ${itemStyle.icon}`
44
+ export const iconClasses = `${icon} h-[18px] w-[18px] flex-shrink-0 ${itemStyle.icon}`
45
45
  export const badgeClasses = itemStyle.badge
46
46
  </script>
47
47
 
@@ -14,7 +14,7 @@ const headerVariants = {
14
14
  hover: 'hover:text-zinc-600 dark:hover:text-zinc-300 cursor-pointer',
15
15
  },
16
16
  desktop: {
17
- base: 'w-full flex items-center gap-2.5 px-3.5 pb-2 pt-4 rounded-[14px] text-left transition-colors duration-150 text-[12px] font-semibold uppercase tracking-[0.10em] text-zinc-500/80 dark:text-zinc-400/80',
17
+ base: 'w-full flex items-center gap-2.5 px-3 pb-1.5 pt-3 rounded-[14px] text-left transition-colors duration-150 text-[12px] font-semibold uppercase tracking-[0.10em] text-zinc-500/80 dark:text-zinc-400/80',
18
18
  hover: 'hover:bg-white/25 dark:hover:bg-white/10 cursor-pointer',
19
19
  },
20
20
  default: {
@@ -26,7 +26,7 @@ const headerVariants = {
26
26
  const headerStyle = headerVariants[variant] || headerVariants.default
27
27
  const headerClasses = [headerStyle.base, collapsible ? headerStyle.hover : ''].filter(Boolean).join(' ')
28
28
  export const headerClassesValue = headerClasses
29
- export const sectionClasses = variant === 'workspace' || variant === 'desktop' ? 'py-1.5' : 'py-1'
29
+ export const sectionClasses = variant === 'workspace' ? 'py-1.5' : variant === 'desktop' ? 'py-1' : 'py-1'
30
30
  export const groupClasses = variant === 'workspace' || variant === 'desktop' ? 'space-y-1 overflow-hidden' : 'mt-1 space-y-0.5 overflow-hidden'
31
31
  export const labelClasses = variant === 'workspace' || variant === 'desktop'
32
32
  ? 'flex-1 truncate'