yaxa-svelte 2.0.0 → 2.0.1

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.
@@ -83,7 +83,7 @@
83
83
  />
84
84
 
85
85
  <!-- Segments -->
86
- {#each segments as seg, idx}
86
+ {#each segments as seg, idx (seg.item.label)}
87
87
  <circle
88
88
  role="graphics-symbol"
89
89
  aria-label={seg.item.label}
@@ -131,9 +131,9 @@
131
131
  <!-- Legend -->
132
132
  {#if showLegend && data.length > 0}
133
133
  <div
134
- class="mt-4 flex flex-wrap justify-center gap-x-4 gap-y-2 text-xs text-neutral-600 dark:text-neutral-300"
134
+ class="mt-4 flex flex-wrap justify-center gap-x-3 gap-y-1.5 text-[11px] text-neutral-600 sm:gap-x-4 sm:gap-y-2 sm:text-xs dark:text-neutral-300"
135
135
  >
136
- {#each segments as seg, idx}
136
+ {#each segments as seg, idx (seg.item.label)}
137
137
  <button
138
138
  type="button"
139
139
  onmouseenter={() => (hoveredIdx = idx)}
@@ -80,8 +80,22 @@
80
80
  </div>
81
81
 
82
82
  <!-- Right Section: Search, Theme Toggle, Actions, Socials -->
83
- <div class="flex items-center gap-2">
83
+ <div class="flex items-center gap-1.5 sm:gap-2">
84
84
  {#if onOpenCommand}
85
+ <!-- Mobile Search Button -->
86
+ <Button
87
+ variant="ghost"
88
+ color="neutral"
89
+ square
90
+ size="sm"
91
+ class="sm:hidden"
92
+ onclick={onOpenCommand}
93
+ aria-label="Search documentation"
94
+ >
95
+ <Icon name="search" size="sm" />
96
+ </Button>
97
+
98
+ <!-- Desktop Search Pill -->
85
99
  <button
86
100
  onclick={onOpenCommand}
87
101
  type="button"
@@ -110,7 +124,7 @@
110
124
  {/if}
111
125
  </Button>
112
126
 
113
- <!-- GitHub Link -->
127
+ <!-- GitHub Link (Desktop) -->
114
128
  {#if currentConfig.socials?.github}
115
129
  <Button
116
130
  href={currentConfig.socials.github}
@@ -118,13 +132,14 @@
118
132
  color="neutral"
119
133
  square
120
134
  size="sm"
135
+ class="hidden sm:inline-flex"
121
136
  aria-label="GitHub Repository"
122
137
  >
123
138
  <Icon name="github" size="sm" />
124
139
  </Button>
125
140
  {/if}
126
141
 
127
- <!-- npm Link -->
142
+ <!-- npm Link (Desktop) -->
128
143
  {#if currentConfig.socials?.npm}
129
144
  <Button
130
145
  href={currentConfig.socials.npm}
@@ -132,6 +147,7 @@
132
147
  color="neutral"
133
148
  square
134
149
  size="sm"
150
+ class="hidden sm:inline-flex"
135
151
  aria-label="npm Package"
136
152
  >
137
153
  <Icon name="npm" size="sm" />
@@ -173,17 +189,61 @@
173
189
  <!-- Mobile Navigation Dropdown -->
174
190
  {#if mobileMenuOpen}
175
191
  <div class="border-t border-neutral-200 py-4 md:hidden dark:border-neutral-800">
176
- <div class="flex flex-col space-y-2">
192
+ <div class="flex flex-col space-y-1">
177
193
  {#each resolvedLinks as item (item.href)}
178
194
  <a
179
195
  href={item.href}
180
196
  onclick={() => (mobileMenuOpen = false)}
181
- class="rounded-lg px-3 py-2 text-base font-medium text-neutral-700 hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
197
+ class="flex items-center justify-between rounded-lg px-3 py-2 text-base font-medium text-neutral-700 hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
182
198
  >
183
- {item.label}
199
+ <span class="flex items-center gap-2">
200
+ {#if item.icon}
201
+ <Icon name={item.icon} size="xs" />
202
+ {/if}
203
+ {item.label}
204
+ </span>
205
+ {#if item.badge}
206
+ <span
207
+ class="rounded bg-primary-100 px-1.5 py-0.5 text-xs font-semibold text-primary-700 dark:bg-primary-950 dark:text-primary-300"
208
+ >
209
+ {item.badge}
210
+ </span>
211
+ {/if}
184
212
  </a>
185
213
  {/each}
186
214
  </div>
215
+
216
+ <!-- Mobile Menu Socials -->
217
+ {#if currentConfig.socials?.github || currentConfig.socials?.npm}
218
+ <div
219
+ class="mt-4 flex items-center gap-2 border-t border-neutral-200 pt-4 dark:border-neutral-800"
220
+ >
221
+ {#if currentConfig.socials?.github}
222
+ <Button
223
+ href={currentConfig.socials.github}
224
+ variant="outline"
225
+ size="sm"
226
+ class="flex-1 justify-center"
227
+ aria-label="GitHub Repository"
228
+ >
229
+ <Icon name="github" size="xs" class="mr-1.5" />
230
+ GitHub
231
+ </Button>
232
+ {/if}
233
+ {#if currentConfig.socials?.npm}
234
+ <Button
235
+ href={currentConfig.socials.npm}
236
+ variant="outline"
237
+ size="sm"
238
+ class="flex-1 justify-center"
239
+ aria-label="npm Package"
240
+ >
241
+ <Icon name="npm" size="xs" class="mr-1.5" />
242
+ npm
243
+ </Button>
244
+ {/if}
245
+ </div>
246
+ {/if}
187
247
  </div>
188
248
  {/if}
189
249
  </Container>
@@ -79,7 +79,7 @@
79
79
  bind:this={listElement}
80
80
  data-slot="list"
81
81
  class={cn(
82
- 'relative flex',
82
+ 'relative scrollbar-none flex max-w-full overflow-x-auto',
83
83
  variant === 'segmented' &&
84
84
  'rounded-xl border border-neutral-200/60 bg-neutral-100 p-1 dark:border-neutral-800/60 dark:bg-neutral-900',
85
85
  variant === 'underline' && 'gap-6 border-b border-neutral-200 dark:border-neutral-800',
@@ -111,7 +111,7 @@
111
111
  disabled={tab.disabled}
112
112
  onclick={() => (value = tab.value)}
113
113
  class={cn(
114
- 'relative z-10 inline-flex items-center justify-center gap-2 text-sm font-medium transition-all duration-150 select-none focus-visible:ring-2 focus-visible:ring-[var(--yaxa-ring)] focus-visible:outline-none motion-reduce:transition-none',
114
+ 'relative z-10 inline-flex shrink-0 items-center justify-center gap-2 text-sm font-medium whitespace-nowrap transition-all duration-150 select-none focus-visible:ring-2 focus-visible:ring-(--yaxa-ring) focus-visible:outline-none motion-reduce:transition-none',
115
115
  tab.disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer',
116
116
  variant === 'segmented' && [
117
117
  'rounded-lg px-3 py-1.5',
@@ -3,7 +3,7 @@
3
3
  import type { Snippet } from 'svelte';
4
4
 
5
5
  export const modalVariants = tv({
6
- base: 'fixed left-1/2 top-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 rounded-2xl border border-neutral-200 bg-white p-6 shadow-2xl duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 dark:border-neutral-800 dark:bg-neutral-900 yaxa-surface-elevated motion-reduce:transition-none',
6
+ base: 'fixed left-1/2 top-1/2 z-50 w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 rounded-2xl border border-neutral-200 bg-white p-4 sm:p-6 shadow-2xl duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 dark:border-neutral-800 dark:bg-neutral-900 yaxa-surface-elevated motion-reduce:transition-none',
7
7
  variants: {
8
8
  size: {
9
9
  sm: 'max-w-sm',
@@ -8,7 +8,7 @@ export declare const modalVariants: import("tailwind-variants").TVReturnType<{
8
8
  xl: "max-w-4xl";
9
9
  full: "max-w-[calc(100vw-2rem)] h-[calc(100vh-2rem)]";
10
10
  };
11
- }, undefined, "fixed left-1/2 top-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 rounded-2xl border border-neutral-200 bg-white p-6 shadow-2xl duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 dark:border-neutral-800 dark:bg-neutral-900 yaxa-surface-elevated motion-reduce:transition-none", {
11
+ }, undefined, "fixed left-1/2 top-1/2 z-50 w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 rounded-2xl border border-neutral-200 bg-white p-4 sm:p-6 shadow-2xl duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 dark:border-neutral-800 dark:bg-neutral-900 yaxa-surface-elevated motion-reduce:transition-none", {
12
12
  size: {
13
13
  sm: "max-w-sm";
14
14
  md: "max-w-lg";
@@ -91,20 +91,23 @@
91
91
  {#if showHeader}
92
92
  <!-- Top Bar -->
93
93
  <div
94
- class="flex flex-wrap items-center justify-between gap-4 rounded-2xl border border-neutral-200 bg-white p-6 shadow-sm dark:border-neutral-800 dark:bg-neutral-900"
94
+ class="flex flex-wrap items-center justify-between gap-4 rounded-2xl border border-neutral-200 bg-white p-4 shadow-sm sm:p-6 dark:border-neutral-800 dark:bg-neutral-900"
95
95
  >
96
- <div>
97
- <h1 class="text-xl font-bold text-neutral-900 dark:text-white">Visual Web Theme Studio</h1>
96
+ <div class="min-w-0 flex-1">
97
+ <h1 class="text-lg font-bold text-neutral-900 sm:text-xl dark:text-white">
98
+ Visual Web Theme Studio
99
+ </h1>
98
100
  <p class="mt-1 text-xs text-neutral-500">
99
101
  Visually customize palettes, harmonic radii, fonts, and scrollbars with instant live
100
102
  preview and zero FOUC.
101
103
  </p>
102
104
  </div>
103
105
 
104
- <div class="flex items-center gap-2.5">
106
+ <div class="flex w-full flex-wrap items-center gap-2 sm:w-auto">
105
107
  <Button
106
108
  variant="outline"
107
109
  size="sm"
110
+ class="flex-1 sm:flex-initial"
108
111
  onclick={() => {
109
112
  const chosen = theme.randomize();
110
113
  toast.info(
@@ -117,22 +120,33 @@
117
120
  Randomize
118
121
  </Button>
119
122
 
120
- <Button variant="outline" size="sm" onclick={() => theme.reset()}>
123
+ <Button
124
+ variant="outline"
125
+ size="sm"
126
+ class="flex-1 sm:flex-initial"
127
+ onclick={() => theme.reset()}
128
+ >
121
129
  <Icon name="rotate-ccw" size="xs" class="mr-1.5" />
122
130
  Reset
123
131
  </Button>
124
132
 
125
- <Button variant="solid" size="sm" onclick={() => (exportModalOpen = true)}>
133
+ <Button
134
+ variant="solid"
135
+ size="sm"
136
+ class="w-full sm:w-auto"
137
+ onclick={() => (exportModalOpen = true)}
138
+ >
126
139
  <Icon name="download" size="xs" class="mr-1.5" />
127
140
  Export Theme Tokens
128
141
  </Button>
129
142
  </div>
130
143
  </div>
131
144
  {:else}
132
- <div class="flex items-center justify-end gap-2.5">
145
+ <div class="flex w-full flex-wrap items-center justify-end gap-2 sm:w-auto">
133
146
  <Button
134
147
  variant="outline"
135
148
  size="sm"
149
+ class="flex-1 sm:flex-initial"
136
150
  onclick={() => {
137
151
  const chosen = theme.randomize();
138
152
  toast.info(
@@ -145,12 +159,22 @@
145
159
  Randomize
146
160
  </Button>
147
161
 
148
- <Button variant="outline" size="sm" onclick={() => theme.reset()}>
162
+ <Button
163
+ variant="outline"
164
+ size="sm"
165
+ class="flex-1 sm:flex-initial"
166
+ onclick={() => theme.reset()}
167
+ >
149
168
  <Icon name="rotate-ccw" size="xs" class="mr-1.5" />
150
169
  Reset
151
170
  </Button>
152
171
 
153
- <Button variant="solid" size="sm" onclick={() => (exportModalOpen = true)}>
172
+ <Button
173
+ variant="solid"
174
+ size="sm"
175
+ class="w-full sm:w-auto"
176
+ onclick={() => (exportModalOpen = true)}
177
+ >
154
178
  <Icon name="download" size="xs" class="mr-1.5" />
155
179
  Export Theme Tokens
156
180
  </Button>
@@ -167,12 +191,12 @@
167
191
  Color Mode
168
192
  </div>
169
193
  <div class="grid grid-cols-3 gap-1.5">
170
- {#each ['light', 'dark', 'system'] as const as mode}
194
+ {#each ['light', 'dark', 'system'] as const as mode (mode)}
171
195
  <Button
172
196
  variant={theme.mode === mode ? 'solid' : 'outline'}
173
197
  size="xs"
174
198
  onclick={() => theme.setMode(mode)}
175
- class="w-full justify-center px-1.5 py-1 text-[11px] capitalize"
199
+ class="min-h-9 w-full justify-center px-1.5 py-1 text-[11px] capitalize"
176
200
  >
177
201
  <Icon
178
202
  name={mode === 'light' ? 'sun' : mode === 'dark' ? 'moon' : 'laptop'}
@@ -199,7 +223,7 @@
199
223
  </span>
200
224
  </div>
201
225
  <div class="grid grid-cols-4 gap-1.5">
202
- {#each Object.entries(ACCENT_PALETTES) as [key, pal]}
226
+ {#each Object.entries(ACCENT_PALETTES) as [key, pal] (key)}
203
227
  <button
204
228
  type="button"
205
229
  onclick={() => theme.setAccent(key as AccentName)}
@@ -234,7 +258,7 @@
234
258
  </span>
235
259
  </div>
236
260
  <div class="grid grid-cols-2 gap-2">
237
- {#each Object.entries(NEUTRAL_PALETTES) as [key, pal]}
261
+ {#each Object.entries(NEUTRAL_PALETTES) as [key, pal] (key)}
238
262
  {@const active = theme.neutral === key}
239
263
  <button
240
264
  type="button"
@@ -284,12 +308,12 @@
284
308
  <span class="text-xs font-semibold text-primary-500 capitalize">{theme.radius}</span>
285
309
  </div>
286
310
  <div class="grid grid-cols-5 gap-1">
287
- {#each Object.entries(RADIUS_PRESETS) as [key, r]}
311
+ {#each Object.entries(RADIUS_PRESETS) as [key, r] (key)}
288
312
  {@const active = theme.radius === key}
289
313
  <button
290
314
  type="button"
291
315
  onclick={() => theme.setRadius(key as RadiusPreset)}
292
- class="border px-1 py-1.5 text-center text-[10px] font-semibold transition-all {active
316
+ class="min-h-9 min-w-0 border px-1 py-1.5 text-center text-[10px] font-semibold transition-all sm:text-xs {active
293
317
  ? 'border-primary-500 bg-primary-500 font-bold text-white shadow-xs'
294
318
  : 'border-neutral-200 bg-white text-neutral-700 hover:bg-neutral-100 dark:border-neutral-800 dark:bg-neutral-800 dark:text-neutral-300 dark:hover:bg-neutral-700'}"
295
319
  style="border-radius: {r.value} !important;"
@@ -306,12 +330,12 @@
306
330
  Typography & Sizing
307
331
  </div>
308
332
  <div class="grid grid-cols-3 gap-1">
309
- {#each Object.entries(FONT_PRESETS) as [key, font]}
333
+ {#each Object.entries(FONT_PRESETS) as [key, font] (key)}
310
334
  {@const active = theme.fontFamily === key}
311
335
  <button
312
336
  type="button"
313
337
  onclick={() => theme.setFontFamily(key as FontFamily)}
314
- class="rounded-md border px-1 py-1.5 text-center text-[11px] font-semibold capitalize transition-all {active
338
+ class="min-h-9 rounded-md border px-1 py-1.5 text-center text-[11px] font-semibold capitalize transition-all {active
315
339
  ? 'border-primary-500 bg-primary-500 text-white shadow-xs'
316
340
  : 'border-neutral-200 bg-white text-neutral-700 hover:bg-neutral-100 dark:border-neutral-800 dark:bg-neutral-800 dark:text-neutral-300 dark:hover:bg-neutral-700'}"
317
341
  style="font-family: {font.value} !important;"
@@ -326,12 +350,12 @@
326
350
  Density / Size Scale
327
351
  </div>
328
352
  <div class="grid grid-cols-3 gap-1">
329
- {#each Object.entries(FONT_SIZE_PRESETS) as [key, sz]}
353
+ {#each Object.entries(FONT_SIZE_PRESETS) as [key, sz] (key)}
330
354
  <Button
331
355
  variant={theme.fontSize === key ? 'solid' : 'outline'}
332
356
  size="xs"
333
357
  onclick={() => theme.setFontSize(key as BaseFontSize)}
334
- class="w-full justify-center px-1 py-1 text-[11px]"
358
+ class="min-h-8.5 w-full min-w-0 justify-center px-0.5 py-1 text-[10px] sm:px-1 sm:text-[11px]"
335
359
  >
336
360
  <span class="truncate">{sz.name}</span>
337
361
  </Button>
@@ -342,14 +366,17 @@
342
366
 
343
367
  <!-- Scrollbar Auto-Alignment -->
344
368
  <Card padding="sm" class="space-y-2">
345
- <div class="flex items-center justify-between">
346
- <div>
369
+ <div class="flex items-center justify-between gap-3">
370
+ <div class="min-w-0 flex-1">
347
371
  <div class="text-xs font-bold text-neutral-900 dark:text-white">Accent Scrollbars</div>
348
- <div class="text-[11px] text-neutral-500">Sync scrollbar thumb to active accent</div>
372
+ <div class="truncate text-[11px] text-neutral-500 sm:whitespace-normal">
373
+ Sync scrollbar thumb to active accent
374
+ </div>
349
375
  </div>
350
376
  <Button
351
377
  variant={theme.accentScrollbar ? 'solid' : 'outline'}
352
378
  size="xs"
379
+ class="shrink-0"
353
380
  onclick={() => theme.setAccentScrollbar(!theme.accentScrollbar)}
354
381
  >
355
382
  {theme.accentScrollbar ? 'Enabled' : 'Disabled'}
@@ -361,10 +388,10 @@
361
388
  <!-- Right Live Sandbox Canvas (7 cols on xl, 8 cols on 2xl) -->
362
389
  <div class="space-y-6 xl:col-span-7 2xl:col-span-8">
363
390
  <!-- Elements Preview Card -->
364
- <Card>
391
+ <Card ui={{ header: 'p-4 sm:p-6', body: 'p-4 sm:p-6 space-y-6' }}>
365
392
  {#snippet header()}
366
393
  <div class="flex items-center justify-between">
367
- <span class="font-semibold text-neutral-900 dark:text-white">
394
+ <span class="text-sm font-semibold text-neutral-900 sm:text-base dark:text-white">
368
395
  Interactive Component Sandbox
369
396
  </span>
370
397
  <Badge variant="soft" color="primary">Live Preview</Badge>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaxa-svelte",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "The Intuitive Svelte UI Library — Nuxt UI v4 equivalent for SvelteKit 2 & 3 & Svelte 5 with automated SEO, dynamic OpenGraph cards, sitemaps, robots.txt, and Tailwind CSS v4.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://yaxa.vercel.app",