@dorsk/tsumikit 0.17.0 → 0.18.0
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.
|
@@ -297,6 +297,25 @@
|
|
|
297
297
|
border-color: var(--ok);
|
|
298
298
|
filter: brightness(1.08);
|
|
299
299
|
}
|
|
300
|
+
/* Other tones on a primary action tint the accent fill rather than repaint the
|
|
301
|
+
text, so the on-accent foreground stays readable (bare tone-as-text would be
|
|
302
|
+
accent-on-accent). success keeps its own filled guard above. */
|
|
303
|
+
.btn-primary.btn-tone-accent,
|
|
304
|
+
.btn-primary.btn-tone-info,
|
|
305
|
+
.btn-primary.btn-tone-warn,
|
|
306
|
+
.btn-primary.btn-tone-danger {
|
|
307
|
+
background: color-mix(in srgb, var(--btn-tone) 35%, var(--accent));
|
|
308
|
+
border-color: color-mix(in srgb, var(--btn-tone) 35%, var(--accent));
|
|
309
|
+
color: var(--text-on-accent);
|
|
310
|
+
}
|
|
311
|
+
.btn-primary.btn-tone-accent:hover:not(:disabled),
|
|
312
|
+
.btn-primary.btn-tone-info:hover:not(:disabled),
|
|
313
|
+
.btn-primary.btn-tone-warn:hover:not(:disabled),
|
|
314
|
+
.btn-primary.btn-tone-danger:hover:not(:disabled) {
|
|
315
|
+
background: color-mix(in srgb, var(--btn-tone) 35%, var(--accent));
|
|
316
|
+
border-color: color-mix(in srgb, var(--btn-tone) 35%, var(--accent));
|
|
317
|
+
filter: brightness(1.08);
|
|
318
|
+
}
|
|
300
319
|
|
|
301
320
|
/* Icon-only buttons (IconButton). Square box = consistent 2.25rem tap target. */
|
|
302
321
|
.btn-icon {
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export interface BreadcrumbItem {
|
|
3
|
+
label: string;
|
|
4
|
+
href?: string;
|
|
5
|
+
}
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<script lang="ts">
|
|
9
|
+
// Navigation trail (e.g. "Musique > Artist > Album > Track"). The last item —
|
|
10
|
+
// or any item without an `href` — renders unlinked and is marked
|
|
11
|
+
// aria-current="page". When the trail exceeds `maxItems` the middle collapses
|
|
12
|
+
// to an ellipsis, always keeping the first item and the tail. `separator` is a
|
|
13
|
+
// snippet for custom markup, else a char via the `char` prop.
|
|
14
|
+
import type { Snippet } from 'svelte';
|
|
15
|
+
import Icon from '../atoms/Icon.svelte';
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
items,
|
|
19
|
+
char,
|
|
20
|
+
separator,
|
|
21
|
+
maxItems = 0
|
|
22
|
+
}: {
|
|
23
|
+
items: BreadcrumbItem[];
|
|
24
|
+
/** Separator character; ignored when the `separator` snippet is set. */
|
|
25
|
+
char?: string;
|
|
26
|
+
separator?: Snippet;
|
|
27
|
+
/** Collapse the middle to an ellipsis when the trail is longer than this
|
|
28
|
+
* (0 = never collapse). Keeps the first item and the last `maxItems - 1`. */
|
|
29
|
+
maxItems?: number;
|
|
30
|
+
} = $props();
|
|
31
|
+
|
|
32
|
+
type Crumb = BreadcrumbItem | { ellipsis: true };
|
|
33
|
+
|
|
34
|
+
const shown = $derived<Crumb[]>(
|
|
35
|
+
maxItems > 0 && items.length > maxItems
|
|
36
|
+
? [items[0], { ellipsis: true }, ...items.slice(items.length - (maxItems - 1))]
|
|
37
|
+
: items
|
|
38
|
+
);
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<nav aria-label="breadcrumb" data-tsu="Breadcrumb">
|
|
42
|
+
<ol class="crumbs">
|
|
43
|
+
{#each shown as item, i (i)}
|
|
44
|
+
<li class="crumb">
|
|
45
|
+
{#if 'ellipsis' in item}
|
|
46
|
+
<span class="ellipsis" aria-hidden="true">…</span>
|
|
47
|
+
{:else if item.href && i < shown.length - 1}
|
|
48
|
+
<a class="link" href={item.href}>{item.label}</a>
|
|
49
|
+
{:else}
|
|
50
|
+
<span class="current" aria-current="page">{item.label}</span>
|
|
51
|
+
{/if}
|
|
52
|
+
{#if i < shown.length - 1}
|
|
53
|
+
<span class="sep" aria-hidden="true">
|
|
54
|
+
{#if separator}{@render separator()}{:else if char}{char}{:else}<Icon
|
|
55
|
+
name="chevron-right"
|
|
56
|
+
size={14}
|
|
57
|
+
/>{/if}
|
|
58
|
+
</span>
|
|
59
|
+
{/if}
|
|
60
|
+
</li>
|
|
61
|
+
{/each}
|
|
62
|
+
</ol>
|
|
63
|
+
</nav>
|
|
64
|
+
|
|
65
|
+
<style>
|
|
66
|
+
.crumbs {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-wrap: wrap;
|
|
69
|
+
align-items: center;
|
|
70
|
+
gap: var(--sp-1);
|
|
71
|
+
margin: 0;
|
|
72
|
+
padding: 0;
|
|
73
|
+
list-style: none;
|
|
74
|
+
font-size: var(--fs-sm);
|
|
75
|
+
}
|
|
76
|
+
.crumb {
|
|
77
|
+
display: inline-flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
gap: var(--sp-1);
|
|
80
|
+
min-width: 0;
|
|
81
|
+
}
|
|
82
|
+
.link {
|
|
83
|
+
color: var(--text-muted);
|
|
84
|
+
text-decoration: none;
|
|
85
|
+
white-space: nowrap;
|
|
86
|
+
overflow: hidden;
|
|
87
|
+
text-overflow: ellipsis;
|
|
88
|
+
max-width: 16ch;
|
|
89
|
+
transition: color 0.12s var(--ease);
|
|
90
|
+
}
|
|
91
|
+
.link:hover {
|
|
92
|
+
color: var(--text);
|
|
93
|
+
text-decoration: underline;
|
|
94
|
+
}
|
|
95
|
+
.current {
|
|
96
|
+
color: var(--text);
|
|
97
|
+
font-weight: var(--fw-medium);
|
|
98
|
+
white-space: nowrap;
|
|
99
|
+
overflow: hidden;
|
|
100
|
+
text-overflow: ellipsis;
|
|
101
|
+
max-width: 24ch;
|
|
102
|
+
}
|
|
103
|
+
.ellipsis {
|
|
104
|
+
color: var(--text-muted);
|
|
105
|
+
}
|
|
106
|
+
.sep {
|
|
107
|
+
display: inline-flex;
|
|
108
|
+
align-items: center;
|
|
109
|
+
color: var(--text-subtle, var(--text-muted));
|
|
110
|
+
}
|
|
111
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface BreadcrumbItem {
|
|
2
|
+
label: string;
|
|
3
|
+
href?: string;
|
|
4
|
+
}
|
|
5
|
+
import type { Snippet } from 'svelte';
|
|
6
|
+
type $$ComponentProps = {
|
|
7
|
+
items: BreadcrumbItem[];
|
|
8
|
+
/** Separator character; ignored when the `separator` snippet is set. */
|
|
9
|
+
char?: string;
|
|
10
|
+
separator?: Snippet;
|
|
11
|
+
/** Collapse the middle to an ellipsis when the trail is longer than this
|
|
12
|
+
* (0 = never collapse). Keeps the first item and the last `maxItems - 1`. */
|
|
13
|
+
maxItems?: number;
|
|
14
|
+
};
|
|
15
|
+
declare const Breadcrumb: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
16
|
+
type Breadcrumb = ReturnType<typeof Breadcrumb>;
|
|
17
|
+
export default Breadcrumb;
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export { default as NavSection } from './components/layouts/NavSection.svelte';
|
|
|
26
26
|
export { default as ResizablePanel } from './components/layouts/ResizablePanel.svelte';
|
|
27
27
|
export { default as Stack } from './components/layouts/Stack.svelte';
|
|
28
28
|
export { type AccordionItem, default as Accordion, } from './components/molecules/Accordion.svelte';
|
|
29
|
+
export { type BreadcrumbItem, default as Breadcrumb, } from './components/molecules/Breadcrumb.svelte';
|
|
29
30
|
export { default as CodeBlock } from './components/molecules/CodeBlock.svelte';
|
|
30
31
|
export { default as CopyButton } from './components/molecules/CopyButton.svelte';
|
|
31
32
|
export { default as Dropzone } from './components/molecules/Dropzone.svelte';
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ export { default as NavSection } from './components/layouts/NavSection.svelte';
|
|
|
33
33
|
export { default as ResizablePanel } from './components/layouts/ResizablePanel.svelte';
|
|
34
34
|
export { default as Stack } from './components/layouts/Stack.svelte';
|
|
35
35
|
export { default as Accordion, } from './components/molecules/Accordion.svelte';
|
|
36
|
+
export { default as Breadcrumb, } from './components/molecules/Breadcrumb.svelte';
|
|
36
37
|
export { default as CodeBlock } from './components/molecules/CodeBlock.svelte';
|
|
37
38
|
export { default as CopyButton } from './components/molecules/CopyButton.svelte';
|
|
38
39
|
export { default as Dropzone } from './components/molecules/Dropzone.svelte';
|
package/package.json
CHANGED