@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
|
@@ -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}>
|
|
@@ -41,13 +49,29 @@
|
|
|
41
49
|
>
|
|
42
50
|
<div class="flex items-baseline gap-2">
|
|
43
51
|
<span
|
|
44
|
-
class="font-heading text-3xl font-medium tracking-tight {tone
|
|
52
|
+
class="font-heading text-3xl font-medium tracking-tight tabular-nums {tone
|
|
53
|
+
? toneText[tone]
|
|
54
|
+
: 'text-text'}"
|
|
45
55
|
>
|
|
46
56
|
{value}
|
|
47
57
|
</span>
|
|
48
58
|
{#if delta}
|
|
49
59
|
<span class="font-mono text-xs {toneText[trendTone[trend]]}">
|
|
50
|
-
|
|
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>
|
|
51
75
|
{delta}
|
|
52
76
|
</span>
|
|
53
77
|
{/if}
|
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
md: { track: 'h-6 w-11', thumb: 'size-5', travel: 'translate-x-5' }
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
const uid = $props.id();
|
|
34
|
+
|
|
33
35
|
function toggle() {
|
|
34
36
|
checked = !checked;
|
|
35
37
|
onchange?.(checked);
|
|
@@ -42,6 +44,7 @@
|
|
|
42
44
|
role="switch"
|
|
43
45
|
aria-checked={checked}
|
|
44
46
|
aria-label={label}
|
|
47
|
+
aria-describedby={description ? `${uid}-description` : undefined}
|
|
45
48
|
{disabled}
|
|
46
49
|
onclick={toggle}
|
|
47
50
|
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
|
|
@@ -57,7 +60,9 @@
|
|
|
57
60
|
<span class="flex flex-col gap-0.5 font-sans text-[15px]">
|
|
58
61
|
{#if label}<span class="leading-snug text-text">{label}</span>{/if}
|
|
59
62
|
{#if description}
|
|
60
|
-
<span class="text-sm leading-snug text-text-muted"
|
|
63
|
+
<span id="{uid}-description" class="text-sm leading-snug text-text-muted"
|
|
64
|
+
>{description}</span
|
|
65
|
+
>
|
|
61
66
|
{/if}
|
|
62
67
|
</span>
|
|
63
68
|
{/if}
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
import Checkbox from './Checkbox.svelte';
|
|
17
17
|
import type { Tone } from '../../core/tones.js';
|
|
18
18
|
import { nextSort, sortRows, toggleKey, type TableSort } from '../../core/table.js';
|
|
19
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
20
19
|
|
|
21
20
|
interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'onselect'> {
|
|
22
21
|
columns: TableColumn[];
|
|
@@ -82,8 +81,6 @@
|
|
|
82
81
|
...rest
|
|
83
82
|
}: Props = $props();
|
|
84
83
|
|
|
85
|
-
const t = useLocale();
|
|
86
|
-
|
|
87
84
|
const aligns = {
|
|
88
85
|
left: 'text-left',
|
|
89
86
|
center: 'text-center',
|
|
@@ -136,14 +133,14 @@
|
|
|
136
133
|
>
|
|
137
134
|
<span class="font-mono text-xs font-medium tracking-wide text-text uppercase">
|
|
138
135
|
{selected.length}
|
|
139
|
-
|
|
136
|
+
selected
|
|
140
137
|
</span>
|
|
141
138
|
<button
|
|
142
139
|
type="button"
|
|
143
140
|
onclick={clearSelection}
|
|
144
141
|
class="font-mono text-xs tracking-wide text-text-muted uppercase transition-colors duration-150 hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
|
|
145
142
|
>
|
|
146
|
-
|
|
143
|
+
Clear selection
|
|
147
144
|
</button>
|
|
148
145
|
<div class="ml-auto flex flex-wrap items-center gap-2">
|
|
149
146
|
{@render bulkActions?.({ selected, clear: clearSelection })}
|
|
@@ -173,7 +170,7 @@
|
|
|
173
170
|
checked={allSelected}
|
|
174
171
|
indeterminate={someSelected}
|
|
175
172
|
{tone}
|
|
176
|
-
aria-label=
|
|
173
|
+
aria-label="Select all rows"
|
|
177
174
|
onchange={toggleAll}
|
|
178
175
|
/>
|
|
179
176
|
</th>
|
|
@@ -220,7 +217,7 @@
|
|
|
220
217
|
colspan={columns.length + (selectable ? 1 : 0)}
|
|
221
218
|
class="px-3.5 py-10 text-center text-sm text-text-muted"
|
|
222
219
|
>
|
|
223
|
-
{#if empty}{@render empty()}{:else}{
|
|
220
|
+
{#if empty}{@render empty()}{:else}No data{/if}
|
|
224
221
|
</td>
|
|
225
222
|
</tr>
|
|
226
223
|
{:else}
|
|
@@ -237,7 +234,7 @@
|
|
|
237
234
|
<Checkbox
|
|
238
235
|
checked={isSelected}
|
|
239
236
|
{tone}
|
|
240
|
-
aria-label=
|
|
237
|
+
aria-label="Select row"
|
|
241
238
|
onchange={() => toggleRow(row)}
|
|
242
239
|
/>
|
|
243
240
|
</td>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
3
2
|
import { addTag, splitTags, type TagRejection } from '../../core/tags.js';
|
|
4
3
|
import { toneFocusWithinBorder, toneSoft, type Tone } from '../../core/tones.js';
|
|
5
4
|
|
|
@@ -46,8 +45,6 @@
|
|
|
46
45
|
class: className = ''
|
|
47
46
|
}: Props = $props();
|
|
48
47
|
|
|
49
|
-
const t = useLocale();
|
|
50
|
-
|
|
51
48
|
let draft = $state('');
|
|
52
49
|
let field: HTMLInputElement | null = $state(null);
|
|
53
50
|
/** The last refusal, cleared as soon as the next keystroke lands. */
|
|
@@ -111,8 +108,8 @@
|
|
|
111
108
|
const messages: Record<TagRejection, string> = $derived({
|
|
112
109
|
empty: '',
|
|
113
110
|
short: `${minLength}+`,
|
|
114
|
-
duplicate:
|
|
115
|
-
full: `$
|
|
111
|
+
duplicate: 'Already added',
|
|
112
|
+
full: `$selected ${tags.length}/${max}`
|
|
116
113
|
});
|
|
117
114
|
</script>
|
|
118
115
|
|
|
@@ -136,7 +133,7 @@
|
|
|
136
133
|
<button
|
|
137
134
|
type="button"
|
|
138
135
|
onclick={() => remove(index)}
|
|
139
|
-
aria-label="
|
|
136
|
+
aria-label="Remove {tag}"
|
|
140
137
|
class="inline-flex size-4 items-center justify-center rounded-full transition-colors duration-150 hover:bg-bg focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-current"
|
|
141
138
|
>
|
|
142
139
|
<svg class="size-2.5" viewBox="0 0 10 10" fill="none" aria-hidden="true">
|
|
@@ -151,8 +148,8 @@
|
|
|
151
148
|
bind:value={draft}
|
|
152
149
|
{disabled}
|
|
153
150
|
readonly={full}
|
|
154
|
-
placeholder={tags.length === 0 ? (placeholder ??
|
|
155
|
-
aria-label={placeholder ??
|
|
151
|
+
placeholder={tags.length === 0 ? (placeholder ?? 'Add a tag') : ''}
|
|
152
|
+
aria-label={placeholder ?? 'Add a tag'}
|
|
156
153
|
aria-invalid={invalid ? 'true' : undefined}
|
|
157
154
|
onkeydown={onKeydown}
|
|
158
155
|
onpaste={onPaste}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { HTMLTextareaAttributes } from 'svelte/elements';
|
|
3
|
-
import { toneFocusBorder, type Tone } from '../../core/tones.js';
|
|
3
|
+
import { focusRing, toneFocusBorder, toneRing, type Tone } from '../../core/tones.js';
|
|
4
4
|
|
|
5
5
|
interface Props extends HTMLTextareaAttributes {
|
|
6
6
|
value?: string;
|
|
@@ -48,7 +48,9 @@
|
|
|
48
48
|
bind:value
|
|
49
49
|
{rows}
|
|
50
50
|
aria-invalid={invalid ? 'true' : undefined}
|
|
51
|
-
class="
|
|
51
|
+
class="{focusRing} {toneRing[
|
|
52
|
+
tone
|
|
53
|
+
]} w-full border bg-bg px-3.5 py-2.5 font-sans text-[15px] text-text transition-colors duration-150 ease-brand-out placeholder:text-text-muted disabled:pointer-events-none disabled:opacity-50
|
|
52
54
|
{autoresize ? 'resize-none overflow-hidden' : 'resize-y'}
|
|
53
55
|
{invalid ? 'border-danger' : `border-hairline ${toneFocusBorder[tone]}`} {className}"
|
|
54
56
|
{...rest}></textarea>
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
storedTheme,
|
|
11
11
|
type Theme
|
|
12
12
|
} from '../../core/theme.svelte.js';
|
|
13
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
14
13
|
|
|
15
14
|
interface Props {
|
|
16
15
|
/** Bindable. `'system'` follows the OS until the visitor chooses. */
|
|
@@ -33,8 +32,6 @@
|
|
|
33
32
|
class: className = ''
|
|
34
33
|
}: Props = $props();
|
|
35
34
|
|
|
36
|
-
const t = useLocale();
|
|
37
|
-
|
|
38
35
|
$effect(() => {
|
|
39
36
|
applyTheme(theme);
|
|
40
37
|
if (persist) persistTheme(theme);
|
|
@@ -50,8 +47,8 @@
|
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
const options = $derived([
|
|
53
|
-
{ value: 'light' as Theme, label:
|
|
54
|
-
{ value: 'dark' as Theme, label:
|
|
50
|
+
{ value: 'light' as Theme, label: 'Light' },
|
|
51
|
+
{ value: 'dark' as Theme, label: 'Dark' },
|
|
55
52
|
{ value: 'system' as Theme, label: 'Auto' }
|
|
56
53
|
]);
|
|
57
54
|
</script>
|
|
@@ -85,7 +82,7 @@
|
|
|
85
82
|
{#if variant === 'segmented'}
|
|
86
83
|
<div
|
|
87
84
|
role="radiogroup"
|
|
88
|
-
aria-label=
|
|
85
|
+
aria-label="Toggle theme"
|
|
89
86
|
class="inline-flex items-center gap-0 border border-hairline bg-bg-alt p-1 {className}"
|
|
90
87
|
>
|
|
91
88
|
{#each options as option (option.value)}
|
|
@@ -109,8 +106,8 @@
|
|
|
109
106
|
<button
|
|
110
107
|
type="button"
|
|
111
108
|
onclick={cycle}
|
|
112
|
-
aria-label="
|
|
113
|
-
title=
|
|
109
|
+
aria-label="Toggle theme ({theme})"
|
|
110
|
+
title="Toggle theme"
|
|
114
111
|
class="inline-flex size-9 items-center justify-center border border-hairline transition-colors duration-150 ease-brand-out {focusRing} {toneRing[
|
|
115
112
|
tone
|
|
116
113
|
]} {toneSoft[tone]} {className}"
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
3
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
4
3
|
import { clampTime, formatTime, parseTime, stepTime } from '../../core/time.js';
|
|
5
4
|
import type { Tone } from '../../core/tones.js';
|
|
6
5
|
import Input, { type InputSize } from './Input.svelte';
|
|
@@ -38,8 +37,6 @@
|
|
|
38
37
|
...rest
|
|
39
38
|
}: Props = $props();
|
|
40
39
|
|
|
41
|
-
const t = useLocale();
|
|
42
|
-
|
|
43
40
|
// Typed text and the bound value are separate until the field settles:
|
|
44
41
|
// `9` is a valid thing to be halfway through typing and an invalid time.
|
|
45
42
|
let text = $state('');
|
|
@@ -106,7 +103,7 @@
|
|
|
106
103
|
class={stepper}
|
|
107
104
|
{disabled}
|
|
108
105
|
onclick={() => nudge(1)}
|
|
109
|
-
aria-label=
|
|
106
|
+
aria-label="Increase"
|
|
110
107
|
>
|
|
111
108
|
<svg class="size-3" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
|
112
109
|
<path d="m3 7.5 3-3 3 3" stroke="currentColor" stroke-width="1.5" />
|
|
@@ -117,7 +114,7 @@
|
|
|
117
114
|
class={stepper}
|
|
118
115
|
{disabled}
|
|
119
116
|
onclick={() => nudge(-1)}
|
|
120
|
-
aria-label=
|
|
117
|
+
aria-label="Decrease"
|
|
121
118
|
>
|
|
122
119
|
<svg class="size-3" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
|
123
120
|
<path d="m3 4.5 3 3 3-3" stroke="currentColor" stroke-width="1.5" />
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
import { toneBorderSoft, toneSurface, toneText } from '../../core/tones.js';
|
|
7
7
|
import { iconMd } from './icon.js';
|
|
8
8
|
import Spinner from './Spinner.svelte';
|
|
9
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
10
9
|
|
|
11
10
|
export type ToasterPosition =
|
|
12
11
|
'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
|
|
@@ -18,8 +17,6 @@
|
|
|
18
17
|
|
|
19
18
|
let { position = 'bottom-right', class: className = '' }: Props = $props();
|
|
20
19
|
|
|
21
|
-
const t = useLocale();
|
|
22
|
-
|
|
23
20
|
const positions: Record<ToasterPosition, string> = {
|
|
24
21
|
'top-left': 'top-4 left-4 items-start',
|
|
25
22
|
'top-center': 'top-4 left-1/2 -translate-x-1/2 items-center',
|
|
@@ -33,22 +30,38 @@
|
|
|
33
30
|
const fromLeft = $derived(position.endsWith('left'));
|
|
34
31
|
const fromCenter = $derived(position.endsWith('center'));
|
|
35
32
|
|
|
33
|
+
/**
|
|
34
|
+
* A card sliding in from the edge of the screen, and a stack of them shuffling
|
|
35
|
+
* to make room, is exactly the motion this preference exists to stop. Under it
|
|
36
|
+
* the toast fades in place and the stack reorders instantly — the state change
|
|
37
|
+
* still reads, it just stops travelling.
|
|
38
|
+
*
|
|
39
|
+
* ponytail: read once at mount. Someone who flips the OS setting mid-session
|
|
40
|
+
* gets the new behaviour on the next load; a live listener is the upgrade.
|
|
41
|
+
*/
|
|
42
|
+
const stillness =
|
|
43
|
+
typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
44
|
+
|
|
36
45
|
const enter = $derived(
|
|
37
|
-
|
|
46
|
+
stillness
|
|
47
|
+
? { x: 0, y: 0 }
|
|
48
|
+
: fromCenter
|
|
49
|
+
? { y: fromTop ? -16 : 16, x: 0 }
|
|
50
|
+
: { x: fromLeft ? -16 : 16, y: 0 }
|
|
38
51
|
);
|
|
39
52
|
</script>
|
|
40
53
|
|
|
41
54
|
<div
|
|
42
55
|
use:portal
|
|
43
56
|
aria-live="polite"
|
|
44
|
-
aria-label=
|
|
57
|
+
aria-label="Notifications"
|
|
45
58
|
class="pointer-events-none fixed z-[100] flex w-[min(24rem,calc(100vw-2rem))] flex-col gap-3 {positions[
|
|
46
59
|
position
|
|
47
60
|
]} {fromTop ? '' : 'flex-col-reverse'} {className}"
|
|
48
61
|
>
|
|
49
62
|
{#each toast.items as item (item.id)}
|
|
50
63
|
<div
|
|
51
|
-
animate:flip={{ duration: 200 }}
|
|
64
|
+
animate:flip={{ duration: stillness ? 0 : 200 }}
|
|
52
65
|
in:fly={{ ...enter, duration: 220 }}
|
|
53
66
|
out:fly={{ ...enter, duration: 160 }}
|
|
54
67
|
role={item.tone === 'danger' ? 'alert' : 'status'}
|
|
@@ -78,7 +91,9 @@
|
|
|
78
91
|
</span>
|
|
79
92
|
|
|
80
93
|
<div class="flex min-w-0 flex-1 flex-col gap-1">
|
|
81
|
-
<p class="text-[15px] leading-snug font-medium {toneText[item.tone]}">
|
|
94
|
+
<p class="font-heading text-[15px] leading-snug font-medium {toneText[item.tone]}">
|
|
95
|
+
{item.title}
|
|
96
|
+
</p>
|
|
82
97
|
{#if item.description}
|
|
83
98
|
<p class="text-sm leading-relaxed text-text-secondary">{item.description}</p>
|
|
84
99
|
{/if}
|
|
@@ -101,7 +116,7 @@
|
|
|
101
116
|
<button
|
|
102
117
|
type="button"
|
|
103
118
|
onclick={() => toast.dismiss(item.id)}
|
|
104
|
-
aria-label=
|
|
119
|
+
aria-label="Dismiss"
|
|
105
120
|
class="-m-1 shrink-0 p-1 text-text-muted transition-colors duration-150 hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
|
|
106
121
|
>
|
|
107
122
|
<svg class="size-3.5" viewBox="0 0 14 14" fill="none" aria-hidden="true">
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
+
import { describedBy } from '../../core/trigger.js';
|
|
3
4
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
5
|
|
|
5
6
|
export type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';
|
|
@@ -13,6 +14,11 @@
|
|
|
13
14
|
|
|
14
15
|
let { content, placement = 'top', class: className = '', children, ...rest }: Props = $props();
|
|
15
16
|
|
|
17
|
+
const uid = $props.id();
|
|
18
|
+
let wrapper: HTMLElement | null = $state(null);
|
|
19
|
+
|
|
20
|
+
$effect(() => describedBy(wrapper, `${uid}-tip`));
|
|
21
|
+
|
|
16
22
|
const placements: Record<TooltipPlacement, string> = {
|
|
17
23
|
top: 'bottom-full left-1/2 mb-2 -translate-x-1/2',
|
|
18
24
|
bottom: 'top-full left-1/2 mt-2 -translate-x-1/2',
|
|
@@ -21,9 +27,10 @@
|
|
|
21
27
|
};
|
|
22
28
|
</script>
|
|
23
29
|
|
|
24
|
-
<span class="group/tt relative inline-flex" {...rest}>
|
|
30
|
+
<span bind:this={wrapper} class="group/tt relative inline-flex" {...rest}>
|
|
25
31
|
{@render children()}
|
|
26
32
|
<span
|
|
33
|
+
id="{uid}-tip"
|
|
27
34
|
role="tooltip"
|
|
28
35
|
class="pointer-events-none invisible absolute z-50 bg-text px-2.5 py-1.5 font-sans text-xs whitespace-nowrap text-text-inverse opacity-0 transition-opacity duration-150 ease-brand-out group-focus-within/tt:visible group-focus-within/tt:opacity-100 group-hover/tt:visible group-hover/tt:opacity-100
|
|
29
36
|
{placements[placement]} {className}"
|
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
* `@nqmcreative/ui/core`, re-exported below so this one import covers
|
|
6
6
|
* the whole style.
|
|
7
7
|
*/
|
|
8
|
-
export { TONES, focusRing, peerFocusRing, toneBorder, toneBorderLeft, toneBorderSoft, toneFill, toneFocusBorder, toneFocusWithinBorder, toneHoverBorder, toneHoverText, tonePeerChecked, tonePeerFocus, toneRing, toneSoft, toneSoftHover, toneSolid, toneSolidHover, toneSurface, toneText, anchored, clickOutside, focusTrap, focusable, navigateList, portal, toast,
|
|
9
|
-
export type { Tone, Placement, AnchorOptions, ClickOutsideOptions, FocusTrapOptions, Toast, ToastOptions, ToastAction,
|
|
10
|
-
export { default as LocaleProvider } from './LocaleProvider.svelte';
|
|
8
|
+
export { TONES, focusRing, peerFocusRing, toneBorder, toneBorderLeft, toneBorderSoft, toneFill, toneFocusBorder, toneFocusWithinBorder, focusWithinRing, toneFocusWithinRing, toneHoverBorder, toneHoverText, tonePeerChecked, tonePeerFocus, toneRing, toneSoft, toneSoftHover, toneSolid, toneSolidHover, toneSurface, toneText, anchored, clickOutside, focusTrap, focusable, navigateList, portal, toast, applyTheme, storedTheme, toISO, fromISO, today, isSameDay, addDays, addMonths, monthGrid, weekdayNames, monthLabel, isOutOfRange, formatISO, parseFormatted } from '../../core/index.js';
|
|
9
|
+
export type { Tone, Placement, AnchorOptions, ClickOutsideOptions, FocusTrapOptions, Toast, ToastOptions, ToastAction, Theme, DateFormat, TableSort, SortDirection, RejectedFile } from '../../core/index.js';
|
|
11
10
|
export { default as Button } from './Button.svelte';
|
|
12
11
|
export type { ButtonVariant, ButtonSize } from './Button.svelte';
|
|
13
12
|
export { default as Link } from './Link.svelte';
|
|
@@ -6,9 +6,7 @@
|
|
|
6
6
|
* the whole style.
|
|
7
7
|
*/
|
|
8
8
|
/* --- shared behaviour --- */
|
|
9
|
-
export { TONES, focusRing, peerFocusRing, toneBorder, toneBorderLeft, toneBorderSoft, toneFill, toneFocusBorder, toneFocusWithinBorder, toneHoverBorder, toneHoverText, tonePeerChecked, tonePeerFocus, toneRing, toneSoft, toneSoftHover, toneSolid, toneSolidHover, toneSurface, toneText, anchored, clickOutside, focusTrap, focusable, navigateList, portal, toast,
|
|
10
|
-
/* --- locale --- */
|
|
11
|
-
export { default as LocaleProvider } from './LocaleProvider.svelte';
|
|
9
|
+
export { TONES, focusRing, peerFocusRing, toneBorder, toneBorderLeft, toneBorderSoft, toneFill, toneFocusBorder, toneFocusWithinBorder, focusWithinRing, toneFocusWithinRing, toneHoverBorder, toneHoverText, tonePeerChecked, tonePeerFocus, toneRing, toneSoft, toneSoftHover, toneSolid, toneSolidHover, toneSurface, toneText, anchored, clickOutside, focusTrap, focusable, navigateList, portal, toast, applyTheme, storedTheme, toISO, fromISO, today, isSameDay, addDays, addMonths, monthGrid, weekdayNames, monthLabel, isOutOfRange, formatISO, parseFormatted } from '../../core/index.js';
|
|
12
10
|
/* --- actions --- */
|
|
13
11
|
export { default as Button } from './Button.svelte';
|
|
14
12
|
export { default as Link } from './Link.svelte';
|
|
@@ -207,3 +207,24 @@
|
|
|
207
207
|
--color-neutral-border: #334155;
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
|
+
|
|
211
|
+
/*
|
|
212
|
+
* The surfaces the browser draws for us.
|
|
213
|
+
*
|
|
214
|
+
* A caret and a highlight in the user-agent's blue belong to no design system,
|
|
215
|
+
* and they are the two the reader touches most: one sits in every field they
|
|
216
|
+
* type into, the other appears the moment they drag across a paragraph. The
|
|
217
|
+
* selection is mixed from the brand rather than pinned to a token so it stays
|
|
218
|
+
* a wash — the text underneath keeps its own colour and its own contrast.
|
|
219
|
+
*/
|
|
220
|
+
@layer base {
|
|
221
|
+
::selection {
|
|
222
|
+
background-color: color-mix(in oklab, var(--color-brand) 24%, transparent);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
input,
|
|
226
|
+
textarea,
|
|
227
|
+
[contenteditable] {
|
|
228
|
+
caret-color: var(--color-brand);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
toneText,
|
|
9
9
|
type Tone
|
|
10
10
|
} from '../../core/tones.js';
|
|
11
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
12
11
|
|
|
13
12
|
export type AlertVariant = 'soft' | 'outline' | 'accent';
|
|
14
13
|
|
|
@@ -36,13 +35,12 @@
|
|
|
36
35
|
...rest
|
|
37
36
|
}: Props = $props();
|
|
38
37
|
|
|
39
|
-
const t = useLocale();
|
|
40
38
|
let open = $state(true);
|
|
41
39
|
|
|
42
40
|
const variants = $derived({
|
|
43
41
|
soft: `${toneSurface[tone]} border ${toneBorderSoft[tone]}`,
|
|
44
42
|
outline: `bg-bg shadow-xs border ${toneBorderSoft[tone]}`,
|
|
45
|
-
accent: `${toneSurface[tone]} border-l-
|
|
43
|
+
accent: `${toneSurface[tone]} border-l-2 ${toneBorder[tone]}`
|
|
46
44
|
});
|
|
47
45
|
|
|
48
46
|
function dismiss() {
|
|
@@ -71,7 +69,7 @@
|
|
|
71
69
|
|
|
72
70
|
<div class="flex min-w-0 flex-1 flex-col gap-1">
|
|
73
71
|
{#if title}
|
|
74
|
-
<p class="text-sm leading-snug font-semibold {toneText[tone]}">{title}</p>
|
|
72
|
+
<p class="font-heading text-sm leading-snug font-semibold {toneText[tone]}">{title}</p>
|
|
75
73
|
{/if}
|
|
76
74
|
{#if children}
|
|
77
75
|
<div class="text-[13px] leading-relaxed text-text-secondary">{@render children()}</div>
|
|
@@ -82,7 +80,7 @@
|
|
|
82
80
|
<button
|
|
83
81
|
type="button"
|
|
84
82
|
onclick={dismiss}
|
|
85
|
-
aria-label=
|
|
83
|
+
aria-label="Dismiss"
|
|
86
84
|
class="-m-1 shrink-0 rounded p-1 text-text-muted transition-colors duration-150 hover:bg-bg/60 hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
|
|
87
85
|
>
|
|
88
86
|
<svg class="size-3.5" viewBox="0 0 14 14" fill="none" aria-hidden="true">
|
|
@@ -47,6 +47,12 @@
|
|
|
47
47
|
xl: 'grid place-items-center *:size-8'
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
+
// A src that 404s left the reader with the browser's broken-image mark while
|
|
51
|
+
// the initials sat right there unused. Holding the failed URL rather than a
|
|
52
|
+
// flag means a new src is tried again on its own.
|
|
53
|
+
let failed = $state('');
|
|
54
|
+
const broken = $derived(failed !== '' && failed === src);
|
|
55
|
+
|
|
50
56
|
const initials = $derived(
|
|
51
57
|
name
|
|
52
58
|
.trim()
|
|
@@ -60,13 +66,18 @@
|
|
|
60
66
|
|
|
61
67
|
<span
|
|
62
68
|
class="inline-flex shrink-0 items-center justify-center overflow-hidden font-sans font-semibold select-none
|
|
63
|
-
{squared ? 'rounded-lg' : 'rounded-full'} {sizes[size]} {src
|
|
69
|
+
{squared ? 'rounded-lg' : 'rounded-full'} {sizes[size]} {src && !broken
|
|
64
70
|
? 'bg-bg-inset'
|
|
65
71
|
: toneSoft[tone]} {className}"
|
|
66
72
|
{...rest}
|
|
67
73
|
>
|
|
68
|
-
{#if src}
|
|
69
|
-
<img
|
|
74
|
+
{#if src && !broken}
|
|
75
|
+
<img
|
|
76
|
+
{src}
|
|
77
|
+
alt={alt ?? name}
|
|
78
|
+
onerror={() => (failed = src ?? '')}
|
|
79
|
+
class="size-full object-cover"
|
|
80
|
+
/>
|
|
70
81
|
{:else if fallback}
|
|
71
82
|
<span class={glyphs[size]}>{@render fallback()}</span>
|
|
72
83
|
{:else}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
4
|
import { toneHoverText, type Tone } from '../../core/tones.js';
|
|
5
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
6
5
|
import { iconMd } from './icon.js';
|
|
7
6
|
|
|
8
7
|
export interface BreadcrumbItem {
|
|
@@ -19,11 +18,9 @@
|
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
let { items, separator = '/', tone = 'brand', class: className = '', ...rest }: Props = $props();
|
|
22
|
-
|
|
23
|
-
const t = useLocale();
|
|
24
21
|
</script>
|
|
25
22
|
|
|
26
|
-
<nav aria-label=
|
|
23
|
+
<nav aria-label="Breadcrumb" class="font-sans text-sm {className}" {...rest}>
|
|
27
24
|
<ol class="flex flex-wrap items-center gap-1.5">
|
|
28
25
|
{#each items as item, i (item.label)}
|
|
29
26
|
<li class="flex items-center gap-1.5">
|
|
@@ -107,6 +107,10 @@
|
|
|
107
107
|
const iconClass = $derived(size === 'sm' ? iconSm : iconMd);
|
|
108
108
|
|
|
109
109
|
async function handleClick(event: MouseEvent) {
|
|
110
|
+
if (inert) {
|
|
111
|
+
event.preventDefault();
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
110
114
|
const result = onclick?.(event);
|
|
111
115
|
// Anything else is a plain handler: nothing to wait for, nothing to lock.
|
|
112
116
|
if (!(result instanceof Promise)) return;
|
|
@@ -125,7 +129,7 @@
|
|
|
125
129
|
disabled={href ? undefined : inert}
|
|
126
130
|
aria-disabled={href && inert ? 'true' : undefined}
|
|
127
131
|
aria-busy={busy ? 'true' : undefined}
|
|
128
|
-
|
|
132
|
+
tabindex={href && inert ? -1 : undefined}
|
|
129
133
|
class="{base} {focusRing} {toneRing[tone]} {variantClass} {isLink
|
|
130
134
|
? ''
|
|
131
135
|
: iconOnly
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
weekdayNames
|
|
12
12
|
} from '../../core/date.js';
|
|
13
13
|
import { calendarKeyMove } from '../../core/calendar.js';
|
|
14
|
-
import { useLocale } from '../../core/locale.svelte.js';
|
|
15
14
|
import {
|
|
16
15
|
focusRing,
|
|
17
16
|
toneFill,
|
|
@@ -53,8 +52,6 @@
|
|
|
53
52
|
class: className = ''
|
|
54
53
|
}: Props = $props();
|
|
55
54
|
|
|
56
|
-
const t = useLocale();
|
|
57
|
-
|
|
58
55
|
const selected = $derived(fromISO(value));
|
|
59
56
|
const now = today();
|
|
60
57
|
|
|
@@ -71,7 +68,7 @@
|
|
|
71
68
|
});
|
|
72
69
|
|
|
73
70
|
const days = $derived(monthGrid(view, weekStart));
|
|
74
|
-
const weekdays = $derived(weekdayNames(
|
|
71
|
+
const weekdays = $derived(weekdayNames(undefined, weekStart));
|
|
75
72
|
|
|
76
73
|
function blocked(date: Date) {
|
|
77
74
|
return isOutOfRange(date, min, max) || (isDisabled?.(date) ?? false);
|
|
@@ -119,7 +116,7 @@
|
|
|
119
116
|
<button
|
|
120
117
|
type="button"
|
|
121
118
|
onclick={() => show(addMonths(view, -1))}
|
|
122
|
-
aria-label=
|
|
119
|
+
aria-label="Previous month"
|
|
123
120
|
class="{arrow} {focusRing} {toneRing[tone]}"
|
|
124
121
|
>
|
|
125
122
|
<svg class="size-4" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
@@ -128,13 +125,13 @@
|
|
|
128
125
|
</button>
|
|
129
126
|
|
|
130
127
|
<span aria-live="polite" class="text-sm font-semibold text-text">
|
|
131
|
-
{monthLabel(view
|
|
128
|
+
{monthLabel(view)}
|
|
132
129
|
</span>
|
|
133
130
|
|
|
134
131
|
<button
|
|
135
132
|
type="button"
|
|
136
133
|
onclick={() => show(addMonths(view, 1))}
|
|
137
|
-
aria-label=
|
|
134
|
+
aria-label="Next month"
|
|
138
135
|
class="{arrow} {focusRing} {toneRing[tone]}"
|
|
139
136
|
>
|
|
140
137
|
<svg class="size-4" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
@@ -154,7 +151,7 @@
|
|
|
154
151
|
bind:this={grid}
|
|
155
152
|
role="grid"
|
|
156
153
|
tabindex="-1"
|
|
157
|
-
aria-label=
|
|
154
|
+
aria-label="Select a date"
|
|
158
155
|
onkeydown={onKeydown}
|
|
159
156
|
class="grid grid-cols-7 gap-0.5 focus:outline-none"
|
|
160
157
|
>
|
|
@@ -196,7 +193,7 @@
|
|
|
196
193
|
tone
|
|
197
194
|
]} hover:underline hover:underline-offset-2 {focusRing} {toneRing[tone]}"
|
|
198
195
|
>
|
|
199
|
-
|
|
196
|
+
Today
|
|
200
197
|
</button>
|
|
201
198
|
{/if}
|
|
202
199
|
</div>
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
|
|
49
49
|
<div
|
|
50
50
|
class="flex flex-col rounded-lg {variants[variant]}
|
|
51
|
-
{accent ? `border-l-
|
|
51
|
+
{accent ? `border-l-2 ${toneBorderLeft[tone]}` : ''}
|
|
52
52
|
{interactive
|
|
53
53
|
? `transition-shadow duration-150 ease-brand-out hover:shadow-md ${toneHoverBorder[tone]}`
|
|
54
54
|
: ''}
|