@nqmcreative/ui 0.4.0 → 0.4.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.
- package/README.md +17 -19
- package/dist/core/calendar.d.ts +1 -1
- package/dist/core/calendar.js +1 -1
- package/dist/core/date.d.ts +3 -3
- package/dist/core/date.js +1 -1
- package/dist/core/files.d.ts +2 -3
- package/dist/core/files.js +2 -3
- package/dist/core/index.d.ts +2 -4
- package/dist/core/index.js +2 -4
- package/dist/core/password.d.ts +1 -1
- package/dist/core/password.js +1 -1
- package/dist/core/tones.d.ts +10 -0
- package/dist/core/tones.js +19 -0
- package/dist/core/trigger.d.ts +8 -0
- package/dist/core/trigger.js +11 -0
- package/dist/styles/matte/Alert.svelte +2 -4
- package/dist/styles/matte/Avatar.svelte +16 -3
- package/dist/styles/matte/Breadcrumb.svelte +1 -4
- package/dist/styles/matte/Button.svelte +6 -2
- package/dist/styles/matte/Calendar.svelte +6 -9
- package/dist/styles/matte/Checkbox.svelte +49 -30
- package/dist/styles/matte/CheckboxGroup.svelte +15 -4
- package/dist/styles/matte/ColorInput.svelte +1 -4
- package/dist/styles/matte/Combobox.svelte +14 -8
- package/dist/styles/matte/CommandPalette.svelte +3 -6
- package/dist/styles/matte/ConfirmDialog.svelte +11 -6
- package/dist/styles/matte/ContextMenu.svelte +1 -4
- package/dist/styles/matte/CurrencyInput.svelte +1 -1
- package/dist/styles/matte/CurrencyInput.svelte.d.ts +1 -1
- package/dist/styles/matte/DatePicker.svelte +18 -11
- package/dist/styles/matte/DatePicker.svelte.d.ts +3 -0
- package/dist/styles/matte/Divider.svelte +1 -1
- package/dist/styles/matte/Drawer.svelte +11 -5
- package/dist/styles/matte/Dropdown.svelte +2 -5
- package/dist/styles/matte/Dropdown.svelte.d.ts +1 -1
- package/dist/styles/matte/Dropzone.svelte +9 -12
- package/dist/styles/matte/Dropzone.svelte.d.ts +1 -1
- package/dist/styles/matte/Field.svelte +59 -3
- package/dist/styles/matte/FileInput.svelte +11 -14
- package/dist/styles/matte/FileInput.svelte.d.ts +2 -2
- package/dist/styles/matte/Footer.svelte +15 -4
- package/dist/styles/matte/Footer.svelte.d.ts +1 -1
- package/dist/styles/matte/Input.svelte +9 -2
- package/dist/styles/matte/Label.svelte +3 -1
- package/dist/styles/matte/Link.svelte +13 -2
- package/dist/styles/matte/MenuItem.svelte +11 -4
- package/dist/styles/matte/Modal.svelte +11 -5
- package/dist/styles/matte/MultiSelect.svelte +5 -8
- package/dist/styles/matte/Navbar.svelte +5 -11
- package/dist/styles/matte/Pagination.svelte +3 -6
- package/dist/styles/matte/PinInput.svelte +1 -4
- package/dist/styles/matte/Radio.svelte +41 -22
- package/dist/styles/matte/RadioGroup.svelte +15 -4
- package/dist/styles/matte/SearchInput.svelte +1 -4
- package/dist/styles/matte/Select.svelte +4 -2
- package/dist/styles/matte/Sidebar.svelte +3 -6
- package/dist/styles/matte/Skeleton.svelte +2 -1
- package/dist/styles/matte/Spinner.svelte +2 -5
- package/dist/styles/matte/Spinner.svelte.d.ts +1 -1
- package/dist/styles/matte/Stat.svelte +27 -3
- package/dist/styles/matte/Switch.svelte +6 -1
- package/dist/styles/matte/Table.svelte +5 -8
- package/dist/styles/matte/Tabs.svelte +1 -1
- package/dist/styles/matte/TagsInput.svelte +5 -8
- package/dist/styles/matte/Textarea.svelte +4 -2
- package/dist/styles/matte/ThemeToggle.svelte +5 -8
- package/dist/styles/matte/TimeInput.svelte +2 -5
- package/dist/styles/matte/Toaster.svelte +23 -8
- package/dist/styles/matte/Tooltip.svelte +8 -1
- package/dist/styles/matte/index.d.ts +2 -3
- package/dist/styles/matte/index.js +1 -3
- package/dist/styles/matte/theme.css +21 -0
- package/dist/styles/paper/Alert.svelte +3 -5
- package/dist/styles/paper/Avatar.svelte +14 -3
- package/dist/styles/paper/Breadcrumb.svelte +1 -4
- package/dist/styles/paper/Button.svelte +5 -1
- package/dist/styles/paper/Calendar.svelte +6 -9
- package/dist/styles/paper/Card.svelte +1 -1
- package/dist/styles/paper/Checkbox.svelte +55 -36
- package/dist/styles/paper/CheckboxGroup.svelte +15 -4
- package/dist/styles/paper/ColorInput.svelte +1 -4
- package/dist/styles/paper/Combobox.svelte +14 -8
- package/dist/styles/paper/CommandPalette.svelte +3 -6
- package/dist/styles/paper/ConfirmDialog.svelte +9 -6
- package/dist/styles/paper/ContextMenu.svelte +1 -4
- package/dist/styles/paper/CurrencyInput.svelte +1 -1
- package/dist/styles/paper/CurrencyInput.svelte.d.ts +1 -1
- package/dist/styles/paper/DatePicker.svelte +18 -11
- package/dist/styles/paper/DatePicker.svelte.d.ts +3 -0
- package/dist/styles/paper/Divider.svelte +1 -1
- package/dist/styles/paper/Drawer.svelte +9 -5
- package/dist/styles/paper/Dropdown.svelte +2 -5
- package/dist/styles/paper/Dropdown.svelte.d.ts +1 -1
- package/dist/styles/paper/Dropzone.svelte +9 -12
- package/dist/styles/paper/Dropzone.svelte.d.ts +1 -1
- package/dist/styles/paper/Field.svelte +59 -3
- package/dist/styles/paper/FileInput.svelte +11 -14
- package/dist/styles/paper/FileInput.svelte.d.ts +2 -2
- package/dist/styles/paper/Footer.svelte +15 -4
- package/dist/styles/paper/Footer.svelte.d.ts +1 -1
- package/dist/styles/paper/Input.svelte +9 -2
- package/dist/styles/paper/Label.svelte +3 -1
- package/dist/styles/paper/Link.svelte +13 -2
- package/dist/styles/paper/MenuItem.svelte +11 -4
- package/dist/styles/paper/Modal.svelte +9 -5
- package/dist/styles/paper/MultiSelect.svelte +5 -8
- package/dist/styles/paper/Navbar.svelte +5 -11
- package/dist/styles/paper/Pagination.svelte +3 -6
- package/dist/styles/paper/PinInput.svelte +1 -4
- package/dist/styles/paper/Radio.svelte +41 -22
- package/dist/styles/paper/RadioGroup.svelte +15 -4
- package/dist/styles/paper/SearchInput.svelte +1 -4
- package/dist/styles/paper/SegmentedControl.svelte +2 -2
- package/dist/styles/paper/Select.svelte +4 -2
- package/dist/styles/paper/Sidebar.svelte +3 -6
- package/dist/styles/paper/Skeleton.svelte +2 -1
- package/dist/styles/paper/Spinner.svelte +2 -5
- package/dist/styles/paper/Spinner.svelte.d.ts +1 -1
- package/dist/styles/paper/Stat.svelte +24 -2
- package/dist/styles/paper/Switch.svelte +6 -1
- package/dist/styles/paper/Table.svelte +5 -8
- package/dist/styles/paper/Tabs.svelte +1 -1
- package/dist/styles/paper/TagsInput.svelte +5 -8
- package/dist/styles/paper/Textarea.svelte +4 -2
- package/dist/styles/paper/ThemeToggle.svelte +5 -8
- package/dist/styles/paper/TimeInput.svelte +2 -5
- package/dist/styles/paper/Toaster.svelte +22 -9
- package/dist/styles/paper/Tooltip.svelte +8 -1
- package/dist/styles/paper/index.d.ts +2 -3
- package/dist/styles/paper/index.js +1 -3
- package/dist/styles/paper/theme.css +21 -0
- package/dist/styles/sprout/Alert.svelte +4 -6
- package/dist/styles/sprout/Avatar.svelte +14 -3
- package/dist/styles/sprout/Breadcrumb.svelte +2 -5
- package/dist/styles/sprout/Button.svelte +8 -4
- package/dist/styles/sprout/Calendar.svelte +7 -10
- package/dist/styles/sprout/Card.svelte +2 -2
- package/dist/styles/sprout/Checkbox.svelte +55 -36
- package/dist/styles/sprout/CheckboxGroup.svelte +15 -4
- package/dist/styles/sprout/ColorInput.svelte +2 -5
- package/dist/styles/sprout/Combobox.svelte +15 -9
- package/dist/styles/sprout/CommandPalette.svelte +3 -6
- package/dist/styles/sprout/ConfirmDialog.svelte +9 -6
- package/dist/styles/sprout/ContextMenu.svelte +1 -4
- package/dist/styles/sprout/CurrencyInput.svelte +1 -1
- package/dist/styles/sprout/CurrencyInput.svelte.d.ts +1 -1
- package/dist/styles/sprout/DatePicker.svelte +20 -13
- package/dist/styles/sprout/DatePicker.svelte.d.ts +3 -0
- package/dist/styles/sprout/Divider.svelte +1 -1
- package/dist/styles/sprout/Drawer.svelte +9 -5
- package/dist/styles/sprout/Dropdown.svelte +2 -5
- package/dist/styles/sprout/Dropdown.svelte.d.ts +1 -1
- package/dist/styles/sprout/Dropzone.svelte +10 -13
- package/dist/styles/sprout/Dropzone.svelte.d.ts +1 -1
- package/dist/styles/sprout/Field.svelte +59 -3
- package/dist/styles/sprout/FileInput.svelte +14 -17
- package/dist/styles/sprout/FileInput.svelte.d.ts +2 -2
- package/dist/styles/sprout/Footer.svelte +15 -4
- package/dist/styles/sprout/Footer.svelte.d.ts +1 -1
- package/dist/styles/sprout/Input.svelte +9 -2
- package/dist/styles/sprout/Label.svelte +3 -1
- package/dist/styles/sprout/Link.svelte +13 -2
- package/dist/styles/sprout/LogoCloud.svelte +1 -1
- package/dist/styles/sprout/MenuItem.svelte +11 -4
- package/dist/styles/sprout/Modal.svelte +9 -5
- package/dist/styles/sprout/MultiSelect.svelte +8 -11
- package/dist/styles/sprout/Navbar.svelte +5 -11
- package/dist/styles/sprout/Pagination.svelte +3 -6
- package/dist/styles/sprout/PinInput.svelte +1 -4
- package/dist/styles/sprout/Radio.svelte +41 -22
- package/dist/styles/sprout/RadioGroup.svelte +15 -4
- package/dist/styles/sprout/SearchInput.svelte +2 -5
- package/dist/styles/sprout/SegmentedControl.svelte +2 -2
- package/dist/styles/sprout/Select.svelte +4 -2
- package/dist/styles/sprout/Sidebar.svelte +5 -7
- package/dist/styles/sprout/Skeleton.svelte +2 -1
- package/dist/styles/sprout/Spinner.svelte +2 -5
- package/dist/styles/sprout/Spinner.svelte.d.ts +1 -1
- package/dist/styles/sprout/Stat.svelte +24 -2
- package/dist/styles/sprout/Switch.svelte +6 -1
- package/dist/styles/sprout/Table.svelte +6 -9
- package/dist/styles/sprout/Tabs.svelte +1 -1
- package/dist/styles/sprout/TagsInput.svelte +6 -9
- package/dist/styles/sprout/Textarea.svelte +4 -2
- package/dist/styles/sprout/ThemeToggle.svelte +5 -8
- package/dist/styles/sprout/TimeInput.svelte +3 -6
- package/dist/styles/sprout/Toaster.svelte +25 -12
- package/dist/styles/sprout/Tooltip.svelte +8 -1
- package/dist/styles/sprout/index.d.ts +3 -4
- package/dist/styles/sprout/index.js +2 -4
- package/dist/styles/sprout/lift.d.ts +14 -0
- package/dist/styles/sprout/lift.js +23 -0
- package/dist/styles/sprout/theme.css +50 -24
- package/package.json +2 -19
- package/registry.json +7 -46
- package/dist/core/locale.svelte.d.ts +0 -101
- package/dist/core/locale.svelte.js +0 -167
- package/dist/styles/matte/LocaleProvider.svelte +0 -24
- package/dist/styles/matte/LocaleProvider.svelte.d.ts +0 -10
- package/dist/styles/paper/LocaleProvider.svelte +0 -24
- package/dist/styles/paper/LocaleProvider.svelte.d.ts +0 -10
- package/dist/styles/sprout/LocaleProvider.svelte +0 -24
- package/dist/styles/sprout/LocaleProvider.svelte.d.ts +0 -10
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import { iconLg } from './icon.js';
|
|
4
4
|
import type { HTMLDialogAttributes } from 'svelte/elements';
|
|
5
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
6
5
|
import { isBackdropClick, syncDialog } from '../../core/dialog.svelte.js';
|
|
7
6
|
import { float } from './lift.js';
|
|
8
7
|
|
|
@@ -41,7 +40,8 @@
|
|
|
41
40
|
...rest
|
|
42
41
|
}: Props = $props();
|
|
43
42
|
|
|
44
|
-
const
|
|
43
|
+
const uid = $props.id();
|
|
44
|
+
|
|
45
45
|
let dialog: HTMLDialogElement | null = $state(null);
|
|
46
46
|
|
|
47
47
|
const closable = $derived(showClose ?? dismissible);
|
|
@@ -67,6 +67,8 @@
|
|
|
67
67
|
|
|
68
68
|
<dialog
|
|
69
69
|
bind:this={dialog}
|
|
70
|
+
aria-labelledby={title ? `${uid}-title` : undefined}
|
|
71
|
+
aria-describedby={description ? `${uid}-description` : undefined}
|
|
70
72
|
onclose={close}
|
|
71
73
|
onclick={onBackdrop}
|
|
72
74
|
oncancel={(event) => {
|
|
@@ -83,17 +85,19 @@
|
|
|
83
85
|
{#if icon}<span class={iconLg}>{@render icon()}</span>{/if}
|
|
84
86
|
<div class="flex min-w-0 flex-1 flex-col gap-1">
|
|
85
87
|
{#if title}
|
|
86
|
-
<h2 class="font-heading text-base font-semibold text-text">{title}</h2>
|
|
88
|
+
<h2 id="{uid}-title" class="font-heading text-base font-semibold text-text">{title}</h2>
|
|
87
89
|
{/if}
|
|
88
90
|
{#if description}
|
|
89
|
-
<p class="font-sans text-[13px] text-text-muted">
|
|
91
|
+
<p id="{uid}-description" class="font-sans text-[13px] text-text-muted">
|
|
92
|
+
{description}
|
|
93
|
+
</p>
|
|
90
94
|
{/if}
|
|
91
95
|
</div>
|
|
92
96
|
{#if closable}
|
|
93
97
|
<button
|
|
94
98
|
type="button"
|
|
95
99
|
onclick={close}
|
|
96
|
-
aria-label=
|
|
100
|
+
aria-label="Close"
|
|
97
101
|
class="-m-1 shrink-0 rounded-xl p-1 text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand"
|
|
98
102
|
>
|
|
99
103
|
<svg class="size-4" viewBox="0 0 14 14" fill="none" aria-hidden="true">
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
import { anchored } from '../../core/actions/anchor.js';
|
|
17
17
|
import { clickOutside, portal } from '../../core/actions/dismissable.js';
|
|
18
18
|
import { ListCursor, groupItems, matchQuery, revealIndex } from '../../core/list.svelte.js';
|
|
19
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
20
19
|
import { iconMd, iconSm } from './icon.js';
|
|
21
20
|
import { toneFocusWithinBorder, toneSoft, toneText, type Tone } from '../../core/tones.js';
|
|
22
21
|
import { edge, soft } from './lift.js';
|
|
@@ -59,8 +58,6 @@
|
|
|
59
58
|
class: className = ''
|
|
60
59
|
}: Props = $props();
|
|
61
60
|
|
|
62
|
-
const t = useLocale();
|
|
63
|
-
|
|
64
61
|
let open = $state(false);
|
|
65
62
|
let query = $state('');
|
|
66
63
|
let wrapper: HTMLElement | null = $state(null);
|
|
@@ -150,7 +147,7 @@
|
|
|
150
147
|
class="inline-flex items-center rounded-xl px-2 py-0.5 text-xs font-medium {toneSoft[tone]}"
|
|
151
148
|
>
|
|
152
149
|
{chosen.length}
|
|
153
|
-
|
|
150
|
+
selected
|
|
154
151
|
</span>
|
|
155
152
|
{:else}
|
|
156
153
|
{#each chosen as option (option.value)}
|
|
@@ -163,8 +160,8 @@
|
|
|
163
160
|
<button
|
|
164
161
|
type="button"
|
|
165
162
|
onclick={() => remove(option)}
|
|
166
|
-
aria-label="
|
|
167
|
-
class="inline-flex size-4 items-center justify-center rounded transition-colors duration-150 hover:bg-bg/70 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-current"
|
|
163
|
+
aria-label="Remove {option.label}"
|
|
164
|
+
class="inline-flex size-4 items-center justify-center rounded-full transition-colors duration-150 hover:bg-bg/70 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-current"
|
|
168
165
|
>
|
|
169
166
|
<svg class="size-2.5" viewBox="0 0 14 14" fill="none" aria-hidden="true">
|
|
170
167
|
<path
|
|
@@ -190,7 +187,7 @@
|
|
|
190
187
|
aria-expanded={open}
|
|
191
188
|
aria-controls="{id ?? 'multiselect'}-listbox"
|
|
192
189
|
aria-invalid={invalid ? 'true' : undefined}
|
|
193
|
-
placeholder={chosen.length ? '' : (placeholder ??
|
|
190
|
+
placeholder={chosen.length ? '' : (placeholder ?? 'Search…')}
|
|
194
191
|
oninput={() => {
|
|
195
192
|
open = true;
|
|
196
193
|
cursor.index = 0;
|
|
@@ -212,8 +209,8 @@
|
|
|
212
209
|
onchange?.([]);
|
|
213
210
|
inputEl?.focus();
|
|
214
211
|
}}
|
|
215
|
-
aria-label=
|
|
216
|
-
class="shrink-0 rounded p-1 text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
|
|
212
|
+
aria-label="Clear selection"
|
|
213
|
+
class="shrink-0 rounded-xl p-1 text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
|
|
217
214
|
>
|
|
218
215
|
<svg class="size-3.5" viewBox="0 0 14 14" fill="none" aria-hidden="true">
|
|
219
216
|
<path
|
|
@@ -240,7 +237,7 @@
|
|
|
240
237
|
>
|
|
241
238
|
{#if flat.length === 0}
|
|
242
239
|
<p class="px-3 py-6 text-center text-sm text-text-muted">
|
|
243
|
-
{emptyText ??
|
|
240
|
+
{emptyText ?? 'No matches'}
|
|
244
241
|
</p>
|
|
245
242
|
{:else}
|
|
246
243
|
{#each groups as [group, items] (group)}
|
|
@@ -264,7 +261,7 @@
|
|
|
264
261
|
{index === active ? toneSoft[tone] : 'text-text-secondary'}"
|
|
265
262
|
>
|
|
266
263
|
<span
|
|
267
|
-
class="mt-0.5 flex size-4 shrink-0 items-center justify-center rounded border transition-colors duration-100
|
|
264
|
+
class="mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-md border transition-colors duration-100
|
|
268
265
|
{checked ? `border-transparent ${toneText[tone]}` : 'border-hairline-strong'}"
|
|
269
266
|
>
|
|
270
267
|
{#if checked}
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
|
|
17
17
|
<script lang="ts">
|
|
18
18
|
import type { Snippet } from 'svelte';
|
|
19
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
20
19
|
import { iconMd } from './icon.js';
|
|
21
20
|
import { focusRing, toneRing, toneSoft, toneText, type Tone } from '../../core/tones.js';
|
|
22
21
|
import Drawer from './Drawer.svelte';
|
|
@@ -53,8 +52,6 @@
|
|
|
53
52
|
class: className = ''
|
|
54
53
|
}: Props = $props();
|
|
55
54
|
|
|
56
|
-
const t = useLocale();
|
|
57
|
-
|
|
58
55
|
// sprout gives the active link a filled pill rather than a colour change, so
|
|
59
56
|
// the current page is legible without relying on hue alone.
|
|
60
57
|
const link =
|
|
@@ -66,10 +63,7 @@
|
|
|
66
63
|
? 'border-b border-hairline'
|
|
67
64
|
: ''} {className}"
|
|
68
65
|
>
|
|
69
|
-
<nav
|
|
70
|
-
aria-label={t.current.navigation}
|
|
71
|
-
class="mx-auto flex h-16 w-full max-w-6xl items-center gap-6 px-6"
|
|
72
|
-
>
|
|
66
|
+
<nav aria-label="Navigation" class="mx-auto flex h-16 w-full max-w-6xl items-center gap-6 px-6">
|
|
73
67
|
{#if brand}
|
|
74
68
|
<div class="flex shrink-0 items-center">{@render brand()}</div>
|
|
75
69
|
{/if}
|
|
@@ -117,7 +111,7 @@
|
|
|
117
111
|
class="{link} {focusRing} {toneRing[tone]} {item.active
|
|
118
112
|
? toneSoft[tone]
|
|
119
113
|
: 'text-text-secondary hover:bg-bg-inset hover:text-text'} {item.disabled
|
|
120
|
-
? 'pointer-events-none opacity-
|
|
114
|
+
? 'pointer-events-none opacity-40'
|
|
121
115
|
: ''}"
|
|
122
116
|
>
|
|
123
117
|
{#if item.icon}<span class={iconMd}>{@render item.icon()}</span>{/if}
|
|
@@ -140,7 +134,7 @@
|
|
|
140
134
|
<button
|
|
141
135
|
type="button"
|
|
142
136
|
onclick={() => (menuOpen = true)}
|
|
143
|
-
aria-label=
|
|
137
|
+
aria-label="Open menu"
|
|
144
138
|
aria-expanded={menuOpen}
|
|
145
139
|
class="inline-flex size-9 items-center justify-center rounded-xl text-text-secondary transition-colors duration-150 hover:bg-bg-inset hover:text-text md:hidden {focusRing} {toneRing[
|
|
146
140
|
tone
|
|
@@ -159,7 +153,7 @@
|
|
|
159
153
|
</nav>
|
|
160
154
|
</header>
|
|
161
155
|
|
|
162
|
-
<Drawer bind:open={menuOpen} side="right" size="sm" title=
|
|
156
|
+
<Drawer bind:open={menuOpen} side="right" size="sm" title="Navigation">
|
|
163
157
|
<ul class="flex flex-col gap-0.5">
|
|
164
158
|
{#each items as item (item.label)}
|
|
165
159
|
<li>
|
|
@@ -170,7 +164,7 @@
|
|
|
170
164
|
class="flex items-center justify-between gap-3 rounded-xl px-3 py-2.5 font-sans text-sm font-medium {item.active
|
|
171
165
|
? `${toneSoft[tone]}`
|
|
172
166
|
: 'text-text-secondary hover:bg-bg-inset'} {item.disabled
|
|
173
|
-
? 'pointer-events-none opacity-
|
|
167
|
+
? 'pointer-events-none opacity-40'
|
|
174
168
|
: ''}"
|
|
175
169
|
>
|
|
176
170
|
<span class="flex min-w-0 items-center gap-2.5">
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
3
|
import { focusRing, toneRing, toneSolid, type Tone } from '../../core/tones.js';
|
|
4
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
5
4
|
import { pageRange } from '../../core/pagination.js';
|
|
6
5
|
import { liftSm } from './lift.js';
|
|
7
6
|
|
|
@@ -26,8 +25,6 @@
|
|
|
26
25
|
...rest
|
|
27
26
|
}: Props = $props();
|
|
28
27
|
|
|
29
|
-
const t = useLocale();
|
|
30
|
-
|
|
31
28
|
const pages = $derived(pageRange(page, total, siblings));
|
|
32
29
|
|
|
33
30
|
function go(next: number) {
|
|
@@ -40,12 +37,12 @@
|
|
|
40
37
|
const cell = `inline-flex h-9 min-w-9 items-center justify-center rounded-full px-2 font-sans text-sm font-medium tabular-nums transition-colors duration-150 ease-brand-out disabled:opacity-40 disabled:pointer-events-none ${focusRing}`;
|
|
41
38
|
</script>
|
|
42
39
|
|
|
43
|
-
<nav aria-label=
|
|
40
|
+
<nav aria-label="Pagination" class="flex items-center gap-1 {className}" {...rest}>
|
|
44
41
|
<button
|
|
45
42
|
type="button"
|
|
46
43
|
class="{cell} {toneRing[tone]} text-text-secondary hover:bg-bg-inset"
|
|
47
44
|
disabled={page <= 1}
|
|
48
|
-
aria-label=
|
|
45
|
+
aria-label="Previous page"
|
|
49
46
|
onclick={() => go(page - 1)}
|
|
50
47
|
>
|
|
51
48
|
<svg class="size-4" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
@@ -74,7 +71,7 @@
|
|
|
74
71
|
type="button"
|
|
75
72
|
class="{cell} {toneRing[tone]} text-text-secondary hover:bg-bg-inset"
|
|
76
73
|
disabled={page >= total}
|
|
77
|
-
aria-label=
|
|
74
|
+
aria-label="Next page"
|
|
78
75
|
onclick={() => go(page + 1)}
|
|
79
76
|
>
|
|
80
77
|
<svg class="size-4" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
3
2
|
import { caretIndex, clearFrom, fillFrom, sanitisePin, type PinMode } from '../../core/pin.js';
|
|
4
3
|
import { toneFocusBorder, type Tone } from '../../core/tones.js';
|
|
5
4
|
import { edge } from './lift.js';
|
|
@@ -39,8 +38,6 @@
|
|
|
39
38
|
class: className = ''
|
|
40
39
|
}: Props = $props();
|
|
41
40
|
|
|
42
|
-
const t = useLocale();
|
|
43
|
-
|
|
44
41
|
let boxes: HTMLInputElement[] = $state([]);
|
|
45
42
|
|
|
46
43
|
const chars = $derived(Array.from({ length }, (_, i) => value[i] ?? ''));
|
|
@@ -120,7 +117,7 @@
|
|
|
120
117
|
autocapitalize="characters"
|
|
121
118
|
spellcheck="false"
|
|
122
119
|
maxlength={length}
|
|
123
|
-
aria-label="
|
|
120
|
+
aria-label="Digit {index + 1}"
|
|
124
121
|
aria-invalid={invalid ? 'true' : undefined}
|
|
125
122
|
oninput={(event) => onInput(event, index)}
|
|
126
123
|
onkeydown={(event) => onKeydown(event, index)}
|
|
@@ -25,32 +25,51 @@
|
|
|
25
25
|
children,
|
|
26
26
|
...rest
|
|
27
27
|
}: Props = $props();
|
|
28
|
+
|
|
29
|
+
const uid = $props.id();
|
|
28
30
|
</script>
|
|
29
31
|
|
|
30
|
-
<
|
|
31
|
-
class="
|
|
32
|
-
|
|
32
|
+
<div
|
|
33
|
+
class="inline-block font-sans text-sm {disabled
|
|
34
|
+
? 'pointer-events-none opacity-50'
|
|
35
|
+
: ''} {className}"
|
|
33
36
|
>
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
<label class="group inline-flex items-start gap-2.5 {disabled ? '' : 'cursor-pointer'}">
|
|
38
|
+
<input
|
|
39
|
+
type="radio"
|
|
40
|
+
bind:group
|
|
41
|
+
{value}
|
|
42
|
+
{disabled}
|
|
43
|
+
aria-describedby={description ? `${uid}-description` : undefined}
|
|
44
|
+
class="peer sr-only"
|
|
45
|
+
{...rest}
|
|
46
|
+
/>
|
|
47
|
+
<span
|
|
48
|
+
class="mt-0.5 flex size-[18px] shrink-0 items-center justify-center rounded-full border border-hairline-strong bg-bg {edge} transition-colors duration-150 ease-brand-out
|
|
37
49
|
{tonePeerChecked[tone]} {peerFocusRing} {tonePeerFocus[tone]}"
|
|
38
|
-
|
|
39
|
-
|
|
50
|
+
aria-hidden="true"
|
|
51
|
+
>
|
|
52
|
+
<span
|
|
53
|
+
class="size-1.5 rounded-full bg-text-inverse opacity-0 transition-opacity duration-150 group-has-[:checked]:opacity-100"
|
|
54
|
+
></span>
|
|
55
|
+
</span>
|
|
56
|
+
{#if label || children}
|
|
57
|
+
<span class="flex flex-col gap-0.5">
|
|
58
|
+
{#if children}
|
|
59
|
+
{@render children()}
|
|
60
|
+
{:else if label}
|
|
61
|
+
<span class="leading-snug text-text">{label}</span>
|
|
62
|
+
{/if}
|
|
63
|
+
</span>
|
|
64
|
+
{/if}
|
|
65
|
+
</label>
|
|
66
|
+
{#if description}
|
|
67
|
+
<!-- ponytail: the indent tracks the 18px dot plus the label's gap; move one, move both. -->
|
|
40
68
|
<span
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<span class="flex flex-col gap-0.5">
|
|
46
|
-
{#if children}
|
|
47
|
-
{@render children()}
|
|
48
|
-
{:else if label}
|
|
49
|
-
<span class="leading-snug text-text">{label}</span>
|
|
50
|
-
{/if}
|
|
51
|
-
{#if description}
|
|
52
|
-
<span class="text-[13px] leading-snug text-text-muted">{description}</span>
|
|
53
|
-
{/if}
|
|
69
|
+
id="{uid}-description"
|
|
70
|
+
class="mt-0.5 block pl-[28px] text-[13px] leading-snug text-text-muted"
|
|
71
|
+
>
|
|
72
|
+
{description}
|
|
54
73
|
</span>
|
|
55
74
|
{/if}
|
|
56
|
-
</
|
|
75
|
+
</div>
|
|
@@ -45,13 +45,24 @@
|
|
|
45
45
|
children,
|
|
46
46
|
...rest
|
|
47
47
|
}: Props = $props();
|
|
48
|
+
|
|
49
|
+
const uid = $props.id();
|
|
50
|
+
// The group's own hint and error sit outside every control in it, so the
|
|
51
|
+
// fieldset is what has to point at them.
|
|
52
|
+
const messageId = $derived(error ? `${uid}-error` : hint ? `${uid}-hint` : undefined);
|
|
48
53
|
</script>
|
|
49
54
|
|
|
50
|
-
<fieldset
|
|
55
|
+
<fieldset
|
|
56
|
+
aria-describedby={messageId}
|
|
57
|
+
class="flex flex-col gap-3 border-0 p-0 {className}"
|
|
58
|
+
{...rest}
|
|
59
|
+
>
|
|
51
60
|
{#if legend}
|
|
52
61
|
<legend class="mb-1 font-sans text-sm font-medium text-text">
|
|
53
62
|
{legend}
|
|
54
|
-
{#if required}<span class="ml-0.5 text-danger" aria-hidden="true">*</span
|
|
63
|
+
{#if required}<span class="ml-0.5 text-danger" aria-hidden="true">*</span><span
|
|
64
|
+
class="sr-only">(required)</span
|
|
65
|
+
>{/if}
|
|
55
66
|
</legend>
|
|
56
67
|
{/if}
|
|
57
68
|
|
|
@@ -95,8 +106,8 @@
|
|
|
95
106
|
</div>
|
|
96
107
|
|
|
97
108
|
{#if error}
|
|
98
|
-
<p class="font-sans text-[13px] text-danger">{error}</p>
|
|
109
|
+
<p id="{uid}-error" role="alert" class="font-sans text-[13px] text-danger">{error}</p>
|
|
99
110
|
{:else if hint}
|
|
100
|
-
<p class="font-sans text-[13px] text-text-muted">{hint}</p>
|
|
111
|
+
<p id="{uid}-hint" class="font-sans text-[13px] text-text-muted">{hint}</p>
|
|
101
112
|
{/if}
|
|
102
113
|
</fieldset>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
4
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
5
4
|
import type { Tone } from '../../core/tones.js';
|
|
6
5
|
import Input, { type InputSize } from './Input.svelte';
|
|
7
6
|
|
|
@@ -37,8 +36,6 @@
|
|
|
37
36
|
...rest
|
|
38
37
|
}: Props = $props();
|
|
39
38
|
|
|
40
|
-
const t = useLocale();
|
|
41
|
-
|
|
42
39
|
// The timer is cleared by the effect's own teardown, so a keystroke that
|
|
43
40
|
// lands mid-wait restarts the clock rather than queueing a second call.
|
|
44
41
|
$effect(() => {
|
|
@@ -75,8 +72,8 @@
|
|
|
75
72
|
<button
|
|
76
73
|
type="button"
|
|
77
74
|
onclick={clear}
|
|
78
|
-
aria-label=
|
|
79
|
-
class="-mr-1 rounded p-1 text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
|
|
75
|
+
aria-label="Clear search"
|
|
76
|
+
class="-mr-1 rounded-xl p-1 text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
|
|
80
77
|
>
|
|
81
78
|
<svg class="size-3.5" viewBox="0 0 14 14" fill="none" aria-hidden="true">
|
|
82
79
|
<path
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
import { focusRing, toneRing, type Tone } from '../../core/tones.js';
|
|
4
|
+
import { focusRing, toneRing, toneText, type Tone } from '../../core/tones.js';
|
|
5
5
|
import { iconMd } from './icon.js';
|
|
6
6
|
import { edge } from './lift.js';
|
|
7
7
|
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
onclick={() => select(option)}
|
|
94
94
|
class="inline-flex items-center justify-center rounded-xl font-sans font-medium whitespace-nowrap transition-all duration-150 ease-brand-out disabled:pointer-events-none disabled:opacity-40
|
|
95
95
|
{iconOnly ? squares[size] : sizes[size]} {focusRing} {toneRing[tone]}
|
|
96
|
-
{value === option.value ? `bg-bg
|
|
96
|
+
{value === option.value ? `bg-bg ${toneText[tone]} ${edge}` : 'text-text-muted hover:text-text'}"
|
|
97
97
|
>
|
|
98
98
|
{#if option.icon}<span class={iconMd}>{@render option.icon()}</span>{/if}
|
|
99
99
|
{#if !iconOnly}{option.label}{/if}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLSelectAttributes } from 'svelte/elements';
|
|
4
|
-
import { toneFocusBorder, type Tone } from '../../core/tones.js';
|
|
4
|
+
import { focusRing, toneFocusBorder, toneRing, type Tone } from '../../core/tones.js';
|
|
5
5
|
import { edge } from './lift.js';
|
|
6
6
|
|
|
7
7
|
export interface SelectOption {
|
|
@@ -36,7 +36,9 @@
|
|
|
36
36
|
<select
|
|
37
37
|
bind:value
|
|
38
38
|
aria-invalid={invalid ? 'true' : undefined}
|
|
39
|
-
class="
|
|
39
|
+
class="{focusRing} {toneRing[
|
|
40
|
+
tone
|
|
41
|
+
]} h-10 w-full appearance-none rounded-xl border bg-bg py-0 pr-9 pl-3 font-sans text-sm text-text {edge} transition-colors duration-150 ease-brand-out disabled:pointer-events-none disabled:opacity-50
|
|
40
42
|
{invalid ? 'border-danger' : `border-hairline-strong ${toneFocusBorder[tone]}`} {className}"
|
|
41
43
|
{...rest}
|
|
42
44
|
>
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
</script>
|
|
36
36
|
|
|
37
37
|
<script lang="ts">
|
|
38
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
39
38
|
import { iconMd } from './icon.js';
|
|
39
|
+
import { soft } from './lift.js';
|
|
40
40
|
import { focusRing, toneRing, toneSoft, type Tone } from '../../core/tones.js';
|
|
41
41
|
|
|
42
42
|
interface Props {
|
|
@@ -69,8 +69,6 @@
|
|
|
69
69
|
class: className = ''
|
|
70
70
|
}: Props = $props();
|
|
71
71
|
|
|
72
|
-
const t = useLocale();
|
|
73
|
-
|
|
74
72
|
const keyOf = (item: SidebarItem) => item.id ?? item.href ?? item.label;
|
|
75
73
|
|
|
76
74
|
/** Groups start open when asked, or when they contain the active item. */
|
|
@@ -93,7 +91,7 @@
|
|
|
93
91
|
const surfaces: Record<SidebarVariant, string> = {
|
|
94
92
|
plain: 'h-full bg-transparent',
|
|
95
93
|
filled: 'h-full border-r border-hairline bg-bg-alt',
|
|
96
|
-
floating:
|
|
94
|
+
floating: `m-3 h-[calc(100%-1.5rem)] rounded-2xl border border-hairline bg-bg-alt ${soft}`
|
|
97
95
|
};
|
|
98
96
|
|
|
99
97
|
const row =
|
|
@@ -141,7 +139,7 @@
|
|
|
141
139
|
</div>
|
|
142
140
|
{/if}
|
|
143
141
|
|
|
144
|
-
<nav aria-label=
|
|
142
|
+
<nav aria-label="Navigation" class="flex-1 overflow-y-auto p-2">
|
|
145
143
|
{#each sections as section, i (section.label ?? i)}
|
|
146
144
|
<div class="flex flex-col gap-0.5 {i > 0 ? 'mt-4' : ''}">
|
|
147
145
|
{#if section.label && !collapsed}
|
|
@@ -230,7 +228,7 @@
|
|
|
230
228
|
<button
|
|
231
229
|
type="button"
|
|
232
230
|
onclick={() => (collapsed = !collapsed)}
|
|
233
|
-
aria-label={collapsed ?
|
|
231
|
+
aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
|
|
234
232
|
class="inline-flex h-8 items-center justify-center gap-2 rounded-xl font-sans text-xs text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text {focusRing} {toneRing[
|
|
235
233
|
tone
|
|
236
234
|
]}"
|
|
@@ -248,7 +246,7 @@
|
|
|
248
246
|
stroke-linecap="round"
|
|
249
247
|
/>
|
|
250
248
|
</svg>
|
|
251
|
-
{#if !collapsed}<span>
|
|
249
|
+
{#if !collapsed}<span>Collapse sidebar</span>{/if}
|
|
252
250
|
</button>
|
|
253
251
|
{/if}
|
|
254
252
|
</div>
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
</script>
|
|
30
30
|
|
|
31
31
|
{#if variant === 'text' && lines > 1}
|
|
32
|
-
<div class="flex w-full flex-col gap-2 {className}" {...rest}>
|
|
32
|
+
<div aria-hidden="true" class="flex w-full flex-col gap-2 {className}" {...rest}>
|
|
33
33
|
{#each { length: lines }, i (i)}
|
|
34
34
|
<div
|
|
35
35
|
class="h-4 animate-pulse rounded-xl bg-bg-inset {i === lines - 1 ? 'w-2/3' : 'w-full'}"
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
</div>
|
|
40
40
|
{:else}
|
|
41
41
|
<div
|
|
42
|
+
aria-hidden="true"
|
|
42
43
|
class="animate-pulse bg-bg-inset {variants[variant]} {className}"
|
|
43
44
|
style="{width ? `width:${width};` : ''}{height ? `height:${height};` : ''}"
|
|
44
45
|
{...rest}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
3
|
import { toneText, type Tone } from '../../core/tones.js';
|
|
4
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
5
4
|
|
|
6
5
|
export type SpinnerSize = 'xs' | 'sm' | 'md' | 'lg';
|
|
7
6
|
|
|
@@ -9,12 +8,10 @@
|
|
|
9
8
|
size?: SpinnerSize;
|
|
10
9
|
/** Omit to inherit the parent's `currentColor` (e.g. inside a Button). */
|
|
11
10
|
tone?: Tone;
|
|
12
|
-
/** Defaults to
|
|
11
|
+
/** Defaults to `Loading`; pass `''` to hide it. */
|
|
13
12
|
label?: string;
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
const t = useLocale();
|
|
17
|
-
|
|
18
15
|
let { size = 'md', tone, label, class: className = '', ...rest }: Props = $props();
|
|
19
16
|
|
|
20
17
|
const sizes: Record<SpinnerSize, string> = {
|
|
@@ -27,7 +24,7 @@
|
|
|
27
24
|
|
|
28
25
|
<span
|
|
29
26
|
role="status"
|
|
30
|
-
aria-label={label ??
|
|
27
|
+
aria-label={label ?? 'Loading'}
|
|
31
28
|
class="inline-block shrink-0 animate-spin rounded-full border-current/25 border-t-current
|
|
32
29
|
{sizes[size]} {tone ? toneText[tone] : ''} {className}"
|
|
33
30
|
{...rest}
|
|
@@ -5,7 +5,7 @@ interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
|
5
5
|
size?: SpinnerSize;
|
|
6
6
|
/** Omit to inherit the parent's `currentColor` (e.g. inside a Button). */
|
|
7
7
|
tone?: Tone;
|
|
8
|
-
/** Defaults to
|
|
8
|
+
/** Defaults to `Loading`; pass `''` to hide it. */
|
|
9
9
|
label?: string;
|
|
10
10
|
}
|
|
11
11
|
declare const Spinner: import("svelte").Component<Props, {}, "">;
|
|
@@ -32,7 +32,15 @@
|
|
|
32
32
|
}: Props = $props();
|
|
33
33
|
|
|
34
34
|
const trendTone: Record<StatTrend, Tone> = { up: 'success', down: 'danger', flat: 'neutral' };
|
|
35
|
-
|
|
35
|
+
// Drawn rather than typed. `↑` renders in whatever face the reader's system
|
|
36
|
+
// substitutes for it and is announced as "up arrow" or nothing at all, and
|
|
37
|
+
// the colour beside it says nothing either — so the word ships with it.
|
|
38
|
+
const trendPath: Record<StatTrend, string> = {
|
|
39
|
+
up: 'M7 11V3.5M7 3l3.5 3.5M7 3 3.5 6.5',
|
|
40
|
+
down: 'M7 3v7.5M7 11l3.5-3.5M7 11 3.5 7.5',
|
|
41
|
+
flat: 'M3 7h7.5M11 7 7.5 3.5M11 7l-3.5 3.5'
|
|
42
|
+
};
|
|
43
|
+
const trendWord: Record<StatTrend, string> = { up: 'up', down: 'down', flat: 'no change' };
|
|
36
44
|
</script>
|
|
37
45
|
|
|
38
46
|
<div class="flex flex-col gap-1 font-sans {className}" {...rest}>
|
|
@@ -49,7 +57,21 @@
|
|
|
49
57
|
</span>
|
|
50
58
|
{#if delta}
|
|
51
59
|
<span class="text-sm font-medium {toneText[trendTone[trend]]}">
|
|
52
|
-
|
|
60
|
+
<svg
|
|
61
|
+
class="inline-block size-[1em] align-[-0.115em]"
|
|
62
|
+
viewBox="0 0 14 14"
|
|
63
|
+
fill="none"
|
|
64
|
+
aria-hidden="true"
|
|
65
|
+
>
|
|
66
|
+
<path
|
|
67
|
+
d={trendPath[trend]}
|
|
68
|
+
stroke="currentColor"
|
|
69
|
+
stroke-width="1.6"
|
|
70
|
+
stroke-linecap="round"
|
|
71
|
+
stroke-linejoin="round"
|
|
72
|
+
/>
|
|
73
|
+
</svg>
|
|
74
|
+
<span class="sr-only">{trendWord[trend]}</span>
|
|
53
75
|
{delta}
|
|
54
76
|
</span>
|
|
55
77
|
{/if}
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
md: { track: 'h-6 w-11', thumb: 'size-5', travel: 'translate-x-5' }
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
const uid = $props.id();
|
|
35
|
+
|
|
34
36
|
function toggle() {
|
|
35
37
|
checked = !checked;
|
|
36
38
|
onchange?.(checked);
|
|
@@ -43,6 +45,7 @@
|
|
|
43
45
|
role="switch"
|
|
44
46
|
aria-checked={checked}
|
|
45
47
|
aria-label={label}
|
|
48
|
+
aria-describedby={description ? `${uid}-description` : undefined}
|
|
46
49
|
{disabled}
|
|
47
50
|
onclick={toggle}
|
|
48
51
|
class="relative mt-0.5 inline-flex shrink-0 items-center rounded-full p-0.5 transition-colors duration-200 ease-brand-out disabled:pointer-events-none
|
|
@@ -58,7 +61,9 @@
|
|
|
58
61
|
<span class="flex flex-col gap-0.5 font-sans text-sm">
|
|
59
62
|
{#if label}<span class="leading-snug text-text">{label}</span>{/if}
|
|
60
63
|
{#if description}
|
|
61
|
-
<span class="text-[13px] leading-snug text-text-muted"
|
|
64
|
+
<span id="{uid}-description" class="text-[13px] leading-snug text-text-muted"
|
|
65
|
+
>{description}</span
|
|
66
|
+
>
|
|
62
67
|
{/if}
|
|
63
68
|
</span>
|
|
64
69
|
{/if}
|