@sero-ai/ui 0.4.0 → 0.4.1
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/.turbo/turbo-build.log +311 -324
- package/CHANGELOG.md +22 -2
- package/LICENSE +201 -0
- package/dist/components/dashboard/catalog.cjs +1 -322
- package/dist/components/dashboard/catalog.d.cts +1 -2
- package/dist/components/dashboard/catalog.d.ts +1 -2
- package/dist/components/dashboard/catalog.js +0 -322
- package/dist/components/dashboard/catalog.json +312 -0
- package/dist/components/dashboard/index.d.cts +1 -1
- package/dist/components/dashboard/index.d.ts +1 -1
- package/dist/components/dashboard/status.cjs +6 -2
- package/dist/components/dashboard/status.js +7 -3
- package/dist/components/dashboard/tone.cjs +9 -1
- package/dist/components/dashboard/tone.d.cts +7 -1
- package/dist/components/dashboard/tone.d.ts +7 -1
- package/dist/components/dashboard/tone.js +8 -0
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/reference.cjs +1251 -3
- package/dist/reference.d.cts +11 -5
- package/dist/reference.d.ts +11 -5
- package/dist/reference.js +1224 -6
- package/package.json +52 -69
- package/scripts/ensure-pnpm-publish.mjs +23 -0
- package/scripts/smoke-dist.mjs +68 -0
- package/src/components/dashboard/__tests__/catalog.test.ts +7 -2
- package/src/components/dashboard/__tests__/state.test.tsx +19 -2
- package/src/components/dashboard/catalog.json +312 -0
- package/src/components/dashboard/catalog.ts +6 -328
- package/src/components/dashboard/index.ts +2 -2
- package/src/components/dashboard/status.tsx +15 -2
- package/src/components/dashboard/tone.ts +13 -0
- package/src/index.ts +3 -1
- package/tsup.config.ts +13 -3
- package/tsup.reference.config.ts +15 -0
- package/dist/components/reference/ActivityExample.cjs +0 -47
- package/dist/components/reference/ActivityExample.d.cts +0 -5
- package/dist/components/reference/ActivityExample.d.ts +0 -5
- package/dist/components/reference/ActivityExample.js +0 -47
- package/dist/components/reference/ResourceExample.cjs +0 -54
- package/dist/components/reference/ResourceExample.d.cts +0 -5
- package/dist/components/reference/ResourceExample.d.ts +0 -5
- package/dist/components/reference/ResourceExample.js +0 -54
- package/dist/components/reference/SchedulerExample.cjs +0 -68
- package/dist/components/reference/SchedulerExample.d.cts +0 -5
- package/dist/components/reference/SchedulerExample.d.ts +0 -5
- package/dist/components/reference/SchedulerExample.js +0 -68
- package/dist/components/reference/StarterExample.cjs +0 -34
- package/dist/components/reference/StarterExample.d.cts +0 -5
- package/dist/components/reference/StarterExample.d.ts +0 -5
- package/dist/components/reference/StarterExample.js +0 -34
- package/dist/components/reference/index.cjs +0 -10
- package/dist/components/reference/index.d.cts +0 -5
- package/dist/components/reference/index.d.ts +0 -5
- package/dist/components/reference/index.js +0 -10
- package/dist/dashboard-catalog.cjs +0 -8
- package/dist/dashboard-catalog.d.cts +0 -1
- package/dist/dashboard-catalog.d.ts +0 -1
- package/dist/dashboard-catalog.js +0 -8
- package/src/dashboard-catalog.ts +0 -13
package/package.json
CHANGED
|
@@ -1,67 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sero-ai/ui",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Shared UI components, AI elements, and design tokens for the Sero platform",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./
|
|
7
|
-
"types": "./
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
|
-
".":
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"./
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
},
|
|
14
|
+
"./dashboard-catalog.json": "./dist/components/dashboard/catalog.json",
|
|
15
|
+
"./reference": {
|
|
16
|
+
"types": "./dist/reference.d.ts",
|
|
17
|
+
"import": "./dist/reference.js",
|
|
18
|
+
"require": "./dist/reference.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./theme": {
|
|
21
|
+
"types": "./dist/theme/index.d.ts",
|
|
22
|
+
"import": "./dist/theme/index.js",
|
|
23
|
+
"require": "./dist/theme/index.cjs"
|
|
24
|
+
},
|
|
25
|
+
"./theme/*": {
|
|
26
|
+
"types": "./dist/theme/*.d.ts",
|
|
27
|
+
"import": "./dist/theme/*.js",
|
|
28
|
+
"require": "./dist/theme/*.cjs"
|
|
29
|
+
},
|
|
30
|
+
"./styles/*": "./dist/styles/*",
|
|
15
31
|
"./package.json": "./package.json",
|
|
16
|
-
"./*":
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"typecheck": "tsc --noEmit",
|
|
21
|
-
"test": "vitest run"
|
|
22
|
-
},
|
|
23
|
-
"publishConfig": {
|
|
24
|
-
"main": "./dist/index.js",
|
|
25
|
-
"module": "./dist/index.js",
|
|
26
|
-
"types": "./dist/index.d.ts",
|
|
27
|
-
"exports": {
|
|
28
|
-
".": {
|
|
29
|
-
"types": "./dist/index.d.ts",
|
|
30
|
-
"import": "./dist/index.js",
|
|
31
|
-
"require": "./dist/index.cjs"
|
|
32
|
-
},
|
|
33
|
-
"./dashboard-catalog": {
|
|
34
|
-
"types": "./dist/dashboard-catalog.d.ts",
|
|
35
|
-
"import": "./dist/dashboard-catalog.js",
|
|
36
|
-
"require": "./dist/dashboard-catalog.cjs"
|
|
37
|
-
},
|
|
38
|
-
"./reference": {
|
|
39
|
-
"types": "./dist/reference.d.ts",
|
|
40
|
-
"import": "./dist/reference.js",
|
|
41
|
-
"require": "./dist/reference.cjs"
|
|
42
|
-
},
|
|
43
|
-
"./theme": {
|
|
44
|
-
"types": "./dist/theme/index.d.ts",
|
|
45
|
-
"import": "./dist/theme/index.js",
|
|
46
|
-
"require": "./dist/theme/index.cjs"
|
|
47
|
-
},
|
|
48
|
-
"./theme/*": {
|
|
49
|
-
"types": "./dist/theme/*.d.ts",
|
|
50
|
-
"import": "./dist/theme/*.js",
|
|
51
|
-
"require": "./dist/theme/*.cjs"
|
|
52
|
-
},
|
|
53
|
-
"./styles/*": "./dist/styles/*",
|
|
54
|
-
"./package.json": "./package.json",
|
|
55
|
-
"./*": {
|
|
56
|
-
"types": "./dist/*.d.ts",
|
|
57
|
-
"import": "./dist/*.js",
|
|
58
|
-
"require": "./dist/*.cjs"
|
|
59
|
-
}
|
|
32
|
+
"./*": {
|
|
33
|
+
"types": "./dist/*.d.ts",
|
|
34
|
+
"import": "./dist/*.js",
|
|
35
|
+
"require": "./dist/*.cjs"
|
|
60
36
|
}
|
|
61
37
|
},
|
|
62
38
|
"peerDependencies": {
|
|
63
|
-
"react": "
|
|
64
|
-
"react-dom": "
|
|
39
|
+
"react": "^19.2.4",
|
|
40
|
+
"react-dom": "^19.2.4"
|
|
65
41
|
},
|
|
66
42
|
"dependencies": {
|
|
67
43
|
"@base-ui/react": "^1.3.0",
|
|
@@ -70,7 +46,6 @@
|
|
|
70
46
|
"@radix-ui/react-use-controllable-state": "^1.2.2",
|
|
71
47
|
"@remixicon/react": "^4.9.0",
|
|
72
48
|
"@rive-app/react-webgl2": "^4.27.1",
|
|
73
|
-
"@sero-ai/common": "workspace:*",
|
|
74
49
|
"@streamdown/cjk": "^1.0.2",
|
|
75
50
|
"@streamdown/code": "^1.1.0",
|
|
76
51
|
"@streamdown/math": "^1.0.2",
|
|
@@ -84,9 +59,9 @@
|
|
|
84
59
|
"date-fns": "^4.1.0",
|
|
85
60
|
"embla-carousel-react": "^8.6.0",
|
|
86
61
|
"input-otp": "^1.4.2",
|
|
87
|
-
"lucide-react": "
|
|
62
|
+
"lucide-react": "^0.563.0",
|
|
88
63
|
"media-chrome": "^4.18.0",
|
|
89
|
-
"motion": "
|
|
64
|
+
"motion": "^12.34.0",
|
|
90
65
|
"nanoid": "^5.1.11",
|
|
91
66
|
"next-themes": "^0.4.6",
|
|
92
67
|
"radix-ui": "^1.4.3",
|
|
@@ -98,25 +73,33 @@
|
|
|
98
73
|
"recharts": "2.15.4",
|
|
99
74
|
"shiki": "^3.23.0",
|
|
100
75
|
"sonner": "^2.0.7",
|
|
101
|
-
"streamdown": "
|
|
76
|
+
"streamdown": "^2.5.0",
|
|
102
77
|
"tailwind-merge": "^3.5.0",
|
|
103
78
|
"tokenlens": "^1.3.1",
|
|
104
79
|
"use-stick-to-bottom": "^1.1.4",
|
|
105
|
-
"vaul": "^1.1.2"
|
|
80
|
+
"vaul": "^1.1.2",
|
|
81
|
+
"@sero-ai/common": "0.3.1"
|
|
106
82
|
},
|
|
107
83
|
"devDependencies": {
|
|
108
84
|
"@hookform/resolvers": "^5.2.2",
|
|
109
|
-
"@types/react": "
|
|
110
|
-
"@types/react-dom": "
|
|
85
|
+
"@types/react": "^19.2.13",
|
|
86
|
+
"@types/react-dom": "^19.2.3",
|
|
111
87
|
"@types/react-syntax-highlighter": "^15.5.13",
|
|
112
88
|
"jsdom": "^26.1.0",
|
|
113
|
-
"react": "
|
|
114
|
-
"react-dom": "
|
|
89
|
+
"react": "^19.2.4",
|
|
90
|
+
"react-dom": "^19.2.4",
|
|
115
91
|
"shadcn": "^3.8.5",
|
|
116
|
-
"tailwindcss": "
|
|
92
|
+
"tailwindcss": "4.1.18",
|
|
117
93
|
"tsup": "^8.5.1",
|
|
118
94
|
"tw-animate-css": "^1.4.0",
|
|
119
|
-
"typescript": "
|
|
120
|
-
"vitest": "
|
|
121
|
-
}
|
|
122
|
-
|
|
95
|
+
"typescript": "^5.9.3",
|
|
96
|
+
"vitest": "^4.1.7"
|
|
97
|
+
},
|
|
98
|
+
"scripts": {
|
|
99
|
+
"build": "tsup && tsup --config tsup.reference.config.ts",
|
|
100
|
+
"typecheck": "tsc --noEmit",
|
|
101
|
+
"test": "vitest run",
|
|
102
|
+
"smoke": "node scripts/smoke-dist.mjs"
|
|
103
|
+
},
|
|
104
|
+
"module": "./dist/index.js"
|
|
105
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Publish guard — this package MUST be published with `pnpm publish`.
|
|
2
|
+
//
|
|
3
|
+
// The `publishConfig` block swaps main/types/exports over to the built `dist/`
|
|
4
|
+
// at publish time. That override is a pnpm (and yarn) feature; plain npm
|
|
5
|
+
// IGNORES it and publishes the top-level fields, which point at `src/`. So
|
|
6
|
+
// `npm publish` here silently ships raw TypeScript source instead of the
|
|
7
|
+
// compiled package — exactly how 0.4.0 went out wrong.
|
|
8
|
+
//
|
|
9
|
+
// This runs from `prepublishOnly`, so it fires on every publish. It aborts
|
|
10
|
+
// unless the invoking package manager is pnpm.
|
|
11
|
+
|
|
12
|
+
const ua = process.env.npm_config_user_agent ?? "";
|
|
13
|
+
|
|
14
|
+
if (!ua.startsWith("pnpm")) {
|
|
15
|
+
const tool = ua.split("/")[0] || "an unknown tool";
|
|
16
|
+
console.error(
|
|
17
|
+
`\n✖ @sero-ai/ui must be published with pnpm, but this ran under ${tool}.\n\n` +
|
|
18
|
+
" Plain npm ignores the publishConfig dist overrides and would ship raw\n" +
|
|
19
|
+
" TypeScript source instead of the built dist/. Use:\n\n" +
|
|
20
|
+
" pnpm publish (from packages/ui)\n",
|
|
21
|
+
);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Smoke test for the published artifact.
|
|
2
|
+
//
|
|
3
|
+
// The package is bundle:false and bundler-resolved, so its public entrypoints
|
|
4
|
+
// are easy to break under raw Node ESM (extensionless / directory imports).
|
|
5
|
+
// This runs the built dist the way a published consumer would: it imports the
|
|
6
|
+
// reference entry (ESM + CJS) and reads the catalogue JSON, failing loudly if
|
|
7
|
+
// any entrypoint no longer resolves. Run after `pnpm build`.
|
|
8
|
+
|
|
9
|
+
import { createRequire } from "node:module";
|
|
10
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { dirname, resolve } from "node:path";
|
|
13
|
+
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const dist = resolve(here, "..", "dist");
|
|
17
|
+
|
|
18
|
+
const fail = (msg) => {
|
|
19
|
+
console.error(`✗ ${msg}`);
|
|
20
|
+
process.exitCode = 1;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
if (!existsSync(dist)) {
|
|
24
|
+
fail("dist/ is missing — run `pnpm build` first");
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 1. Reference entrypoint resolves as ESM and exposes the example widgets.
|
|
29
|
+
const EXPECTED = [
|
|
30
|
+
"StarterExample",
|
|
31
|
+
"SchedulerExample",
|
|
32
|
+
"ResourceExample",
|
|
33
|
+
"ActivityExample",
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const esm = await import(resolve(dist, "reference.js"));
|
|
37
|
+
for (const name of EXPECTED) {
|
|
38
|
+
if (typeof esm[name] !== "function") fail(`reference.js missing export ${name}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 2. Reference entrypoint resolves as CJS too.
|
|
42
|
+
const cjs = require(resolve(dist, "reference.cjs"));
|
|
43
|
+
for (const name of EXPECTED) {
|
|
44
|
+
if (typeof cjs[name] !== "function") fail(`reference.cjs missing export ${name}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// The publishConfig `types` map points at these; a clean-race once dropped them.
|
|
48
|
+
for (const f of ["reference.d.ts", "reference.d.cts"]) {
|
|
49
|
+
if (!existsSync(resolve(dist, f))) fail(`${f} not emitted to dist`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 3. Catalogue ships as plain JSON with the expected shape.
|
|
53
|
+
const catalogPath = resolve(dist, "components", "dashboard", "catalog.json");
|
|
54
|
+
if (!existsSync(catalogPath)) fail("dashboard-catalog.json not emitted to dist");
|
|
55
|
+
else {
|
|
56
|
+
const catalog = JSON.parse(readFileSync(catalogPath, "utf8"));
|
|
57
|
+
if (!Array.isArray(catalog) || catalog.length === 0) {
|
|
58
|
+
fail("dashboard-catalog.json is not a non-empty array");
|
|
59
|
+
} else if (!catalog.every((e) => e.name && e.category && e.kind)) {
|
|
60
|
+
fail("dashboard-catalog.json has malformed entries");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (process.exitCode) {
|
|
65
|
+
console.error("Smoke test failed.");
|
|
66
|
+
} else {
|
|
67
|
+
console.log("✓ dist entrypoints resolve (reference esm+cjs, catalog json)");
|
|
68
|
+
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
// Catalogue integrity — keeps the
|
|
1
|
+
// Catalogue integrity — keeps the JSON catalogue honest against the exports.
|
|
2
2
|
|
|
3
3
|
import { describe, expect, it } from "vitest";
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import type { DashboardComponentCatalogEntry } from "../catalog";
|
|
6
|
+
import catalogJson from "../catalog.json";
|
|
6
7
|
import * as dashboard from "../index";
|
|
7
8
|
|
|
9
|
+
// The JSON is the source of truth. JSON imports widen literal unions to
|
|
10
|
+
// `string`, so assert the authored entry shape for the checks below.
|
|
11
|
+
const dashboardComponentCatalog = catalogJson as DashboardComponentCatalogEntry[];
|
|
12
|
+
|
|
8
13
|
// Reused primitives live in other component folders, not the dashboard barrel.
|
|
9
14
|
const REUSED_PRIMITIVES = new Set(["Badge", "Alert", "Button", "Skeleton"]);
|
|
10
15
|
|
|
@@ -94,10 +94,27 @@ describe("accessibility contracts", () => {
|
|
|
94
94
|
expect(html).toContain('type="button"');
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
-
it("a bare Status dot
|
|
97
|
+
it("a bare Status dot exposes its tone as announceable text", () => {
|
|
98
98
|
const html = renderToStaticMarkup(<Status tone="success" />);
|
|
99
99
|
expect(html).toContain('role="status"');
|
|
100
|
-
|
|
100
|
+
// Not an empty live region: assistive tech gets a text alternative.
|
|
101
|
+
expect(html).toContain('class="sr-only">Success<');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("a bare Status dot honours a caller aria-label instead of the tone", () => {
|
|
105
|
+
const html = renderToStaticMarkup(
|
|
106
|
+
<Status tone="success" aria-label="Backup succeeded" />,
|
|
107
|
+
);
|
|
108
|
+
expect(html).toContain('aria-label="Backup succeeded"');
|
|
109
|
+
// The caller supplied the name, so no generic fallback is added.
|
|
110
|
+
expect(html).not.toContain("sr-only");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("a labelled Status uses its visible text and adds no fallback", () => {
|
|
114
|
+
const html = renderToStaticMarkup(<Status tone="neutral">Idle</Status>);
|
|
115
|
+
expect(html).toContain("Idle");
|
|
116
|
+
expect(html).not.toContain('role="status"');
|
|
117
|
+
expect(html).not.toContain("sr-only");
|
|
101
118
|
});
|
|
102
119
|
|
|
103
120
|
it("EmptyState renders its title and message", () => {
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "WidgetContent",
|
|
4
|
+
"category": "layout",
|
|
5
|
+
"kind": "composite",
|
|
6
|
+
"summary": "Full-height widget frame with standard padding and a container-query boundary.",
|
|
7
|
+
"useWhen": "As the outermost element of every dashboard widget.",
|
|
8
|
+
"related": ["Stack", "Inline"],
|
|
9
|
+
"status": "stable",
|
|
10
|
+
"example": "<WidgetContent><Stack gap=\"sm\">…</Stack></WidgetContent>"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "Stack",
|
|
14
|
+
"category": "layout",
|
|
15
|
+
"kind": "composite",
|
|
16
|
+
"summary": "Vertical layout with semantic spacing, alignment and optional scrolling.",
|
|
17
|
+
"useWhen": "For the primary top-to-bottom content flow inside a widget.",
|
|
18
|
+
"related": ["Inline", "WidgetContent"],
|
|
19
|
+
"status": "stable",
|
|
20
|
+
"example": "<Stack gap=\"sm\" scroll>…</Stack>"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "Inline",
|
|
24
|
+
"category": "layout",
|
|
25
|
+
"kind": "composite",
|
|
26
|
+
"summary": "Horizontal layout with spacing, alignment, wrap and justify.",
|
|
27
|
+
"useWhen": "For a row of items such as a header with a trailing action.",
|
|
28
|
+
"related": ["Stack"],
|
|
29
|
+
"status": "stable",
|
|
30
|
+
"example": "<Inline justify=\"between\" align=\"center\">…</Inline>"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "Grid",
|
|
34
|
+
"category": "layout",
|
|
35
|
+
"kind": "composite",
|
|
36
|
+
"summary": "Responsive grid with bounded columns and gap.",
|
|
37
|
+
"useWhen": "For metric and summary layouts that reflow by width.",
|
|
38
|
+
"related": ["MetricGroup"],
|
|
39
|
+
"status": "stable",
|
|
40
|
+
"example": "<Grid columns=\"auto\" minColumnWidth={120}>…</Grid>"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "Section",
|
|
44
|
+
"category": "layout",
|
|
45
|
+
"kind": "composite",
|
|
46
|
+
"summary": "Compact section with optional heading, description and trailing action.",
|
|
47
|
+
"useWhen": "To group related content under a labelled heading.",
|
|
48
|
+
"related": ["Divider", "Heading"],
|
|
49
|
+
"status": "stable",
|
|
50
|
+
"example": "<Section heading=\"Summary\" action={…}>…</Section>"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "Divider",
|
|
54
|
+
"category": "layout",
|
|
55
|
+
"kind": "composite",
|
|
56
|
+
"summary": "Compact horizontal or vertical divider built on Separator.",
|
|
57
|
+
"useWhen": "To separate sections without a heavy border.",
|
|
58
|
+
"related": ["Section"],
|
|
59
|
+
"status": "stable",
|
|
60
|
+
"example": "<Divider spacing=\"sm\" />"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "Text",
|
|
64
|
+
"category": "typography",
|
|
65
|
+
"kind": "composite",
|
|
66
|
+
"summary": "Semantic text variants (body, label, supporting, muted, numeric) with truncation.",
|
|
67
|
+
"useWhen": "For any text, instead of ad-hoc font-size utilities.",
|
|
68
|
+
"related": ["Heading"],
|
|
69
|
+
"status": "stable",
|
|
70
|
+
"example": "<Text variant=\"label\">Jobs</Text>"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "Heading",
|
|
74
|
+
"category": "typography",
|
|
75
|
+
"kind": "composite",
|
|
76
|
+
"summary": "Compact heading levels and sizes that keep correct HTML semantics.",
|
|
77
|
+
"useWhen": "For section and view titles.",
|
|
78
|
+
"related": ["Section", "Text"],
|
|
79
|
+
"status": "stable",
|
|
80
|
+
"example": "<Heading level={2} size=\"md\">Overview</Heading>"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "Icon",
|
|
84
|
+
"category": "typography",
|
|
85
|
+
"kind": "composite",
|
|
86
|
+
"summary": "Consistent icon wrapper for size, tone and accessibility.",
|
|
87
|
+
"useWhen": "To render an icon component with a shared size and tone.",
|
|
88
|
+
"related": ["IconButton"],
|
|
89
|
+
"status": "stable",
|
|
90
|
+
"example": "<Icon icon={Clock} size=\"sm\" tone=\"warning\" />"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "Metric",
|
|
94
|
+
"category": "data-display",
|
|
95
|
+
"kind": "composite",
|
|
96
|
+
"summary": "Label + value with optional icon, supporting text and trend.",
|
|
97
|
+
"useWhen": "To show a single number inline.",
|
|
98
|
+
"related": ["MetricCard", "MetricGroup"],
|
|
99
|
+
"status": "stable",
|
|
100
|
+
"example": "<Metric label=\"Jobs\" value={6} />"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"name": "MetricCard",
|
|
104
|
+
"category": "data-display",
|
|
105
|
+
"kind": "composite",
|
|
106
|
+
"summary": "A contained surface for a Metric or compact summary.",
|
|
107
|
+
"useWhen": "To give a metric its own bounded card.",
|
|
108
|
+
"related": ["Metric", "MetricGroup"],
|
|
109
|
+
"status": "stable",
|
|
110
|
+
"example": "<MetricCard><Metric label=\"Jobs\" value={6} /></MetricCard>"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"name": "MetricGroup",
|
|
114
|
+
"category": "data-display",
|
|
115
|
+
"kind": "composite",
|
|
116
|
+
"summary": "Arranges multiple metrics responsively in a bounded grid.",
|
|
117
|
+
"useWhen": "To show several metrics that reflow by width.",
|
|
118
|
+
"related": ["Metric", "Grid"],
|
|
119
|
+
"status": "stable",
|
|
120
|
+
"example": "<MetricGroup><Metric … /><Metric … /></MetricGroup>"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"name": "Status",
|
|
124
|
+
"category": "data-display",
|
|
125
|
+
"kind": "composite",
|
|
126
|
+
"summary": "Semantic status dot, label or pill with neutral/success/warning/error/info tones.",
|
|
127
|
+
"useWhen": "To show a health or state indicator. Map domain status onto a tone.",
|
|
128
|
+
"related": ["Badge"],
|
|
129
|
+
"status": "stable",
|
|
130
|
+
"example": "<Status tone=\"success\">Active</Status>"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"name": "Badge",
|
|
134
|
+
"category": "data-display",
|
|
135
|
+
"kind": "primitive",
|
|
136
|
+
"summary": "Existing badge primitive, extended with success/warning/info tones.",
|
|
137
|
+
"useWhen": "For compact counts, tags and category labels.",
|
|
138
|
+
"related": ["Status"],
|
|
139
|
+
"status": "stable",
|
|
140
|
+
"example": "<Badge variant=\"success\">Passed</Badge>"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"name": "KeyValue",
|
|
144
|
+
"category": "data-display",
|
|
145
|
+
"kind": "composite",
|
|
146
|
+
"summary": "A single label/value row with predictable alignment and truncation.",
|
|
147
|
+
"useWhen": "For metadata, totals and configuration summaries.",
|
|
148
|
+
"related": ["KeyValueList"],
|
|
149
|
+
"status": "stable",
|
|
150
|
+
"example": "<KeyValue label=\"Region\" value=\"eu-west-1\" mono />"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"name": "KeyValueList",
|
|
154
|
+
"category": "data-display",
|
|
155
|
+
"kind": "composite",
|
|
156
|
+
"summary": "A vertical list of KeyValue rows.",
|
|
157
|
+
"useWhen": "For a block of metadata pairs.",
|
|
158
|
+
"related": ["KeyValue"],
|
|
159
|
+
"status": "stable",
|
|
160
|
+
"example": "<KeyValueList><KeyValue … /></KeyValueList>"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"name": "ItemList",
|
|
164
|
+
"category": "data-display",
|
|
165
|
+
"kind": "composite",
|
|
166
|
+
"summary": "Compact rows with leading media, text, trailing metadata, actions and overflow.",
|
|
167
|
+
"useWhen": "For entity lists (files, notes, results).",
|
|
168
|
+
"related": ["ItemListItem", "ActivityList"],
|
|
169
|
+
"status": "stable",
|
|
170
|
+
"example": "<ItemList overflowCount={3}><ItemListItem … /></ItemList>"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"name": "ItemListItem",
|
|
174
|
+
"category": "data-display",
|
|
175
|
+
"kind": "composite",
|
|
176
|
+
"summary": "A single compact list row with media, primary/secondary text and actions.",
|
|
177
|
+
"useWhen": "As the row inside an ItemList.",
|
|
178
|
+
"related": ["ItemList"],
|
|
179
|
+
"status": "stable",
|
|
180
|
+
"example": "<ItemListItem primary=\"Report.pdf\" trailing=\"2h\" />"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"name": "ActivityList",
|
|
184
|
+
"category": "data-display",
|
|
185
|
+
"kind": "composite",
|
|
186
|
+
"summary": "A chronological list for recent events with a shared overflow footer.",
|
|
187
|
+
"useWhen": "For time-ordered activity or upcoming events.",
|
|
188
|
+
"related": ["ActivityListItem", "ItemList"],
|
|
189
|
+
"status": "stable",
|
|
190
|
+
"example": "<ActivityList><ActivityListItem … /></ActivityList>"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"name": "ActivityListItem",
|
|
194
|
+
"category": "data-display",
|
|
195
|
+
"kind": "composite",
|
|
196
|
+
"summary": "An event row with a status marker or icon, label, timestamp and detail.",
|
|
197
|
+
"useWhen": "As the row inside an ActivityList.",
|
|
198
|
+
"related": ["ActivityList", "Status"],
|
|
199
|
+
"status": "stable",
|
|
200
|
+
"example": "<ActivityListItem label=\"Backup\" timestamp=\"08:00\" tone=\"success\" />"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"name": "ProgressRing",
|
|
204
|
+
"category": "data-display",
|
|
205
|
+
"kind": "composite",
|
|
206
|
+
"summary": "Accessible circular progress / donut gauge, no charting dependency.",
|
|
207
|
+
"useWhen": "For a bounded value such as a success rate or usage percentage.",
|
|
208
|
+
"related": ["Metric"],
|
|
209
|
+
"status": "stable",
|
|
210
|
+
"example": "<ProgressRing value={75} label=\"Success rate\" tone=\"success\" />"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"name": "StaleIndicator",
|
|
214
|
+
"category": "data-display",
|
|
215
|
+
"kind": "composite",
|
|
216
|
+
"summary": "Compact hint that data may be out of date, with optional refresh action.",
|
|
217
|
+
"useWhen": "When displayed data can lag its source.",
|
|
218
|
+
"related": ["DataBoundary"],
|
|
219
|
+
"status": "stable",
|
|
220
|
+
"example": "<StaleIndicator lastUpdated=\"Updated 5m ago\" onRefresh={…} />"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"name": "DataBoundary",
|
|
224
|
+
"category": "state",
|
|
225
|
+
"kind": "composite",
|
|
226
|
+
"summary": "Selects presentation for loading / ready / empty / stale / error states.",
|
|
227
|
+
"useWhen": "To switch a widget's content by data state without owning fetching.",
|
|
228
|
+
"related": ["EmptyState", "MetricSkeleton", "StaleIndicator"],
|
|
229
|
+
"status": "stable",
|
|
230
|
+
"example": "<DataBoundary state={state} loading={…} empty={…} error={…}>…</DataBoundary>"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"name": "EmptyState",
|
|
234
|
+
"category": "state",
|
|
235
|
+
"kind": "composite",
|
|
236
|
+
"summary": "Compact empty state built on the Empty primitives.",
|
|
237
|
+
"useWhen": "When there is nothing to show yet.",
|
|
238
|
+
"related": ["DataBoundary"],
|
|
239
|
+
"status": "stable",
|
|
240
|
+
"example": "<EmptyState icon={Inbox} title=\"No activity yet\" />"
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"name": "Alert",
|
|
244
|
+
"category": "state",
|
|
245
|
+
"kind": "primitive",
|
|
246
|
+
"summary": "Existing alert primitive for inline warnings and errors.",
|
|
247
|
+
"useWhen": "For a persistent inline message inside a widget or view.",
|
|
248
|
+
"related": ["DataBoundary"],
|
|
249
|
+
"status": "stable",
|
|
250
|
+
"example": "<Alert variant=\"destructive\">Failed to load</Alert>"
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
"name": "MetricSkeleton",
|
|
254
|
+
"category": "state",
|
|
255
|
+
"kind": "composite",
|
|
256
|
+
"summary": "Loading placeholder for a row of metrics.",
|
|
257
|
+
"useWhen": "As the `loading` fallback for metric layouts.",
|
|
258
|
+
"related": ["DataBoundary", "ListSkeleton"],
|
|
259
|
+
"status": "stable",
|
|
260
|
+
"example": "<MetricSkeleton count={3} />"
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"name": "ListSkeleton",
|
|
264
|
+
"category": "state",
|
|
265
|
+
"kind": "composite",
|
|
266
|
+
"summary": "Loading placeholder for a list of rows.",
|
|
267
|
+
"useWhen": "As the `loading` fallback for item lists.",
|
|
268
|
+
"related": ["DataBoundary", "ItemList"],
|
|
269
|
+
"status": "stable",
|
|
270
|
+
"example": "<ListSkeleton count={4} />"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"name": "ActivitySkeleton",
|
|
274
|
+
"category": "state",
|
|
275
|
+
"kind": "composite",
|
|
276
|
+
"summary": "Loading placeholder for an activity list.",
|
|
277
|
+
"useWhen": "As the `loading` fallback for activity feeds.",
|
|
278
|
+
"related": ["DataBoundary", "ActivityList"],
|
|
279
|
+
"status": "stable",
|
|
280
|
+
"example": "<ActivitySkeleton count={4} />"
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"name": "Skeleton",
|
|
284
|
+
"category": "state",
|
|
285
|
+
"kind": "primitive",
|
|
286
|
+
"summary": "Existing skeleton primitive for bespoke loading shapes.",
|
|
287
|
+
"useWhen": "When the prebuilt skeleton patterns do not fit.",
|
|
288
|
+
"related": ["MetricSkeleton", "ListSkeleton", "ActivitySkeleton"],
|
|
289
|
+
"status": "stable",
|
|
290
|
+
"example": "<Skeleton className=\"h-4 w-24\" />"
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"name": "Button",
|
|
294
|
+
"category": "action",
|
|
295
|
+
"kind": "primitive",
|
|
296
|
+
"summary": "Existing button primitive, the standard text-action control.",
|
|
297
|
+
"useWhen": "For a labelled action.",
|
|
298
|
+
"related": ["IconButton"],
|
|
299
|
+
"status": "stable",
|
|
300
|
+
"example": "<Button size=\"sm\">Open</Button>"
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"name": "IconButton",
|
|
304
|
+
"category": "action",
|
|
305
|
+
"kind": "composite",
|
|
306
|
+
"summary": "Small icon-only button with a required accessible label.",
|
|
307
|
+
"useWhen": "For a compact action such as refresh or dismiss.",
|
|
308
|
+
"related": ["Button", "Icon"],
|
|
309
|
+
"status": "stable",
|
|
310
|
+
"example": "<IconButton icon={RotateCw} label=\"Refresh\" size=\"xs\" />"
|
|
311
|
+
}
|
|
312
|
+
]
|