@sentropic/design-system-svelte 0.21.0 → 0.22.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.
package/dist/BarChart.svelte
CHANGED
|
@@ -25,6 +25,19 @@
|
|
|
25
25
|
height?: number;
|
|
26
26
|
orientation?: "vertical" | "horizontal";
|
|
27
27
|
label: string;
|
|
28
|
+
/**
|
|
29
|
+
* Keys of the currently selected bars (a bar's key is its `label`).
|
|
30
|
+
* CONTROLLED — the parent owns the toggle; the component never stores
|
|
31
|
+
* selection. When non-empty the selected bars stay full opacity (+ accent)
|
|
32
|
+
* and the rest dim; when empty every bar is normal. Defaults to [].
|
|
33
|
+
*/
|
|
34
|
+
selectedKeys?: string[];
|
|
35
|
+
/**
|
|
36
|
+
* Called when a bar is clicked / activated (Enter / Space) with the bar's
|
|
37
|
+
* key (its `label`). When provided the bars become focusable buttons; when
|
|
38
|
+
* omitted the chart is purely presentational (no interactivity, unchanged).
|
|
39
|
+
*/
|
|
40
|
+
onSelect?: (key: string) => void;
|
|
28
41
|
class?: string;
|
|
29
42
|
};
|
|
30
43
|
|
|
@@ -34,6 +47,8 @@
|
|
|
34
47
|
height = 240,
|
|
35
48
|
orientation = "vertical",
|
|
36
49
|
label,
|
|
50
|
+
selectedKeys = [],
|
|
51
|
+
onSelect,
|
|
37
52
|
class: className
|
|
38
53
|
}: BarChartProps = $props();
|
|
39
54
|
|
|
@@ -75,6 +90,20 @@
|
|
|
75
90
|
|
|
76
91
|
let hoveredIndex: number | null = $state(null);
|
|
77
92
|
|
|
93
|
+
// Selection (controlled): fast lookup + "is any bar selected" flag. Only when
|
|
94
|
+
// something is selected do we dim the non-selected bars.
|
|
95
|
+
const selectedSet = $derived(new Set<string>(selectedKeys));
|
|
96
|
+
const hasSelection = $derived(selectedSet.size > 0);
|
|
97
|
+
const interactive = $derived(typeof onSelect === "function");
|
|
98
|
+
|
|
99
|
+
function handleBarKeydown(key: string, e: KeyboardEvent) {
|
|
100
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
101
|
+
// preventDefault on Space so it activates rather than scrolling the page.
|
|
102
|
+
e.preventDefault();
|
|
103
|
+
onSelect?.(key);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
78
107
|
const scales = $derived.by(() => {
|
|
79
108
|
const values = data.map((d) => d.value);
|
|
80
109
|
const minRaw = Math.min(0, ...values);
|
|
@@ -272,15 +301,29 @@
|
|
|
272
301
|
{/each}
|
|
273
302
|
|
|
274
303
|
<!-- bars -->
|
|
304
|
+
<!-- A bar becomes an interactive button only when `onSelect` is provided;
|
|
305
|
+
the role + tabindex are then dynamic, which the static a11y check cannot
|
|
306
|
+
verify, hence the targeted ignore (mirrors SelectableRow). -->
|
|
275
307
|
{#each bars as bar, i (bar.datum.label)}
|
|
308
|
+
{@const isSelected = selectedSet.has(bar.datum.label)}
|
|
309
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
276
310
|
<rect
|
|
277
311
|
class="st-barChart__bar st-barChart__bar--{bar.tone}"
|
|
312
|
+
class:st-barChart__bar--selected={isSelected}
|
|
313
|
+
class:st-barChart__bar--dim={hasSelection && !isSelected}
|
|
314
|
+
class:st-barChart__bar--interactive={interactive}
|
|
278
315
|
x={bar.x}
|
|
279
316
|
y={bar.y}
|
|
280
317
|
width={bar.width}
|
|
281
318
|
height={bar.height}
|
|
282
319
|
rx="2"
|
|
283
320
|
data-chart-index={i}
|
|
321
|
+
role={interactive ? "button" : undefined}
|
|
322
|
+
tabindex={interactive ? 0 : undefined}
|
|
323
|
+
aria-pressed={interactive ? isSelected : undefined}
|
|
324
|
+
aria-label={interactive ? `${bar.datum.label}: ${bar.datum.value}` : undefined}
|
|
325
|
+
onclick={interactive ? () => onSelect?.(bar.datum.label) : undefined}
|
|
326
|
+
onkeydown={interactive ? (e) => handleBarKeydown(bar.datum.label, e) : undefined}
|
|
284
327
|
/>
|
|
285
328
|
{/each}
|
|
286
329
|
</svg>
|
|
@@ -339,13 +382,38 @@
|
|
|
339
382
|
|
|
340
383
|
.st-barChart__bar {
|
|
341
384
|
cursor: pointer;
|
|
342
|
-
transition: opacity 120ms ease;
|
|
385
|
+
transition: opacity var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
|
|
343
386
|
}
|
|
344
387
|
|
|
345
388
|
.st-barChart__bar:hover {
|
|
346
389
|
opacity: 0.82;
|
|
347
390
|
}
|
|
348
391
|
|
|
392
|
+
/* Interactive (onSelect provided): the bar is a keyboard-activable button. */
|
|
393
|
+
.st-barChart__bar--interactive:focus-visible {
|
|
394
|
+
outline: 2px solid var(--st-semantic-border-interactive, var(--st-semantic-action-primary));
|
|
395
|
+
outline-offset: 1px;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* Non-selected bars are dimmed while a selection is active. */
|
|
399
|
+
.st-barChart__bar--dim {
|
|
400
|
+
opacity: 0.45;
|
|
401
|
+
}
|
|
402
|
+
/* Hover still lifts a dimmed bar so it stays explorable. */
|
|
403
|
+
.st-barChart__bar--dim:hover {
|
|
404
|
+
opacity: 0.7;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/* Selected bar: full opacity + a contrast-safe accent stroke (two signals,
|
|
408
|
+
never a font/size reflow). Outranks the dim rule. */
|
|
409
|
+
.st-barChart__bar--selected,
|
|
410
|
+
.st-barChart__bar--selected:hover {
|
|
411
|
+
opacity: 1;
|
|
412
|
+
stroke: var(--st-semantic-border-interactive, var(--st-semantic-action-primary));
|
|
413
|
+
stroke-width: 2;
|
|
414
|
+
paint-order: stroke;
|
|
415
|
+
}
|
|
416
|
+
|
|
349
417
|
.st-barChart__bar--category1 { fill: var(--st-semantic-data-category1); }
|
|
350
418
|
.st-barChart__bar--category2 { fill: var(--st-semantic-data-category2); }
|
|
351
419
|
.st-barChart__bar--category3 { fill: var(--st-semantic-data-category3); }
|
|
@@ -379,4 +447,8 @@
|
|
|
379
447
|
.st-barChart__tooltipValue {
|
|
380
448
|
opacity: 0.85;
|
|
381
449
|
}
|
|
450
|
+
|
|
451
|
+
@media (prefers-reduced-motion: reduce) {
|
|
452
|
+
.st-barChart__bar { transition: none; }
|
|
453
|
+
}
|
|
382
454
|
</style>
|
|
@@ -10,6 +10,19 @@ type BarChartProps = {
|
|
|
10
10
|
height?: number;
|
|
11
11
|
orientation?: "vertical" | "horizontal";
|
|
12
12
|
label: string;
|
|
13
|
+
/**
|
|
14
|
+
* Keys of the currently selected bars (a bar's key is its `label`).
|
|
15
|
+
* CONTROLLED — the parent owns the toggle; the component never stores
|
|
16
|
+
* selection. When non-empty the selected bars stay full opacity (+ accent)
|
|
17
|
+
* and the rest dim; when empty every bar is normal. Defaults to [].
|
|
18
|
+
*/
|
|
19
|
+
selectedKeys?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Called when a bar is clicked / activated (Enter / Space) with the bar's
|
|
22
|
+
* key (its `label`). When provided the bars become focusable buttons; when
|
|
23
|
+
* omitted the chart is purely presentational (no interactivity, unchanged).
|
|
24
|
+
*/
|
|
25
|
+
onSelect?: (key: string) => void;
|
|
13
26
|
class?: string;
|
|
14
27
|
};
|
|
15
28
|
declare const BarChart: import("svelte").Component<BarChartProps, {}, "">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BarChart.svelte.d.ts","sourceRoot":"","sources":["../src/lib/BarChart.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,MAAM,YAAY,GACpB,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,CAAC;AAEhB,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,CAAC;AAMF,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;
|
|
1
|
+
{"version":3,"file":"BarChart.svelte.d.ts","sourceRoot":"","sources":["../src/lib/BarChart.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,MAAM,YAAY,GACpB,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,CAAC;AAEhB,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,CAAC;AAMF,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAwOJ,QAAA,MAAM,QAAQ,mDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
|