@usetheo/ui 0.5.0-next.0 → 0.6.0-next.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/CHANGELOG.md +176 -0
- package/NOTICE +38 -0
- package/README.md +18 -18
- package/dist/index.d.ts +324 -31
- package/dist/index.js +991 -56
- package/dist/index.js.map +1 -1
- package/dist/preset-v3-legacy.d.ts +35 -0
- package/dist/{preset.js → preset-v3-legacy.js} +5 -5
- package/dist/preset-v3-legacy.js.map +1 -0
- package/dist/preset.css +27 -0
- package/dist/styles-v3-legacy.css +88 -0
- package/dist/styles.css +22 -5
- package/dist/tokens-v4.css +187 -0
- package/package.json +12 -6
- package/registry/index.json +1 -1
- package/registry/r/agent-stream.json +1 -1
- package/registry/r/chat-message.json +112 -4
- package/registry/r/chat-types.json +1 -1
- package/dist/preset.d.ts +0 -31
- package/dist/preset.js.map +0 -1
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Config } from 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `@usetheo/ui/preset-v3-legacy` — Tailwind v3 JS preset (legacy path).
|
|
5
|
+
*
|
|
6
|
+
* Default-export a `Partial<Config>` mirroring the design tokens shipped
|
|
7
|
+
* in `@usetheo/ui/tokens.css`. Adds a `content` field covering the
|
|
8
|
+
* library's published artifact tree so v3-based Tailwind builds emit
|
|
9
|
+
* the utilities used by `@usetheo/ui` components.
|
|
10
|
+
*
|
|
11
|
+
* **Tailwind v4 consumers MUST use `@usetheo/ui/preset.css`**, not this
|
|
12
|
+
* file — Tailwind v4 dropped the JS preset format entirely. This file
|
|
13
|
+
* exists for any remaining `tailwindcss@^3` consumer (notably the
|
|
14
|
+
* shadcn-style copy-paste registry path); new code should not import
|
|
15
|
+
* from this subpath.
|
|
16
|
+
*
|
|
17
|
+
* The token surface is delegated to `./styles/tailwind-preset.ts` (the
|
|
18
|
+
* existing source of truth used by the local Ladle dev surface and the
|
|
19
|
+
* shadcn registry).
|
|
20
|
+
*
|
|
21
|
+
* v3 consumer usage:
|
|
22
|
+
*
|
|
23
|
+
* // tailwind.config.ts (Tailwind v3 only)
|
|
24
|
+
* import preset from "@usetheo/ui/preset-v3-legacy";
|
|
25
|
+
* export default {
|
|
26
|
+
* presets: [preset],
|
|
27
|
+
* content: ["./app/**\/*.{ts,tsx}"],
|
|
28
|
+
* };
|
|
29
|
+
*
|
|
30
|
+
* See RFC 0008 follow-up.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
declare const preset: Partial<Config>;
|
|
34
|
+
|
|
35
|
+
export { preset as default };
|
|
@@ -141,7 +141,7 @@ var theoUIPreset = {
|
|
|
141
141
|
plugins: [animate]
|
|
142
142
|
};
|
|
143
143
|
|
|
144
|
-
// src/preset.ts
|
|
144
|
+
// src/preset-v3-legacy.ts
|
|
145
145
|
var LIBRARY_CONTENT_GLOBS = [
|
|
146
146
|
// Resolved relative to the consumer's `tailwind.config.{ts,js}`.
|
|
147
147
|
"./node_modules/@usetheo/ui/dist/**/*.{js,mjs,cjs}",
|
|
@@ -152,8 +152,8 @@ var preset = {
|
|
|
152
152
|
...theoUIPreset,
|
|
153
153
|
content: LIBRARY_CONTENT_GLOBS
|
|
154
154
|
};
|
|
155
|
-
var
|
|
155
|
+
var preset_v3_legacy_default = preset;
|
|
156
156
|
|
|
157
|
-
export {
|
|
158
|
-
//# sourceMappingURL=preset.js.map
|
|
159
|
-
//# sourceMappingURL=preset.js.map
|
|
157
|
+
export { preset_v3_legacy_default as default };
|
|
158
|
+
//# sourceMappingURL=preset-v3-legacy.js.map
|
|
159
|
+
//# sourceMappingURL=preset-v3-legacy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/styles/tailwind-preset.ts","../src/preset-v3-legacy.ts"],"names":[],"mappings":"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","file":"preset-v3-legacy.js","sourcesContent":["/**\n * Theo UI Tailwind preset — Violet Forge identity.\n *\n * Single source of truth for the design system's utility-level tokens:\n * - colors mapped to CSS variables (HSL split via `hsl(var(--x) / <alpha>)`)\n * - Geist-inspired typescale (display / title / body / label / code tiers)\n * - radii, shadows, motion timing & duration, keyframes\n * - tailwindcss-animate plugin\n *\n * Consumed by:\n * - `tailwind.config.ts` (this repo) via `presets: [theoUIPreset]`\n * - registry/r/tailwind-preset.json (shipped to consumers via shadcn CLI)\n *\n * Consumers integrate as:\n *\n * import type { Config } from \"tailwindcss\";\n * import { theoUIPreset } from \"./styles/tailwind-preset\";\n *\n * export default {\n * darkMode: \"class\",\n * content: [\"./src/**\\/*.{ts,tsx}\"],\n * presets: [theoUIPreset],\n * } satisfies Config;\n *\n * Note: `darkMode` and `content` are NOT in the preset — they are consumer\n * decisions. The preset only contains `theme.extend.*` and `plugins`.\n */\n\nimport type { Config } from \"tailwindcss\";\nimport animate from \"tailwindcss-animate\";\n\nconst hsl = (token: string) => `hsl(var(${token}) / <alpha-value>)`;\n\nexport const theoUIPreset: Partial<Config> = {\n theme: {\n container: {\n center: true,\n padding: \"1rem\",\n screens: {\n \"2xl\": \"1280px\",\n },\n },\n extend: {\n colors: {\n background: hsl(\"--background\"),\n foreground: hsl(\"--foreground\"),\n card: {\n DEFAULT: hsl(\"--card\"),\n foreground: hsl(\"--card-foreground\"),\n },\n popover: {\n DEFAULT: hsl(\"--popover\"),\n foreground: hsl(\"--popover-foreground\"),\n },\n primary: {\n DEFAULT: hsl(\"--primary\"),\n deep: hsl(\"--primary-deep\"),\n glow: hsl(\"--primary-glow\"),\n foreground: hsl(\"--primary-foreground\"),\n },\n secondary: {\n DEFAULT: hsl(\"--secondary\"),\n foreground: hsl(\"--secondary-foreground\"),\n },\n accent: {\n DEFAULT: hsl(\"--accent\"),\n deep: hsl(\"--accent-deep\"),\n foreground: hsl(\"--accent-foreground\"),\n },\n muted: {\n DEFAULT: hsl(\"--muted\"),\n foreground: hsl(\"--muted-foreground\"),\n },\n success: {\n DEFAULT: hsl(\"--success\"),\n foreground: hsl(\"--success-foreground\"),\n },\n warning: {\n DEFAULT: hsl(\"--warning\"),\n foreground: hsl(\"--warning-foreground\"),\n },\n destructive: {\n DEFAULT: hsl(\"--destructive\"),\n foreground: hsl(\"--destructive-foreground\"),\n },\n info: {\n DEFAULT: hsl(\"--info\"),\n foreground: hsl(\"--info-foreground\"),\n },\n border: hsl(\"--border\"),\n input: hsl(\"--input\"),\n ring: hsl(\"--ring\"),\n },\n fontFamily: {\n display: \"var(--font-display)\",\n sans: \"var(--font-body)\",\n mono: \"var(--font-mono)\",\n },\n /* Geist-inspired Violet Forge typescale.\n *\n * Three strict weights: 400 (body), 500 (UI), 600 (display/headings).\n * Letter-spacing scales with size — aggressive negative on display.\n * Mirrors the Vercel/Geist vocabulary while keeping Theo's identity.\n */\n fontSize: {\n // Display tier — aggressive compression, content-led headlines\n \"display-2xl\": [\"64px\", { lineHeight: \"1\", letterSpacing: \"-0.0464em\", fontWeight: \"600\" }],\n \"display-xl\": [\"48px\", { lineHeight: \"1.05\", letterSpacing: \"-0.05em\", fontWeight: \"600\" }],\n \"display-lg\": [\"40px\", { lineHeight: \"1.1\", letterSpacing: \"-0.05em\", fontWeight: \"600\" }],\n \"display-md\": [\"32px\", { lineHeight: \"1.2\", letterSpacing: \"-0.04em\", fontWeight: \"600\" }],\n headline: [\"28px\", { lineHeight: \"1.25\", letterSpacing: \"-0.035em\", fontWeight: \"600\" }],\n // Title tier — section / card heads\n \"title-lg\": [\"24px\", { lineHeight: \"1.33\", letterSpacing: \"-0.04em\", fontWeight: \"600\" }],\n \"title-md\": [\"20px\", { lineHeight: \"1.4\", letterSpacing: \"-0.03em\", fontWeight: \"600\" }],\n // Body tier — FAANG-density realignment 2026-05-22: body-md is the\n // industry-standard 14px (shadcn / Vercel Geist / Linear / Stripe /\n // Mantine). The previous 15px was idiosyncratic. body-sm (14px label\n // weight) remains separate via its line-height / weight signature.\n \"body-lg\": [\"18px\", { lineHeight: \"1.56\", letterSpacing: \"-0.01em\", fontWeight: \"400\" }],\n \"body-md\": [\"14px\", { lineHeight: \"1.43\", letterSpacing: \"0\", fontWeight: \"400\" }],\n \"body-sm\": [\"13px\", { lineHeight: \"1.46\", fontWeight: \"400\" }],\n // Label tier — used on buttons, nav, secondary actions\n label: [\"14px\", { lineHeight: \"1.43\", fontWeight: \"500\" }],\n \"label-caps\": [\"12px\", { lineHeight: \"1.33\", letterSpacing: \"0.04em\", fontWeight: \"500\" }],\n // Mono — code surfaces, technical labels\n \"code-md\": [\"14px\", { lineHeight: \"1.5\", fontWeight: \"400\" }],\n \"code-sm\": [\"13px\", { lineHeight: \"1.54\", fontWeight: \"500\" }],\n },\n borderRadius: {\n none: \"var(--radius-none)\",\n sm: \"var(--radius-sm)\",\n md: \"var(--radius-md)\",\n lg: \"var(--radius-lg)\",\n xl: \"var(--radius-xl)\",\n \"2xl\": \"var(--radius-2xl)\",\n full: \"var(--radius-full)\",\n },\n boxShadow: {\n sm: \"var(--shadow-sm)\",\n md: \"var(--shadow-md)\",\n lg: \"var(--shadow-lg)\",\n glow: \"var(--shadow-glow)\",\n \"glow-strong\": \"var(--shadow-glow-strong)\",\n },\n transitionTimingFunction: {\n \"out-soft\": \"var(--ease-out-soft)\",\n snap: \"var(--ease-snap)\",\n },\n transitionDuration: {\n fast: \"var(--duration-fast)\",\n base: \"var(--duration-base)\",\n slow: \"var(--duration-slow)\",\n },\n keyframes: {\n \"fade-in-up\": {\n \"0%\": { opacity: \"0\", transform: \"translateY(8px)\" },\n \"100%\": { opacity: \"1\", transform: \"translateY(0)\" },\n },\n \"pulse-glow\": {\n \"0%, 100%\": { boxShadow: \"0 0 0 0 hsl(var(--primary) / 0.5)\" },\n \"50%\": { boxShadow: \"0 0 0 8px hsl(var(--primary) / 0)\" },\n },\n },\n animation: {\n \"fade-in-up\": \"fade-in-up var(--duration-base) var(--ease-out-soft) both\",\n \"pulse-glow\": \"pulse-glow 1.5s var(--ease-in-out) infinite\",\n },\n },\n },\n plugins: [animate],\n};\n","/**\n * `@usetheo/ui/preset-v3-legacy` — Tailwind v3 JS preset (legacy path).\n *\n * Default-export a `Partial<Config>` mirroring the design tokens shipped\n * in `@usetheo/ui/tokens.css`. Adds a `content` field covering the\n * library's published artifact tree so v3-based Tailwind builds emit\n * the utilities used by `@usetheo/ui` components.\n *\n * **Tailwind v4 consumers MUST use `@usetheo/ui/preset.css`**, not this\n * file — Tailwind v4 dropped the JS preset format entirely. This file\n * exists for any remaining `tailwindcss@^3` consumer (notably the\n * shadcn-style copy-paste registry path); new code should not import\n * from this subpath.\n *\n * The token surface is delegated to `./styles/tailwind-preset.ts` (the\n * existing source of truth used by the local Ladle dev surface and the\n * shadcn registry).\n *\n * v3 consumer usage:\n *\n * // tailwind.config.ts (Tailwind v3 only)\n * import preset from \"@usetheo/ui/preset-v3-legacy\";\n * export default {\n * presets: [preset],\n * content: [\"./app/**\\/*.{ts,tsx}\"],\n * };\n *\n * See RFC 0008 follow-up.\n */\nimport type { Config } from \"tailwindcss\";\nimport { theoUIPreset } from \"./styles/tailwind-preset.js\";\n\nconst LIBRARY_CONTENT_GLOBS: string[] = [\n // Resolved relative to the consumer's `tailwind.config.{ts,js}`.\n \"./node_modules/@usetheo/ui/dist/**/*.{js,mjs,cjs}\",\n // Yarn PnP / pnpm hoist fallback — Tailwind's globbing tolerates both.\n \"./node_modules/@usetheo/ui/dist/**/*.{ts,tsx}\",\n];\n\nconst preset: Partial<Config> = {\n ...theoUIPreset,\n content: LIBRARY_CONTENT_GLOBS,\n};\n\nexport default preset;\n"]}
|
package/dist/preset.css
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* Theo UI — Tailwind v4 CSS preset.
|
|
2
|
+
*
|
|
3
|
+
* For consumers running their own Tailwind v4 build (TheoKit framework
|
|
4
|
+
* path, custom Vite/Astro/Next apps with @tailwindcss/vite, etc.). The
|
|
5
|
+
* preset pulls in:
|
|
6
|
+
* 1. `tokens.css` — runtime `--*` vars `<ThemeProvider>` mutates per
|
|
7
|
+
* theme cascade.
|
|
8
|
+
* 2. `tokens-v4.css` — the `@theme { --color-*, --font-*, --text-*,
|
|
9
|
+
* --radius-*, --shadow-*, --ease-*, --animate-* }` namespace
|
|
10
|
+
* Tailwind v4 actually reads to generate utilities.
|
|
11
|
+
*
|
|
12
|
+
* Consumer usage (their entry CSS):
|
|
13
|
+
*
|
|
14
|
+
* @import "tailwindcss";
|
|
15
|
+
* @import "@usetheo/ui/preset.css";
|
|
16
|
+
*
|
|
17
|
+
* /* the consumer's own @theme overrides come AFTER, so they win. * /
|
|
18
|
+
*
|
|
19
|
+
* Tailwind v4 dropped the v3 JS preset format. The previous JS preset
|
|
20
|
+
* remains shipped under `@usetheo/ui/preset-v3-legacy` (which works only
|
|
21
|
+
* with `tailwindcss@^3`). New v4 consumers MUST use this CSS preset.
|
|
22
|
+
*
|
|
23
|
+
* See RFC 0008 follow-up.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
@import "./tokens.css";
|
|
27
|
+
@import "./tokens-v4.css";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
@import "./fonts.css";
|
|
2
|
+
@import "./tokens.css";
|
|
3
|
+
|
|
4
|
+
@tailwind base;
|
|
5
|
+
@tailwind components;
|
|
6
|
+
@tailwind utilities;
|
|
7
|
+
|
|
8
|
+
@layer base {
|
|
9
|
+
* {
|
|
10
|
+
border-color: hsl(var(--border));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
html {
|
|
14
|
+
font-family: var(--font-body);
|
|
15
|
+
-webkit-font-smoothing: antialiased;
|
|
16
|
+
-moz-osx-font-smoothing: grayscale;
|
|
17
|
+
text-rendering: optimizeLegibility;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
body {
|
|
21
|
+
background-color: hsl(var(--background));
|
|
22
|
+
color: hsl(var(--foreground));
|
|
23
|
+
/* OpenType ligatures globally — Geist's "liga" feature is structural
|
|
24
|
+
* and gives the Vercel-tight glyph combinations. */
|
|
25
|
+
font-feature-settings: "liga" 1, "ss01" 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Display headings inherit theme display font (Geist by default).
|
|
29
|
+
* Per-size tracking is set in tailwind.config.ts; this is the safety net. */
|
|
30
|
+
h1,
|
|
31
|
+
h2,
|
|
32
|
+
h3,
|
|
33
|
+
h4 {
|
|
34
|
+
font-family: var(--font-display);
|
|
35
|
+
font-weight: 600;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Code surfaces: use the mono token + tabular numerals so columns of
|
|
39
|
+
* numbers line up in tables/logs/metrics. */
|
|
40
|
+
code,
|
|
41
|
+
pre,
|
|
42
|
+
kbd,
|
|
43
|
+
samp {
|
|
44
|
+
font-family: var(--font-mono);
|
|
45
|
+
font-feature-settings: "tnum" 1, "liga" 1;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* Focus ring — violet (signature) */
|
|
49
|
+
:focus-visible {
|
|
50
|
+
outline: 2px solid hsl(var(--ring));
|
|
51
|
+
outline-offset: 2px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Selection — soft violet */
|
|
55
|
+
::selection {
|
|
56
|
+
background-color: hsl(var(--primary) / 0.25);
|
|
57
|
+
color: hsl(var(--foreground));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Native scrollbar fallback (Violet Forge).
|
|
61
|
+
* Used for native browser scroll on elements that don't wrap in <ScrollArea>.
|
|
62
|
+
* Components that DO use <ScrollArea> hide the native scrollbar via Radix.
|
|
63
|
+
*/
|
|
64
|
+
*::-webkit-scrollbar {
|
|
65
|
+
width: 10px;
|
|
66
|
+
height: 10px;
|
|
67
|
+
}
|
|
68
|
+
*::-webkit-scrollbar-track {
|
|
69
|
+
background: transparent;
|
|
70
|
+
}
|
|
71
|
+
*::-webkit-scrollbar-thumb {
|
|
72
|
+
background-color: hsl(var(--primary) / 0.25);
|
|
73
|
+
border: 2px solid transparent;
|
|
74
|
+
background-clip: content-box;
|
|
75
|
+
border-radius: 9999px;
|
|
76
|
+
transition: background-color var(--duration-fast) var(--ease-out-soft);
|
|
77
|
+
}
|
|
78
|
+
*::-webkit-scrollbar-thumb:hover {
|
|
79
|
+
background-color: hsl(var(--primary) / 0.5);
|
|
80
|
+
}
|
|
81
|
+
*::-webkit-scrollbar-thumb:active {
|
|
82
|
+
background-color: hsl(var(--primary) / 0.75);
|
|
83
|
+
}
|
|
84
|
+
* {
|
|
85
|
+
scrollbar-width: thin;
|
|
86
|
+
scrollbar-color: hsl(var(--primary) / 0.3) transparent;
|
|
87
|
+
}
|
|
88
|
+
}
|
package/dist/styles.css
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
|
+
/* Theo UI — Tailwind v4 prebuilt entry stylesheet.
|
|
2
|
+
*
|
|
3
|
+
* What ships at `@usetheo/ui/styles.css` since RFC 0008 follow-up
|
|
4
|
+
* (`0.5.1-next.0`). Consumer imports this once and the framework's
|
|
5
|
+
* Tailwind v4 build picks up:
|
|
6
|
+
* - `@import "tailwindcss"` — Tailwind v4 core (preflight + utilities)
|
|
7
|
+
* - `@import "./fonts.css"` — self-hosted Geist + Geist Mono @font-face
|
|
8
|
+
* - `@import "./tokens.css"` — runtime `--*` vars (theme cascade target)
|
|
9
|
+
* - `@import "./tokens-v4.css"` — `@theme { --color-*, --text-*, … }`
|
|
10
|
+
* namespace Tailwind v4 reads to emit utilities
|
|
11
|
+
* - `@layer base` — `border-color`, body font, focus ring, scrollbar
|
|
12
|
+
* styling that depend on the runtime vars
|
|
13
|
+
*
|
|
14
|
+
* v3-only consumers (Tailwind 3.x + the shadcn registry preset) should
|
|
15
|
+
* load `@usetheo/ui/styles-v3-legacy.css` instead — that file is the
|
|
16
|
+
* unchanged `@tailwind base; @tailwind components; @tailwind utilities`
|
|
17
|
+
* variant. See RFC 0008 follow-up.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
@import "tailwindcss";
|
|
1
21
|
@import "./fonts.css";
|
|
2
22
|
@import "./tokens.css";
|
|
3
|
-
|
|
4
|
-
@tailwind base;
|
|
5
|
-
@tailwind components;
|
|
6
|
-
@tailwind utilities;
|
|
23
|
+
@import "./tokens-v4.css";
|
|
7
24
|
|
|
8
25
|
@layer base {
|
|
9
26
|
* {
|
|
@@ -26,7 +43,7 @@
|
|
|
26
43
|
}
|
|
27
44
|
|
|
28
45
|
/* Display headings inherit theme display font (Geist by default).
|
|
29
|
-
* Per-size tracking is set in
|
|
46
|
+
* Per-size tracking is set in tokens-v4.css; this is the safety net. */
|
|
30
47
|
h1,
|
|
31
48
|
h2,
|
|
32
49
|
h3,
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/* Theo UI — Tailwind v4 theme aliases.
|
|
2
|
+
*
|
|
3
|
+
* Companion to `tokens.css`. The base file declares the v3-style runtime
|
|
4
|
+
* variables (`--primary`, `--background`, …) that `<ThemeProvider>` and
|
|
5
|
+
* `[data-theme]` cascades mutate at runtime. This file declares the
|
|
6
|
+
* Tailwind v4 `@theme` namespace (`--color-primary`, `--color-background`,
|
|
7
|
+
* …) by aliasing back to those runtime vars via `hsl(var(--*))`.
|
|
8
|
+
*
|
|
9
|
+
* Why two layers:
|
|
10
|
+
* - `<ThemeProvider>` (and the 10 built-in themes) sets `--primary`
|
|
11
|
+
* etc. at runtime — that's the theme switch surface.
|
|
12
|
+
* - Tailwind v4 resolves color utilities exclusively through
|
|
13
|
+
* `--color-*` tokens declared in `@theme`. Without these aliases
|
|
14
|
+
* `bg-primary`, `text-muted-foreground`, `border-border`, etc. emit
|
|
15
|
+
* a className with no matching CSS rule.
|
|
16
|
+
*
|
|
17
|
+
* The indirection (`--color-primary: hsl(var(--primary))`) preserves the
|
|
18
|
+
* runtime theme cascade — browsers resolve `var(--color-primary)` →
|
|
19
|
+
* `hsl(var(--primary))` → current `[data-theme]` value at paint time.
|
|
20
|
+
*
|
|
21
|
+
* See RFC 0008 follow-up.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
@theme {
|
|
25
|
+
/* Color tokens ------------------------------------------------------ */
|
|
26
|
+
--color-background: hsl(var(--background));
|
|
27
|
+
--color-foreground: hsl(var(--foreground));
|
|
28
|
+
|
|
29
|
+
--color-card: hsl(var(--card));
|
|
30
|
+
--color-card-foreground: hsl(var(--card-foreground));
|
|
31
|
+
|
|
32
|
+
--color-popover: hsl(var(--popover));
|
|
33
|
+
--color-popover-foreground: hsl(var(--popover-foreground));
|
|
34
|
+
|
|
35
|
+
--color-primary: hsl(var(--primary));
|
|
36
|
+
--color-primary-deep: hsl(var(--primary-deep));
|
|
37
|
+
--color-primary-glow: hsl(var(--primary-glow));
|
|
38
|
+
--color-primary-foreground: hsl(var(--primary-foreground));
|
|
39
|
+
|
|
40
|
+
--color-secondary: hsl(var(--secondary));
|
|
41
|
+
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
|
42
|
+
|
|
43
|
+
--color-accent: hsl(var(--accent));
|
|
44
|
+
--color-accent-deep: hsl(var(--accent-deep));
|
|
45
|
+
--color-accent-foreground: hsl(var(--accent-foreground));
|
|
46
|
+
|
|
47
|
+
--color-muted: hsl(var(--muted));
|
|
48
|
+
--color-muted-foreground: hsl(var(--muted-foreground));
|
|
49
|
+
|
|
50
|
+
--color-border: hsl(var(--border));
|
|
51
|
+
--color-input: hsl(var(--input));
|
|
52
|
+
--color-ring: hsl(var(--ring));
|
|
53
|
+
|
|
54
|
+
--color-success: hsl(var(--success));
|
|
55
|
+
--color-success-foreground: hsl(var(--success-foreground));
|
|
56
|
+
--color-warning: hsl(var(--warning));
|
|
57
|
+
--color-warning-foreground: hsl(var(--warning-foreground));
|
|
58
|
+
--color-destructive: hsl(var(--destructive));
|
|
59
|
+
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
|
60
|
+
--color-info: hsl(var(--info));
|
|
61
|
+
--color-info-foreground: hsl(var(--info-foreground));
|
|
62
|
+
|
|
63
|
+
/* Fonts ------------------------------------------------------------- */
|
|
64
|
+
--font-display: var(--font-display);
|
|
65
|
+
--font-sans: var(--font-body);
|
|
66
|
+
--font-mono: var(--font-mono);
|
|
67
|
+
|
|
68
|
+
/* Violet Forge typescale -------------------------------------------- *
|
|
69
|
+
* Compound text utilities: each `--text-{name}` declares the size,
|
|
70
|
+
* with companion `--*--line-height`, `--*--letter-spacing`, and
|
|
71
|
+
* `--*--font-weight` properties Tailwind v4 picks up automatically.
|
|
72
|
+
*/
|
|
73
|
+
--text-display-2xl: 64px;
|
|
74
|
+
--text-display-2xl--line-height: 1;
|
|
75
|
+
--text-display-2xl--letter-spacing: -0.0464em;
|
|
76
|
+
--text-display-2xl--font-weight: 600;
|
|
77
|
+
|
|
78
|
+
--text-display-xl: 48px;
|
|
79
|
+
--text-display-xl--line-height: 1.05;
|
|
80
|
+
--text-display-xl--letter-spacing: -0.05em;
|
|
81
|
+
--text-display-xl--font-weight: 600;
|
|
82
|
+
|
|
83
|
+
--text-display-lg: 40px;
|
|
84
|
+
--text-display-lg--line-height: 1.1;
|
|
85
|
+
--text-display-lg--letter-spacing: -0.05em;
|
|
86
|
+
--text-display-lg--font-weight: 600;
|
|
87
|
+
|
|
88
|
+
--text-display-md: 32px;
|
|
89
|
+
--text-display-md--line-height: 1.2;
|
|
90
|
+
--text-display-md--letter-spacing: -0.04em;
|
|
91
|
+
--text-display-md--font-weight: 600;
|
|
92
|
+
|
|
93
|
+
--text-headline: 28px;
|
|
94
|
+
--text-headline--line-height: 1.25;
|
|
95
|
+
--text-headline--letter-spacing: -0.035em;
|
|
96
|
+
--text-headline--font-weight: 600;
|
|
97
|
+
|
|
98
|
+
--text-title-lg: 24px;
|
|
99
|
+
--text-title-lg--line-height: 1.33;
|
|
100
|
+
--text-title-lg--letter-spacing: -0.04em;
|
|
101
|
+
--text-title-lg--font-weight: 600;
|
|
102
|
+
|
|
103
|
+
--text-title-md: 20px;
|
|
104
|
+
--text-title-md--line-height: 1.4;
|
|
105
|
+
--text-title-md--letter-spacing: -0.03em;
|
|
106
|
+
--text-title-md--font-weight: 600;
|
|
107
|
+
|
|
108
|
+
--text-body-lg: 18px;
|
|
109
|
+
--text-body-lg--line-height: 1.56;
|
|
110
|
+
--text-body-lg--letter-spacing: -0.01em;
|
|
111
|
+
--text-body-lg--font-weight: 400;
|
|
112
|
+
|
|
113
|
+
--text-body-md: 14px;
|
|
114
|
+
--text-body-md--line-height: 1.43;
|
|
115
|
+
--text-body-md--letter-spacing: 0;
|
|
116
|
+
--text-body-md--font-weight: 400;
|
|
117
|
+
|
|
118
|
+
--text-body-sm: 13px;
|
|
119
|
+
--text-body-sm--line-height: 1.46;
|
|
120
|
+
--text-body-sm--font-weight: 400;
|
|
121
|
+
|
|
122
|
+
--text-label: 14px;
|
|
123
|
+
--text-label--line-height: 1.43;
|
|
124
|
+
--text-label--font-weight: 500;
|
|
125
|
+
|
|
126
|
+
--text-label-caps: 12px;
|
|
127
|
+
--text-label-caps--line-height: 1.33;
|
|
128
|
+
--text-label-caps--letter-spacing: 0.04em;
|
|
129
|
+
--text-label-caps--font-weight: 500;
|
|
130
|
+
|
|
131
|
+
--text-code-md: 14px;
|
|
132
|
+
--text-code-md--line-height: 1.5;
|
|
133
|
+
--text-code-md--font-weight: 400;
|
|
134
|
+
|
|
135
|
+
--text-code-sm: 13px;
|
|
136
|
+
--text-code-sm--line-height: 1.54;
|
|
137
|
+
--text-code-sm--font-weight: 500;
|
|
138
|
+
|
|
139
|
+
/* Radii — Tailwind v4 reads the value directly (no var indirection). */
|
|
140
|
+
--radius-none: 0px;
|
|
141
|
+
--radius-sm: 4px;
|
|
142
|
+
--radius-md: 6px;
|
|
143
|
+
--radius-lg: 10px;
|
|
144
|
+
--radius-xl: 14px;
|
|
145
|
+
--radius-2xl: 20px;
|
|
146
|
+
--radius-full: 9999px;
|
|
147
|
+
|
|
148
|
+
/* Shadows — alias to tokens.css computed values (which already use
|
|
149
|
+
* `hsl(var(--foreground) / …)` so theme-switch keeps them in step). */
|
|
150
|
+
--shadow-sm: var(--shadow-sm);
|
|
151
|
+
--shadow-md: var(--shadow-md);
|
|
152
|
+
--shadow-lg: var(--shadow-lg);
|
|
153
|
+
--shadow-glow: var(--shadow-glow);
|
|
154
|
+
--shadow-glow-strong: var(--shadow-glow-strong);
|
|
155
|
+
|
|
156
|
+
/* Motion ------------------------------------------------------------ */
|
|
157
|
+
--ease-out-soft: var(--ease-out-soft);
|
|
158
|
+
--ease-snap: var(--ease-snap);
|
|
159
|
+
|
|
160
|
+
/* Animations — declare so `animate-fade-in-up` and `animate-pulse-glow`
|
|
161
|
+
* resolve. Keyframes are declared below (outside @theme — Tailwind v4
|
|
162
|
+
* picks them up via the @keyframes namespace).
|
|
163
|
+
*/
|
|
164
|
+
--animate-fade-in-up: fade-in-up var(--duration-base) var(--ease-out-soft) both;
|
|
165
|
+
--animate-pulse-glow: pulse-glow 1.5s var(--ease-in-out) infinite;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@keyframes fade-in-up {
|
|
169
|
+
0% {
|
|
170
|
+
opacity: 0;
|
|
171
|
+
transform: translateY(8px);
|
|
172
|
+
}
|
|
173
|
+
100% {
|
|
174
|
+
opacity: 1;
|
|
175
|
+
transform: translateY(0);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
@keyframes pulse-glow {
|
|
180
|
+
0%,
|
|
181
|
+
100% {
|
|
182
|
+
box-shadow: 0 0 0 0 hsl(var(--primary) / 0.5);
|
|
183
|
+
}
|
|
184
|
+
50% {
|
|
185
|
+
box-shadow: 0 0 0 8px hsl(var(--primary) / 0);
|
|
186
|
+
}
|
|
187
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usetheo/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-next.0",
|
|
4
4
|
"description": "Theo UI — framework-agnostic React component library with the Violet Forge design system. Focused on AI-agent interfaces, cloud dashboards, and developer-tooling surfaces.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -11,7 +11,11 @@
|
|
|
11
11
|
"import": "./dist/index.js"
|
|
12
12
|
},
|
|
13
13
|
"./styles.css": "./dist/styles.css",
|
|
14
|
+
"./styles-v3-legacy.css": "./dist/styles-v3-legacy.css",
|
|
14
15
|
"./tokens.css": "./dist/tokens.css",
|
|
16
|
+
"./tokens-v4.css": "./dist/tokens-v4.css",
|
|
17
|
+
"./preset.css": "./dist/preset.css",
|
|
18
|
+
"./preset": "./dist/preset.css",
|
|
15
19
|
"./fonts.css": "./dist/fonts.css",
|
|
16
20
|
"./fonts-cdn.css": "./dist/fonts-cdn.css",
|
|
17
21
|
"./slide/themes/default.css": "./dist/slide/themes/default.css",
|
|
@@ -444,12 +448,12 @@
|
|
|
444
448
|
"types": "./dist/vite-plugin.d.ts",
|
|
445
449
|
"import": "./dist/vite-plugin.js"
|
|
446
450
|
},
|
|
447
|
-
"./preset": {
|
|
448
|
-
"types": "./dist/preset.d.ts",
|
|
449
|
-
"import": "./dist/preset.js"
|
|
451
|
+
"./preset-v3-legacy": {
|
|
452
|
+
"types": "./dist/preset-v3-legacy.d.ts",
|
|
453
|
+
"import": "./dist/preset-v3-legacy.js"
|
|
450
454
|
}
|
|
451
455
|
},
|
|
452
|
-
"files": ["dist", "registry/r", "registry/index.json", "LICENSE", "CHANGELOG.md"],
|
|
456
|
+
"files": ["dist", "registry/r", "registry/index.json", "LICENSE", "NOTICE", "CHANGELOG.md"],
|
|
453
457
|
"scripts": {
|
|
454
458
|
"build": "tsup",
|
|
455
459
|
"dev": "ladle serve",
|
|
@@ -481,7 +485,9 @@
|
|
|
481
485
|
"dogfood:slide": "tsx scripts/dogfood-slide.ts",
|
|
482
486
|
"dogfood:slide-deck": "tsx scripts/dogfood-slide-deck.ts",
|
|
483
487
|
"dogfood:slide-rich": "tsx scripts/dogfood-slide-rich.ts",
|
|
484
|
-
"
|
|
488
|
+
"dogfood:v4-zero-config": "tsx scripts/dogfood-v4-zero-config.ts",
|
|
489
|
+
"dogfood:v4-real-build": "bash scripts/dogfood-v4-real-build.sh",
|
|
490
|
+
"quality:gates": "pnpm format:check && pnpm lint:ci && pnpm typecheck && pnpm test && pnpm build && pnpm registry:build && pnpm registry:validate && pnpm quality:structure && pnpm quality:bundle && pnpm quality:a11y && pnpm ladle:build && pnpm dogfood:whiteboard && pnpm dogfood:slide && pnpm dogfood:slide-deck && pnpm dogfood:slide-rich && pnpm dogfood:v4-zero-config",
|
|
485
491
|
"quality:gates:fast": "pnpm format:check && pnpm lint:ci && pnpm typecheck && pnpm registry:build && pnpm registry:validate && pnpm quality:structure"
|
|
486
492
|
},
|
|
487
493
|
"peerDependencies": {
|
package/registry/index.json
CHANGED
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
"name": "chat-message",
|
|
161
161
|
"type": "registry:ui",
|
|
162
162
|
"title": "ChatMessage",
|
|
163
|
-
"description": "
|
|
163
|
+
"description": "Composable chat-turn surface with Vercel AI SDK UIMessage parts API — markdown, code blocks, math, tool calls, reasoning, file attachments, source citations, branching navigation."
|
|
164
164
|
},
|
|
165
165
|
{
|
|
166
166
|
"name": "chat-thread",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"path": "components/composites/agent-stream/agent-stream.tsx",
|
|
22
22
|
"type": "registry:ui",
|
|
23
23
|
"target": "components/ui/agent-stream.tsx",
|
|
24
|
-
"content": "import { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { LiveRegionProvider } from \"@/lib/live-region-context\";\nimport type { IconComponent } from \"@/lib/types\";\nimport type {
|
|
24
|
+
"content": "import { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { LiveRegionProvider } from \"@/lib/live-region-context\";\nimport type { IconComponent } from \"@/lib/types\";\nimport type { UIMessage } from \"@/types/chat\";\nimport { AgentErrorCard, type AgentErrorKind } from \"@/components/ui/agent-error-card\";\nimport { AgentStreaming } from \"@/components/ui/agent-streaming\";\nimport { ToolCallCard, type ToolCallStatus } from \"@/components/ui/tool-call-card\";\nimport { ApprovalCard, type ApprovalSeverity } from \"@/components/blocks/approval-card\";\nimport { ChatMessage } from \"@/components/ui/chat-message/index\";\n\n/**\n * AgentStream — the canonical conversation surface for a code agent.\n *\n * Interleaves chat messages (user + assistant), tool invocations, approval\n * gates, errors, and the live streaming indicator. Mirrors how Claude Code\n * presents work to the user: conversation-centric, tool calls embedded,\n * approvals pause the flow inline, errors surface where they happen.\n *\n * Items are rendered in array order. The consumer fully controls the data;\n * AgentStream is a pure presentational composite over its child primitives.\n */\n\ninterface ToolCallStreamItem {\n kind: \"tool-call\";\n id: string;\n tool: ReactNode;\n icon?: IconComponent;\n target?: ReactNode;\n status: ToolCallStatus;\n output?: ReactNode;\n defaultExpanded?: boolean;\n timestamp?: ReactNode;\n}\n\ninterface ApprovalStreamItem {\n kind: \"approval\";\n id: string;\n severity?: ApprovalSeverity;\n title: ReactNode;\n request: ReactNode;\n description?: ReactNode;\n details?: ReactNode;\n onApprove?: () => void;\n onDeny?: () => void;\n onAlways?: () => void;\n}\n\ninterface ErrorStreamItem {\n kind: \"error\";\n id: string;\n errorKind?: AgentErrorKind;\n title: ReactNode;\n detail?: ReactNode;\n actions?: ReactNode;\n timestamp?: ReactNode;\n}\n\ninterface StreamingStreamItem {\n kind: \"streaming\";\n id: string;\n model?: ReactNode;\n partial?: ReactNode;\n}\n\ninterface MessageStreamItem {\n kind: \"message\";\n id: string;\n message: UIMessage;\n}\n\ninterface CustomStreamItem {\n kind: \"custom\";\n id: string;\n /** Arbitrary node — escape hatch for inline diff cards, etc. */\n node: ReactNode;\n}\n\nexport type AgentStreamItem =\n | MessageStreamItem\n | ToolCallStreamItem\n | ApprovalStreamItem\n | ErrorStreamItem\n | StreamingStreamItem\n | CustomStreamItem;\n\ninterface AgentStreamProps extends HTMLAttributes<HTMLDivElement> {\n items: AgentStreamItem[];\n}\n\nconst AgentStream = forwardRef<HTMLDivElement, AgentStreamProps>(\n ({ className, items, ...props }, ref) => (\n // T4.1 (MF-4): AgentStream is the canonical live region for the stream\n // surface. Wrap children in LiveRegionProvider so nested AgentStreaming,\n // AgentErrorCard, AutoCompactNotice, Skeleton, etc. don't declare their\n // own aria-live (which would cause double announcements).\n <LiveRegionProvider value={true}>\n <div\n ref={ref}\n role=\"log\"\n aria-live=\"polite\"\n aria-relevant=\"additions\"\n // MEDIUM-001: explicit aria-atomic=\"false\" so VoiceOver/macOS doesn't\n // reannounce the entire stream on each new item.\n aria-atomic=\"false\"\n className={cn(\"flex flex-col gap-3\", className)}\n {...props}\n >\n {items.map((item) => {\n if (item.kind === \"message\") return <ChatMessage key={item.id} message={item.message} />;\n if (item.kind === \"tool-call\")\n return (\n <ToolCallCard\n key={item.id}\n tool={item.tool}\n icon={item.icon}\n target={item.target}\n status={item.status}\n output={item.output}\n defaultExpanded={item.defaultExpanded}\n timestamp={item.timestamp}\n />\n );\n if (item.kind === \"approval\")\n return (\n <ApprovalCard\n key={item.id}\n severity={item.severity}\n title={item.title}\n request={item.request}\n description={item.description}\n details={item.details}\n onApprove={item.onApprove}\n onDeny={item.onDeny}\n onAlways={item.onAlways}\n />\n );\n if (item.kind === \"error\")\n return (\n <AgentErrorCard\n key={item.id}\n kind={item.errorKind}\n title={item.title}\n detail={item.detail}\n actions={item.actions}\n timestamp={item.timestamp}\n />\n );\n if (item.kind === \"streaming\")\n return <AgentStreaming key={item.id} model={item.model} partial={item.partial} />;\n if (item.kind === \"custom\") return <div key={item.id}>{item.node}</div>;\n return null;\n })}\n </div>\n </LiveRegionProvider>\n ),\n);\nAgentStream.displayName = \"AgentStream\";\n\nexport { AgentStream };\n"
|
|
25
25
|
}
|
|
26
26
|
]
|
|
27
27
|
}
|