@robr0/design-system 0.11.0 → 0.13.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/README.md +4 -4
- package/charts.d.ts +1 -0
- package/charts.js +2 -0
- package/components/AppLayout/AppLayout.d.ts +7 -1
- package/components/AppLayout/AppLayout.js +2 -1
- package/components/AppSidebar/AppSidebar.css +104 -40
- package/components/AppSidebar/AppSidebar.d.ts +14 -1
- package/components/AppSidebar/AppSidebar.js +26 -17
- package/components/AvatarGroup/AvatarGroup.css +61 -0
- package/components/AvatarGroup/AvatarGroup.d.ts +32 -0
- package/components/AvatarGroup/AvatarGroup.js +31 -0
- package/components/Badge/Badge.css +4 -5
- package/components/Chart/AreaChart.d.ts +5 -1
- package/components/Chart/AreaChart.js +5 -4
- package/components/Chart/BarChart.d.ts +3 -1
- package/components/Chart/BarChart.js +3 -3
- package/components/Chart/Chart.css +45 -0
- package/components/Chart/ComboChart.d.ts +40 -0
- package/components/Chart/ComboChart.js +142 -0
- package/components/Chart/LineChart.d.ts +3 -1
- package/components/Chart/LineChart.js +3 -3
- package/components/Chart/PieChart.d.ts +3 -1
- package/components/Chart/PieChart.js +3 -3
- package/components/Chart/RadarChart.d.ts +3 -1
- package/components/Chart/RadarChart.js +3 -3
- package/components/Chart/RadialChart.d.ts +7 -1
- package/components/Chart/RadialChart.js +51 -43
- package/components/Chart/ScatterChart.d.ts +3 -1
- package/components/Chart/ScatterChart.js +3 -3
- package/components/Chart/StackedBarChart.d.ts +3 -1
- package/components/Chart/StackedBarChart.js +3 -3
- package/components/Chart/Treemap.d.ts +3 -1
- package/components/Chart/Treemap.js +3 -3
- package/components/Chart/palette.js +1 -3
- package/components/FilterBar/FilterBar.css +202 -0
- package/components/FilterBar/FilterBar.d.ts +55 -0
- package/components/FilterBar/FilterBar.js +249 -0
- package/components/FunnelChart/FunnelChart.css +41 -0
- package/components/FunnelChart/FunnelChart.d.ts +40 -0
- package/components/FunnelChart/FunnelChart.js +48 -0
- package/components/Gauge/Gauge.css +93 -0
- package/components/Gauge/Gauge.d.ts +56 -0
- package/components/Gauge/Gauge.js +95 -0
- package/components/LegendTile/LegendTile.css +60 -0
- package/components/LegendTile/LegendTile.d.ts +30 -0
- package/components/LegendTile/LegendTile.js +21 -0
- package/components/Panel/Panel.css +26 -0
- package/components/Panel/Panel.d.ts +22 -0
- package/components/Panel/Panel.js +19 -0
- package/components/SplitPane/SplitPane.css +106 -0
- package/components/SplitPane/SplitPane.d.ts +36 -0
- package/components/SplitPane/SplitPane.js +130 -0
- package/components/Stat/Stat.css +35 -2
- package/components/Stat/Stat.d.ts +3 -1
- package/components/Stat/Stat.js +7 -1
- package/components/StreamingText/StreamingText.css +40 -0
- package/components/StreamingText/StreamingText.d.ts +44 -0
- package/components/StreamingText/StreamingText.js +61 -0
- package/components/registry.json +73 -0
- package/components/registry.json.d.ts +73 -0
- package/components/registry.json.js +1 -1
- package/index.d.ts +8 -0
- package/index.js +16 -0
- package/package.json +1 -1
- package/tokens/motion.d.ts +7 -3
- package/tokens/motion.js +3 -1
- package/tokens/registry.json +4 -1
- package/tokens/registry.json.d.ts +4 -1
- package/tokens/registry.json.js +1 -1
- package/tokens/tokens-dark.css +3 -0
- package/tokens/tokens-light.css +11 -0
- package/tokens/tokens-primitives.css +2 -0
- package/tokens/tokens-typography.css +12 -5
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
|
+
import React, { useState, useRef } from "react";
|
|
4
|
+
import "./SplitPane.css";
|
|
5
|
+
const KEY_STEP = 2;
|
|
6
|
+
const KEY_STEP_LARGE = 10;
|
|
7
|
+
const SplitPane = React.forwardRef(
|
|
8
|
+
({
|
|
9
|
+
children,
|
|
10
|
+
direction = "horizontal",
|
|
11
|
+
split,
|
|
12
|
+
defaultSplit = 50,
|
|
13
|
+
minSplit = 10,
|
|
14
|
+
maxSplit = 90,
|
|
15
|
+
onSplitChange,
|
|
16
|
+
separatorLabel = "Resize panes",
|
|
17
|
+
className = "",
|
|
18
|
+
...rest
|
|
19
|
+
}, ref) => {
|
|
20
|
+
const baseClass = "ds-split-pane";
|
|
21
|
+
const [uncontrolledSplit, setUncontrolledSplit] = useState(defaultSplit);
|
|
22
|
+
const [dragging, setDragging] = useState(false);
|
|
23
|
+
const draggingRef = useRef(false);
|
|
24
|
+
const internalRef = useRef(null);
|
|
25
|
+
const setRef = (node) => {
|
|
26
|
+
internalRef.current = node;
|
|
27
|
+
if (typeof ref === "function") ref(node);
|
|
28
|
+
else if (ref) ref.current = node;
|
|
29
|
+
};
|
|
30
|
+
const clamp = (value) => Math.min(Math.max(value, minSplit), maxSplit);
|
|
31
|
+
const currentSplit = clamp(split ?? uncontrolledSplit);
|
|
32
|
+
const applySplit = (value) => {
|
|
33
|
+
const next = clamp(value);
|
|
34
|
+
if (split === void 0) setUncontrolledSplit(next);
|
|
35
|
+
onSplitChange?.(next);
|
|
36
|
+
};
|
|
37
|
+
const splitFromPointer = (e) => {
|
|
38
|
+
const rect = internalRef.current?.getBoundingClientRect();
|
|
39
|
+
if (!rect) return;
|
|
40
|
+
const fraction = direction === "horizontal" ? (e.clientX - rect.left) / rect.width : (e.clientY - rect.top) / rect.height;
|
|
41
|
+
applySplit(fraction * 100);
|
|
42
|
+
};
|
|
43
|
+
const handlePointerDown = (e) => {
|
|
44
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
45
|
+
draggingRef.current = true;
|
|
46
|
+
setDragging(true);
|
|
47
|
+
splitFromPointer(e);
|
|
48
|
+
};
|
|
49
|
+
const handlePointerMove = (e) => {
|
|
50
|
+
if (!draggingRef.current) return;
|
|
51
|
+
splitFromPointer(e);
|
|
52
|
+
};
|
|
53
|
+
const handlePointerUp = (e) => {
|
|
54
|
+
if (e.currentTarget.hasPointerCapture(e.pointerId)) {
|
|
55
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
56
|
+
}
|
|
57
|
+
draggingRef.current = false;
|
|
58
|
+
setDragging(false);
|
|
59
|
+
};
|
|
60
|
+
const handleKeyDown = (e) => {
|
|
61
|
+
const step = e.shiftKey ? KEY_STEP_LARGE : KEY_STEP;
|
|
62
|
+
const shrinkKey = direction === "horizontal" ? "ArrowLeft" : "ArrowUp";
|
|
63
|
+
const growKey = direction === "horizontal" ? "ArrowRight" : "ArrowDown";
|
|
64
|
+
switch (e.key) {
|
|
65
|
+
case shrinkKey:
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
applySplit(currentSplit - step);
|
|
68
|
+
break;
|
|
69
|
+
case growKey:
|
|
70
|
+
e.preventDefault();
|
|
71
|
+
applySplit(currentSplit + step);
|
|
72
|
+
break;
|
|
73
|
+
case "Home":
|
|
74
|
+
e.preventDefault();
|
|
75
|
+
applySplit(minSplit);
|
|
76
|
+
break;
|
|
77
|
+
case "End":
|
|
78
|
+
e.preventDefault();
|
|
79
|
+
applySplit(maxSplit);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const classes = [
|
|
84
|
+
baseClass,
|
|
85
|
+
`${baseClass}--${direction}`,
|
|
86
|
+
dragging && `${baseClass}--dragging`,
|
|
87
|
+
className
|
|
88
|
+
].filter(Boolean).join(" ");
|
|
89
|
+
const [first, second] = React.Children.toArray(children);
|
|
90
|
+
return /* @__PURE__ */ jsxs(
|
|
91
|
+
"div",
|
|
92
|
+
{
|
|
93
|
+
...rest,
|
|
94
|
+
ref: setRef,
|
|
95
|
+
className: classes,
|
|
96
|
+
style: {
|
|
97
|
+
"--ds-split-pane-split": `${currentSplit}%`,
|
|
98
|
+
...rest.style
|
|
99
|
+
},
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ jsx("div", { className: `${baseClass}__pane ${baseClass}__pane--first`, children: first }),
|
|
102
|
+
/* @__PURE__ */ jsx(
|
|
103
|
+
"div",
|
|
104
|
+
{
|
|
105
|
+
className: `${baseClass}__separator`,
|
|
106
|
+
role: "separator",
|
|
107
|
+
tabIndex: 0,
|
|
108
|
+
"aria-label": separatorLabel,
|
|
109
|
+
"aria-orientation": direction === "horizontal" ? "vertical" : "horizontal",
|
|
110
|
+
"aria-valuenow": Math.round(currentSplit),
|
|
111
|
+
"aria-valuemin": Math.round(minSplit),
|
|
112
|
+
"aria-valuemax": Math.round(maxSplit),
|
|
113
|
+
onPointerDown: handlePointerDown,
|
|
114
|
+
onPointerMove: handlePointerMove,
|
|
115
|
+
onPointerUp: handlePointerUp,
|
|
116
|
+
onPointerCancel: handlePointerUp,
|
|
117
|
+
onKeyDown: handleKeyDown,
|
|
118
|
+
children: /* @__PURE__ */ jsx("span", { className: `${baseClass}__grip`, "aria-hidden": "true" })
|
|
119
|
+
}
|
|
120
|
+
),
|
|
121
|
+
/* @__PURE__ */ jsx("div", { className: `${baseClass}__pane ${baseClass}__pane--second`, children: second })
|
|
122
|
+
]
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
SplitPane.displayName = "SplitPane";
|
|
128
|
+
export {
|
|
129
|
+
SplitPane
|
|
130
|
+
};
|
package/components/Stat/Stat.css
CHANGED
|
@@ -65,18 +65,51 @@
|
|
|
65
65
|
line-height: 1;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/* The trend tokens are theme-split for contrast: deep status inks on
|
|
69
|
+
light surfaces, the mint/coral accents on dark ones. */
|
|
68
70
|
.ds-stat__delta--up {
|
|
69
|
-
color: var(--color-
|
|
71
|
+
color: var(--color-trend-up);
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
.ds-stat__delta--down {
|
|
73
|
-
color: var(--color-
|
|
75
|
+
color: var(--color-trend-down);
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
.ds-stat__delta--neutral {
|
|
77
79
|
color: var(--color-text-tertiary);
|
|
78
80
|
}
|
|
79
81
|
|
|
82
|
+
/* ============================================
|
|
83
|
+
INLINE DELTA — delta to the right of the
|
|
84
|
+
value, bottom-aligned to its baseline
|
|
85
|
+
============================================ */
|
|
86
|
+
|
|
87
|
+
.ds-stat--delta-inline {
|
|
88
|
+
display: grid;
|
|
89
|
+
grid-template-columns: auto 1fr;
|
|
90
|
+
grid-template-areas:
|
|
91
|
+
'value delta'
|
|
92
|
+
'label label';
|
|
93
|
+
column-gap: var(--gap-sm);
|
|
94
|
+
row-gap: var(--gap-xxs);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.ds-stat--delta-inline .ds-stat__value {
|
|
98
|
+
grid-area: value;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.ds-stat--delta-inline .ds-stat__label {
|
|
102
|
+
grid-area: label;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.ds-stat--delta-inline .ds-stat__delta {
|
|
106
|
+
grid-area: delta;
|
|
107
|
+
align-self: end;
|
|
108
|
+
justify-self: start;
|
|
109
|
+
/* Optical baseline: compensates the display value's half-leading. */
|
|
110
|
+
margin-bottom: var(--gap-xs);
|
|
111
|
+
}
|
|
112
|
+
|
|
80
113
|
/* Icons take the colour of the text around them. Explicit, not just
|
|
81
114
|
inherited by default: a consumer stylesheet that sets a colour on
|
|
82
115
|
.material-symbols-rounded itself (a common global default) would
|
|
@@ -7,6 +7,8 @@ export interface StatProps {
|
|
|
7
7
|
delta?: string;
|
|
8
8
|
/** Direction of the delta — colours it and adds an arrow */
|
|
9
9
|
trend?: 'up' | 'down' | 'neutral';
|
|
10
|
+
/** Where the delta sits: stacked below the label, or inline to the right of the value, bottom-aligned */
|
|
11
|
+
deltaPlacement?: 'stacked' | 'inline';
|
|
10
12
|
/** Stat size */
|
|
11
13
|
size?: 'default' | 'large';
|
|
12
14
|
/** Additional CSS classes */
|
|
@@ -16,4 +18,4 @@ export interface StatProps {
|
|
|
16
18
|
* Stat component — a single headline metric with a label and an
|
|
17
19
|
* optional trend delta. Compose several in a row for a metrics band.
|
|
18
20
|
*/
|
|
19
|
-
export declare const Stat: ({ value, label, delta, trend, size, className, }: StatProps) => import("react").JSX.Element;
|
|
21
|
+
export declare const Stat: ({ value, label, delta, trend, deltaPlacement, size, className, }: StatProps) => import("react").JSX.Element;
|
package/components/Stat/Stat.js
CHANGED
|
@@ -11,11 +11,17 @@ const Stat = ({
|
|
|
11
11
|
label,
|
|
12
12
|
delta,
|
|
13
13
|
trend = "neutral",
|
|
14
|
+
deltaPlacement = "stacked",
|
|
14
15
|
size = "default",
|
|
15
16
|
className = ""
|
|
16
17
|
}) => {
|
|
17
18
|
const baseClass = "ds-stat";
|
|
18
|
-
const classes = [
|
|
19
|
+
const classes = [
|
|
20
|
+
baseClass,
|
|
21
|
+
`${baseClass}--${size}`,
|
|
22
|
+
deltaPlacement === "inline" ? `${baseClass}--delta-inline` : "",
|
|
23
|
+
className
|
|
24
|
+
].filter(Boolean).join(" ");
|
|
19
25
|
return /* @__PURE__ */ jsxs("div", { className: classes, children: [
|
|
20
26
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__value`, children: value }),
|
|
21
27
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: label }),
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* ============================================
|
|
2
|
+
STREAMING TEXT COMPONENT
|
|
3
|
+
Progressive reveal for text arriving in
|
|
4
|
+
chunks, with a blinking cursor. Inherits the
|
|
5
|
+
surrounding typography — the reveal is not a
|
|
6
|
+
text style of its own.
|
|
7
|
+
============================================ */
|
|
8
|
+
|
|
9
|
+
/* Base */
|
|
10
|
+
|
|
11
|
+
.ds-streaming-text {
|
|
12
|
+
white-space: pre-wrap;
|
|
13
|
+
overflow-wrap: break-word;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* Cursor */
|
|
17
|
+
|
|
18
|
+
.ds-streaming-text__cursor {
|
|
19
|
+
display: inline-block;
|
|
20
|
+
width: 0.55em;
|
|
21
|
+
height: 1em;
|
|
22
|
+
margin-left: 0.1em;
|
|
23
|
+
vertical-align: text-bottom;
|
|
24
|
+
border-radius: var(--radius-xxs);
|
|
25
|
+
background-color: currentColor;
|
|
26
|
+
animation: ds-streaming-text-blink var(--motion-duration-loop-spin) var(--motion-ease-standard)
|
|
27
|
+
infinite;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@keyframes ds-streaming-text-blink {
|
|
31
|
+
0%,
|
|
32
|
+
45% {
|
|
33
|
+
opacity: 1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
55%,
|
|
37
|
+
100% {
|
|
38
|
+
opacity: 0.15;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
/** Props owned by StreamingText itself — everything else falls through to the root span. */
|
|
3
|
+
type StreamingTextOwnProps = {
|
|
4
|
+
/**
|
|
5
|
+
* The text received so far. Grow it across renders as chunks arrive; the
|
|
6
|
+
* reveal animates through the appended part. A value that does not extend
|
|
7
|
+
* the previous one is treated as a new message and reveals from the start.
|
|
8
|
+
*/
|
|
9
|
+
text: string;
|
|
10
|
+
/**
|
|
11
|
+
* Whether the source is still producing text. Keeps the cursor visible
|
|
12
|
+
* between chunks, when the reveal has caught up but more may arrive.
|
|
13
|
+
*/
|
|
14
|
+
streaming?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Milliseconds between reveal steps. The reveal adds more characters per
|
|
17
|
+
* step the further it falls behind, so a large chunk catches up instead of
|
|
18
|
+
* typing for seconds.
|
|
19
|
+
*/
|
|
20
|
+
charIntervalMs?: number;
|
|
21
|
+
/** Shows the blinking cursor while streaming or revealing. */
|
|
22
|
+
cursor?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Fires once when the reveal catches up with `text` after `streaming` has
|
|
25
|
+
* ended — the moment the message is fully on screen.
|
|
26
|
+
*/
|
|
27
|
+
onRevealComplete?: () => void;
|
|
28
|
+
/** Additional CSS classes */
|
|
29
|
+
className?: string;
|
|
30
|
+
};
|
|
31
|
+
export interface StreamingTextProps extends StreamingTextOwnProps, Omit<React.ComponentPropsWithoutRef<'span'>, keyof StreamingTextOwnProps | 'children'> {
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* StreamingText — the reveal for text that arrives in chunks: an LLM
|
|
35
|
+
* response typing itself out, with a cursor that blinks while more is
|
|
36
|
+
* coming. Feed it the accumulated text on every render and it animates
|
|
37
|
+
* through what was appended, catching up faster the further behind it
|
|
38
|
+
* falls. Under `prefers-reduced-motion` the reveal is skipped and each
|
|
39
|
+
* chunk appears whole. Announcement is the container's job — pair it with
|
|
40
|
+
* an `aria-live` region when the surrounding UI does not already announce
|
|
41
|
+
* the message.
|
|
42
|
+
*/
|
|
43
|
+
export declare const StreamingText: React.ForwardRefExoticComponent<StreamingTextProps & React.RefAttributes<HTMLSpanElement>>;
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
|
+
import React, { useState, useRef, useEffect } from "react";
|
|
4
|
+
import { MOTION_STREAM_CHAR_INTERVAL_MS } from "../../tokens/motion.js";
|
|
5
|
+
import "./StreamingText.css";
|
|
6
|
+
const StreamingText = React.forwardRef(
|
|
7
|
+
({
|
|
8
|
+
text,
|
|
9
|
+
streaming = false,
|
|
10
|
+
charIntervalMs = MOTION_STREAM_CHAR_INTERVAL_MS,
|
|
11
|
+
cursor = true,
|
|
12
|
+
onRevealComplete,
|
|
13
|
+
className = "",
|
|
14
|
+
...rest
|
|
15
|
+
}, ref) => {
|
|
16
|
+
const baseClass = "ds-streaming-text";
|
|
17
|
+
const [revealed, setRevealed] = useState(text.length);
|
|
18
|
+
const previousText = useRef(text);
|
|
19
|
+
const completed = useRef(false);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!text.startsWith(previousText.current)) {
|
|
22
|
+
setRevealed(0);
|
|
23
|
+
completed.current = false;
|
|
24
|
+
}
|
|
25
|
+
previousText.current = text;
|
|
26
|
+
}, [text]);
|
|
27
|
+
const caughtUp = revealed >= text.length;
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (caughtUp) return;
|
|
30
|
+
completed.current = false;
|
|
31
|
+
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
|
32
|
+
setRevealed(text.length);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const interval = setInterval(() => {
|
|
36
|
+
setRevealed((current) => {
|
|
37
|
+
const pending = text.length - current;
|
|
38
|
+
if (pending <= 0) return current;
|
|
39
|
+
return current + Math.max(1, Math.round(pending / 20));
|
|
40
|
+
});
|
|
41
|
+
}, charIntervalMs);
|
|
42
|
+
return () => clearInterval(interval);
|
|
43
|
+
}, [text, caughtUp, charIntervalMs]);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (caughtUp && !streaming && text.length > 0 && !completed.current) {
|
|
46
|
+
completed.current = true;
|
|
47
|
+
onRevealComplete?.();
|
|
48
|
+
}
|
|
49
|
+
}, [caughtUp, streaming, text, onRevealComplete]);
|
|
50
|
+
const showCursor = cursor && (streaming || !caughtUp);
|
|
51
|
+
const classes = [baseClass, className].filter(Boolean).join(" ");
|
|
52
|
+
return /* @__PURE__ */ jsxs("span", { ...rest, ref, className: classes, children: [
|
|
53
|
+
caughtUp ? text : text.slice(0, revealed),
|
|
54
|
+
showCursor && /* @__PURE__ */ jsx("span", { className: `${baseClass}__cursor`, "aria-hidden": "true" })
|
|
55
|
+
] });
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
StreamingText.displayName = "StreamingText";
|
|
59
|
+
export {
|
|
60
|
+
StreamingText
|
|
61
|
+
};
|
package/components/registry.json
CHANGED
|
@@ -147,6 +147,14 @@
|
|
|
147
147
|
"category": "data-display",
|
|
148
148
|
"client": true
|
|
149
149
|
},
|
|
150
|
+
{
|
|
151
|
+
"name": "AvatarGroup",
|
|
152
|
+
"label": "Avatar group",
|
|
153
|
+
"slug": "avatar-group",
|
|
154
|
+
"description": "Overlapping avatar stack with a +N counter for the overflow.",
|
|
155
|
+
"category": "data-display",
|
|
156
|
+
"client": false
|
|
157
|
+
},
|
|
150
158
|
{
|
|
151
159
|
"name": "Badge",
|
|
152
160
|
"label": "Badge",
|
|
@@ -292,6 +300,15 @@
|
|
|
292
300
|
"category": "forms",
|
|
293
301
|
"client": true
|
|
294
302
|
},
|
|
303
|
+
{
|
|
304
|
+
"name": "ComboChart",
|
|
305
|
+
"label": "Combo chart",
|
|
306
|
+
"slug": "combo-chart",
|
|
307
|
+
"description": "Bar and line series in one chart, with an optional second y-axis for pairs in different units, like spend and ROAS.",
|
|
308
|
+
"category": "charts",
|
|
309
|
+
"client": false,
|
|
310
|
+
"folder": "Chart"
|
|
311
|
+
},
|
|
295
312
|
{
|
|
296
313
|
"name": "Combobox",
|
|
297
314
|
"label": "Combobox",
|
|
@@ -460,6 +477,30 @@
|
|
|
460
477
|
"category": "forms",
|
|
461
478
|
"client": true
|
|
462
479
|
},
|
|
480
|
+
{
|
|
481
|
+
"name": "FilterBar",
|
|
482
|
+
"label": "Filter bar",
|
|
483
|
+
"slug": "filter-bar",
|
|
484
|
+
"description": "A row of filter chips for narrowing a collection, each opening a popover of options, with per-filter and clear-all resets.",
|
|
485
|
+
"category": "forms",
|
|
486
|
+
"client": true
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
"name": "FunnelChart",
|
|
490
|
+
"label": "Funnel chart",
|
|
491
|
+
"slug": "funnel-chart",
|
|
492
|
+
"description": "Ordered funnel stages as stepped bars with conversion percentages, each sized by its share of the first stage.",
|
|
493
|
+
"category": "charts",
|
|
494
|
+
"client": false
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"name": "Gauge",
|
|
498
|
+
"label": "Gauge",
|
|
499
|
+
"slug": "gauge",
|
|
500
|
+
"description": "A radial dial for a single bounded reading, recoloured through the status roles as it crosses thresholds.",
|
|
501
|
+
"category": "charts",
|
|
502
|
+
"client": false
|
|
503
|
+
},
|
|
463
504
|
{
|
|
464
505
|
"name": "Globe",
|
|
465
506
|
"label": "Globe",
|
|
@@ -500,6 +541,14 @@
|
|
|
500
541
|
"category": "data-display",
|
|
501
542
|
"client": false
|
|
502
543
|
},
|
|
544
|
+
{
|
|
545
|
+
"name": "LegendTile",
|
|
546
|
+
"label": "Legend tile",
|
|
547
|
+
"slug": "legend-tile",
|
|
548
|
+
"description": "The labelled value tile under a chart: a series dot, the series name, and its reading, on an inset fill.",
|
|
549
|
+
"category": "charts",
|
|
550
|
+
"client": false
|
|
551
|
+
},
|
|
503
552
|
{
|
|
504
553
|
"name": "LineChart",
|
|
505
554
|
"label": "Line chart",
|
|
@@ -597,6 +646,14 @@
|
|
|
597
646
|
"category": "navigation",
|
|
598
647
|
"client": true
|
|
599
648
|
},
|
|
649
|
+
{
|
|
650
|
+
"name": "Panel",
|
|
651
|
+
"label": "Panel",
|
|
652
|
+
"slug": "panel",
|
|
653
|
+
"description": "The plain dashboard surface: a rounded container with no border or shadow, just padding and a gap.",
|
|
654
|
+
"category": "layout",
|
|
655
|
+
"client": false
|
|
656
|
+
},
|
|
600
657
|
{
|
|
601
658
|
"name": "PieChart",
|
|
602
659
|
"label": "Pie chart",
|
|
@@ -769,6 +826,14 @@
|
|
|
769
826
|
"category": "feedback",
|
|
770
827
|
"client": false
|
|
771
828
|
},
|
|
829
|
+
{
|
|
830
|
+
"name": "SplitPane",
|
|
831
|
+
"label": "Split pane",
|
|
832
|
+
"slug": "split-pane",
|
|
833
|
+
"description": "Two resizable regions with a draggable, keyboard-operable divider between them.",
|
|
834
|
+
"category": "layout",
|
|
835
|
+
"client": true
|
|
836
|
+
},
|
|
772
837
|
{
|
|
773
838
|
"name": "StackedBarChart",
|
|
774
839
|
"label": "Stacked bar chart",
|
|
@@ -794,6 +859,14 @@
|
|
|
794
859
|
"category": "navigation",
|
|
795
860
|
"client": true
|
|
796
861
|
},
|
|
862
|
+
{
|
|
863
|
+
"name": "StreamingText",
|
|
864
|
+
"label": "Streaming text",
|
|
865
|
+
"slug": "streaming-text",
|
|
866
|
+
"description": "Progressive reveal for text arriving in chunks, with a blinking cursor while more is coming.",
|
|
867
|
+
"category": "ai",
|
|
868
|
+
"client": true
|
|
869
|
+
},
|
|
797
870
|
{
|
|
798
871
|
"name": "Swatch",
|
|
799
872
|
"label": "Swatch",
|
|
@@ -147,6 +147,14 @@ declare const _default: {
|
|
|
147
147
|
"category": "data-display",
|
|
148
148
|
"client": true
|
|
149
149
|
},
|
|
150
|
+
{
|
|
151
|
+
"name": "AvatarGroup",
|
|
152
|
+
"label": "Avatar group",
|
|
153
|
+
"slug": "avatar-group",
|
|
154
|
+
"description": "Overlapping avatar stack with a +N counter for the overflow.",
|
|
155
|
+
"category": "data-display",
|
|
156
|
+
"client": false
|
|
157
|
+
},
|
|
150
158
|
{
|
|
151
159
|
"name": "Badge",
|
|
152
160
|
"label": "Badge",
|
|
@@ -292,6 +300,15 @@ declare const _default: {
|
|
|
292
300
|
"category": "forms",
|
|
293
301
|
"client": true
|
|
294
302
|
},
|
|
303
|
+
{
|
|
304
|
+
"name": "ComboChart",
|
|
305
|
+
"label": "Combo chart",
|
|
306
|
+
"slug": "combo-chart",
|
|
307
|
+
"description": "Bar and line series in one chart, with an optional second y-axis for pairs in different units, like spend and ROAS.",
|
|
308
|
+
"category": "charts",
|
|
309
|
+
"client": false,
|
|
310
|
+
"folder": "Chart"
|
|
311
|
+
},
|
|
295
312
|
{
|
|
296
313
|
"name": "Combobox",
|
|
297
314
|
"label": "Combobox",
|
|
@@ -460,6 +477,30 @@ declare const _default: {
|
|
|
460
477
|
"category": "forms",
|
|
461
478
|
"client": true
|
|
462
479
|
},
|
|
480
|
+
{
|
|
481
|
+
"name": "FilterBar",
|
|
482
|
+
"label": "Filter bar",
|
|
483
|
+
"slug": "filter-bar",
|
|
484
|
+
"description": "A row of filter chips for narrowing a collection, each opening a popover of options, with per-filter and clear-all resets.",
|
|
485
|
+
"category": "forms",
|
|
486
|
+
"client": true
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
"name": "FunnelChart",
|
|
490
|
+
"label": "Funnel chart",
|
|
491
|
+
"slug": "funnel-chart",
|
|
492
|
+
"description": "Ordered funnel stages as stepped bars with conversion percentages, each sized by its share of the first stage.",
|
|
493
|
+
"category": "charts",
|
|
494
|
+
"client": false
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"name": "Gauge",
|
|
498
|
+
"label": "Gauge",
|
|
499
|
+
"slug": "gauge",
|
|
500
|
+
"description": "A radial dial for a single bounded reading, recoloured through the status roles as it crosses thresholds.",
|
|
501
|
+
"category": "charts",
|
|
502
|
+
"client": false
|
|
503
|
+
},
|
|
463
504
|
{
|
|
464
505
|
"name": "Globe",
|
|
465
506
|
"label": "Globe",
|
|
@@ -500,6 +541,14 @@ declare const _default: {
|
|
|
500
541
|
"category": "data-display",
|
|
501
542
|
"client": false
|
|
502
543
|
},
|
|
544
|
+
{
|
|
545
|
+
"name": "LegendTile",
|
|
546
|
+
"label": "Legend tile",
|
|
547
|
+
"slug": "legend-tile",
|
|
548
|
+
"description": "The labelled value tile under a chart: a series dot, the series name, and its reading, on an inset fill.",
|
|
549
|
+
"category": "charts",
|
|
550
|
+
"client": false
|
|
551
|
+
},
|
|
503
552
|
{
|
|
504
553
|
"name": "LineChart",
|
|
505
554
|
"label": "Line chart",
|
|
@@ -597,6 +646,14 @@ declare const _default: {
|
|
|
597
646
|
"category": "navigation",
|
|
598
647
|
"client": true
|
|
599
648
|
},
|
|
649
|
+
{
|
|
650
|
+
"name": "Panel",
|
|
651
|
+
"label": "Panel",
|
|
652
|
+
"slug": "panel",
|
|
653
|
+
"description": "The plain dashboard surface: a rounded container with no border or shadow, just padding and a gap.",
|
|
654
|
+
"category": "layout",
|
|
655
|
+
"client": false
|
|
656
|
+
},
|
|
600
657
|
{
|
|
601
658
|
"name": "PieChart",
|
|
602
659
|
"label": "Pie chart",
|
|
@@ -769,6 +826,14 @@ declare const _default: {
|
|
|
769
826
|
"category": "feedback",
|
|
770
827
|
"client": false
|
|
771
828
|
},
|
|
829
|
+
{
|
|
830
|
+
"name": "SplitPane",
|
|
831
|
+
"label": "Split pane",
|
|
832
|
+
"slug": "split-pane",
|
|
833
|
+
"description": "Two resizable regions with a draggable, keyboard-operable divider between them.",
|
|
834
|
+
"category": "layout",
|
|
835
|
+
"client": true
|
|
836
|
+
},
|
|
772
837
|
{
|
|
773
838
|
"name": "StackedBarChart",
|
|
774
839
|
"label": "Stacked bar chart",
|
|
@@ -794,6 +859,14 @@ declare const _default: {
|
|
|
794
859
|
"category": "navigation",
|
|
795
860
|
"client": true
|
|
796
861
|
},
|
|
862
|
+
{
|
|
863
|
+
"name": "StreamingText",
|
|
864
|
+
"label": "Streaming text",
|
|
865
|
+
"slug": "streaming-text",
|
|
866
|
+
"description": "Progressive reveal for text arriving in chunks, with a blinking cursor while more is coming.",
|
|
867
|
+
"category": "ai",
|
|
868
|
+
"client": true
|
|
869
|
+
},
|
|
797
870
|
{
|
|
798
871
|
"name": "Swatch",
|
|
799
872
|
"label": "Swatch",
|