@timbal-ai/timbal-react 0.8.1 → 1.0.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 +40 -0
- package/README.md +69 -6
- package/dist/app.cjs +704 -56
- package/dist/app.d.cts +4 -3
- package/dist/app.d.ts +4 -3
- package/dist/app.esm.js +26 -4
- package/dist/{button-ClSgD6OF.d.cts → button-BoyX5pM_.d.cts} +1 -1
- package/dist/{button-ClSgD6OF.d.ts → button-BoyX5pM_.d.ts} +1 -1
- package/dist/{chart-artifact-DwfRtQWL.d.ts → chart-artifact-CBo9x8Ch.d.ts} +237 -13
- package/dist/{chart-artifact-DWkqIAK5.d.cts → chart-artifact-DOkwSTjQ.d.cts} +237 -13
- package/dist/chat.cjs +23 -1
- package/dist/chat.esm.js +3 -3
- package/dist/{chunk-OISVICYF.esm.js → chunk-AYHOVAMI.esm.js} +1 -1
- package/dist/{chunk-VWHHKAHN.esm.js → chunk-C6IXFM4T.esm.js} +4 -4
- package/dist/{chunk-QVAUCVQA.esm.js → chunk-FOD67Z6G.esm.js} +42 -0
- package/dist/{chunk-GBBLAM3G.esm.js → chunk-GLPOVYEA.esm.js} +776 -172
- package/dist/{chunk-CFU3YDTV.esm.js → chunk-RZ6QC6RG.esm.js} +5 -5
- package/dist/{chunk-5ZKLPWVN.esm.js → chunk-SNLXVG7H.esm.js} +1 -3
- package/dist/chunk-YEFBANNF.esm.js +3485 -0
- package/dist/index.cjs +3965 -84
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.esm.js +409 -9
- package/dist/studio.cjs +23 -1
- package/dist/studio.esm.js +5 -5
- package/dist/styles.css +194 -0
- package/dist/ui.cjs +3354 -89
- package/dist/ui.d.cts +402 -6
- package/dist/ui.d.ts +402 -6
- package/dist/ui.esm.js +384 -6
- package/package.json +3 -1
- package/dist/chunk-P4SN7M67.esm.js +0 -435
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@timbal-ai/timbal-react` are documented here.
|
|
4
4
|
|
|
5
|
+
## [1.0.0] — 2026-06-02
|
|
6
|
+
|
|
7
|
+
First stable release. The `@timbal-ai/timbal-react/ui` primitive layer, the control-surface contract, and the app-kit are now a settled public surface.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Built-in motion engine** — Dialog, AlertDialog, Sheet, Popover, DropdownMenu, Select, Tooltip, Toast, NavigationMenu, and Accordion / Collapsible now animate (fade / zoom / slide / height) out of the box. The `animate-in` / `animate-out` / `fade-*` / `zoom-*` / `slide-*` utilities and the `accordion` / `collapsible` / `caret-blink` keyframes are **inlined in `styles.css`** — no `tailwindcss-animate` / `tw-animate-css` dependency and no consumer config. Duration flows from any `duration-*` utility via `--tw-duration` (default 150ms). Compose `overlayAnimationClass` for custom overlays.
|
|
12
|
+
- **Complete vendored primitive catalog** on the control-surface contract: `Form`, `AspectRatio`, `Toolbar`, `Menubar`, `NavigationMenu`, `Breadcrumb`, `Pagination`, `Command` (cmdk), `Calendar` (react-day-picker), `Combobox`, `DatePicker`, `InputOTP`, `Kbd`, `Spinner`, `InputGroup` — alongside the existing `Input`, `Select`, `Dialog`, `Sheet`, `AlertDialog`, `Table`, `Toast`, `Card`, `Badge`, `Slider`, `Progress`, and more.
|
|
13
|
+
- **`overlayListPanelClass`** + **`PopoverContent` `variant="list"`** — one shared listbox/menu chrome so `Select`, `DropdownMenu`, `Combobox`, and `Command` panels are visually identical. `Combobox` uses `ComboboxTrigger` (control skin), not a `Button`.
|
|
14
|
+
- **App-kit organized into two libraries** (example): a **UI primitives** catalog (per-family audit, sidebar) and a **Blocks** library (composed sections — Project settings, Settings form, Metrics, Analytics, Charts, Table, Integrations, Resources, Confirm & destructive, Detail sheet, Empty states, Sign-in). Driven by `primitives-catalog.ts` / `blocks-catalog.ts`.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- `overlayAnimationClass` is now exported from `@timbal-ai/timbal-react/ui` and the root for composing custom overlays.
|
|
19
|
+
|
|
20
|
+
### Removed (breaking)
|
|
21
|
+
|
|
22
|
+
- **`Tabs` / `TabsList` / `TabsTrigger` / `TabsContent` are no longer exported.** Radix/shadcn Tabs are intentionally not part of this package. Use **`PillSegmentedTabs`** (`trackVariant="flush"`) or the app-kit **`SubNav`** for section bars; switch panel content with local state or the router. Use `Accordion` / `Collapsible` for expand-collapse.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## [0.8.2] — 2026-06-02
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **Full theme personalities** — extend programmatic theming beyond brand color to **roundness, shadows, and fonts** in one intent object:
|
|
31
|
+
- **`createTimbalTheme`** — new options: `shadow` (`none` | `hairline` | `soft` | `medium` | `strong`), `typography` (`sans`, optional `display`/`mono`, `importUrl` for web fonts). `radius` now also sets `--radius-2xl` (composer shell). Returns `fontFamily` + `fontImportUrl` for runtime font loading.
|
|
32
|
+
- **`themeToCss(theme, { scope?, includeFontImport? })`** — emits a `font-family: var(--font-sans)` rule when the theme carries a font; optional `@import` for standalone stylesheets.
|
|
33
|
+
- **`ensureThemeFontLink(url)`** — inject/remove a managed font `<link>` in `<head>`.
|
|
34
|
+
- **`applyTimbalTheme` / `TimbalThemeStyle`** — auto-load preset/custom web fonts via `<link>`.
|
|
35
|
+
- **`TIMBAL_THEME_PRESETS`** — each preset is now a full personality (color + radius + shadow + font), not color-only. New presets: **`folio`** (Fraunces serif, sharp corners), **`carbon`** (JetBrains Mono, green accent). Existing presets (`indigo`, `violet`, …) ship distinct fonts and radii.
|
|
36
|
+
- **`ThemePresetGallery`** — shows font name on each swatch card.
|
|
37
|
+
- **`THEME_AGENT_INSTRUCTIONS`** — documents typography, shadow, and font-loading rules for UI-generation agents.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- **`TimbalThemePreset`** — adds optional `font` label for pickers.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
5
45
|
## [0.8.1] — 2026-06-02
|
|
6
46
|
|
|
7
47
|
### Added
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
React components and runtime for building Timbal chat UIs and studio apps. Drop in a single component to get a fully-featured streaming chat interface connected to a Timbal workforce agent, or compose dashboards with the **app kit**.
|
|
4
4
|
|
|
5
|
-
## Package structure (0
|
|
5
|
+
## Package structure (1.0)
|
|
6
6
|
|
|
7
7
|
| Subpath | Use when |
|
|
8
8
|
|---------|----------|
|
|
@@ -73,20 +73,30 @@ Both light AND dark blocks must be defined for every overridden token — otherw
|
|
|
73
73
|
|
|
74
74
|
### Programmatic theming (no hand-authored OKLCH)
|
|
75
75
|
|
|
76
|
-
Instead of hand-writing paired `:root` / `.dark` blocks, derive a complete,
|
|
76
|
+
Instead of hand-writing paired `:root` / `.dark` blocks, derive a complete **personality** — color, roundness, shadows, and fonts — from a single intent object. The package owns the OKLCH math for every color token (primary, foreground, ring, the full button gradient, the playground tint):
|
|
77
77
|
|
|
78
78
|
```ts
|
|
79
79
|
import { createTimbalTheme, themeToCss, applyTimbalTheme } from "@timbal-ai/timbal-react";
|
|
80
80
|
|
|
81
|
-
const theme = createTimbalTheme({
|
|
81
|
+
const theme = createTimbalTheme({
|
|
82
|
+
brand: "#4f46e5",
|
|
83
|
+
radius: 0.875, // corner roundness (rem) → --radius + --radius-2xl
|
|
84
|
+
shadow: "soft", // "none" | "hairline" | "soft" | "medium" | "strong"
|
|
85
|
+
typography: { // optional — re-skins every component's font
|
|
86
|
+
sans: '"Geist", ui-sans-serif, system-ui, sans-serif',
|
|
87
|
+
importUrl: "https://fonts.googleapis.com/css2?family=Geist:wght@400..600&display=swap",
|
|
88
|
+
},
|
|
89
|
+
});
|
|
82
90
|
|
|
83
91
|
// Build-time / SSR — paste into index.css (paired light + dark, always in sync):
|
|
84
92
|
const css = themeToCss(theme);
|
|
85
93
|
|
|
86
|
-
// Runtime — inject a managed <style
|
|
94
|
+
// Runtime — inject a managed <style> (+ font <link>), swappable, returns a disposer:
|
|
87
95
|
const dispose = applyTimbalTheme(theme);
|
|
88
96
|
```
|
|
89
97
|
|
|
98
|
+
> **Fonts must be loaded.** `applyTimbalTheme` and `TimbalThemeStyle` inject the `<link>` for `typography.importUrl` automatically. For build-time `themeToCss`, add the `<link rel="stylesheet">` to `index.html` yourself (or pass `themeToCss(theme, { includeFontImport: true })` when the result is a standalone stylesheet).
|
|
99
|
+
|
|
90
100
|
Or render it as a component near your app root:
|
|
91
101
|
|
|
92
102
|
```tsx
|
|
@@ -98,7 +108,7 @@ import { TimbalThemeStyle } from "@timbal-ai/timbal-react";
|
|
|
98
108
|
|
|
99
109
|
### Presets + the picker
|
|
100
110
|
|
|
101
|
-
A small closed catalog (`TIMBAL_THEME_PRESETS
|
|
111
|
+
A small closed catalog (`TIMBAL_THEME_PRESETS`) lets you offer styles by stable id and apply on selection. Each preset is a **full personality** (color + radius + shadows + font), not just a color: `platform` (system), `indigo` (Geist), `violet` (Sora), `forest`/`warm` (Lexend), `slate` (Inter), `folio` (Fraunces serif), `carbon` (JetBrains Mono). `ThemePresetGallery` previews each option with real components, scoped so the live app doesn't change until the user picks:
|
|
102
112
|
|
|
103
113
|
```tsx
|
|
104
114
|
import { ThemePresetGallery, applyThemePreset } from "@timbal-ai/timbal-react";
|
|
@@ -110,6 +120,33 @@ import { ThemePresetGallery, applyThemePreset } from "@timbal-ai/timbal-react";
|
|
|
110
120
|
|
|
111
121
|
**For UI-generation agents:** inject `THEME_AGENT_INSTRUCTIONS` into the system prompt so the model themes via these APIs (and never emits raw OKLCH), mirroring `APP_KIT_AGENT_INSTRUCTIONS`.
|
|
112
122
|
|
|
123
|
+
### Anti-slop guardrails for generated UIs
|
|
124
|
+
|
|
125
|
+
When an agent composes app-kit UIs, taste is enforced — not just suggested — through three layers built on one shared vocabulary (`HOUSE_RULES`, `SEMANTIC_COLOR_TOKENS`, `SLOP_BUDGETS`):
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import {
|
|
129
|
+
lintGeneratedUi,
|
|
130
|
+
reviewGeneratedUi,
|
|
131
|
+
UI_REVIEW_AGENT_INSTRUCTIONS,
|
|
132
|
+
} from "@timbal-ai/timbal-react"; // or "/app"
|
|
133
|
+
|
|
134
|
+
// 1. Prompt: APP_KIT_AGENT_INSTRUCTIONS renders its anti-slop checklist from
|
|
135
|
+
// HOUSE_RULES; add UI_REVIEW_AGENT_INSTRUCTIONS so the model self-reviews.
|
|
136
|
+
const systemPrompt = `${basePrompt}\n\n${APP_KIT_AGENT_INSTRUCTIONS}\n\n${UI_REVIEW_AGENT_INSTRUCTIONS}`;
|
|
137
|
+
|
|
138
|
+
// 2. Lint: deterministic checks reject hardcoded palette colors / hex / oklch
|
|
139
|
+
// (errors) and flag icon-spam, bold giant values, per-row dividers, and
|
|
140
|
+
// gradients on data surfaces (warnings).
|
|
141
|
+
const { ok, findings } = lintGeneratedUi(generatedTsx);
|
|
142
|
+
|
|
143
|
+
// 3. Critique loop: review → fix → re-review until it passes clean.
|
|
144
|
+
const review = reviewGeneratedUi(generatedTsx, { strict: true });
|
|
145
|
+
if (!review.passed) regenerate(review.revisionPrompt); // names the exact lines + fixes
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Color decisions belong to the theme generator and semantic tokens, never to the per-component agent — the linter enforces exactly that.
|
|
149
|
+
|
|
113
150
|
### CSS imports
|
|
114
151
|
|
|
115
152
|
Import these stylesheets once in your app entry:
|
|
@@ -841,6 +878,17 @@ if (res.ok) {
|
|
|
841
878
|
|
|
842
879
|
Radix-backed wrappers pre-styled with the design tokens (`bg-popover`, `border-border`, `shadow-card`, …) — import from `@timbal-ai/timbal-react/ui` or the root. Use these instead of `npx shadcn`; raw shadcn references token names the app doesn't define and renders unstyled.
|
|
843
880
|
|
|
881
|
+
**Control-surface contract.** Every input, select / dropdown trigger, and search field shares **one** skin so they match side by side regardless of origin. Build custom controls by composing it — never hand-roll a `rounded-* border-input bg-…` surface:
|
|
882
|
+
|
|
883
|
+
```tsx
|
|
884
|
+
import { controlClass, overlaySurfaceClass, overlayItemClass } from "@timbal-ai/timbal-react/ui";
|
|
885
|
+
|
|
886
|
+
<input className={controlClass({}, "w-full")} /> {/* field shape, h-10 */}
|
|
887
|
+
<button className={controlClass({ shape: "pill", size: "sm" })} /> {/* chrome pill */}
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
`controlClass({ size, shape })` — `size`: `"sm" | "default"`; `shape`: `"field"` (rounded-lg, default) or `"pill"` (chrome rows). Floating panels (popover, menu, listbox) compose `overlaySurfaceClass` + `overlayItemClass`. Vendoring a new shadcn primitive means swapping its inline surface string for these before shipping.
|
|
891
|
+
|
|
844
892
|
- **Button:** `Button`
|
|
845
893
|
- **Dialog:** `Dialog` · `DialogTrigger` · `DialogContent` · `DialogTitle` · `DialogDescription` · `DialogHeader` · `DialogFooter` · `DialogClose` · `DialogOverlay` · `DialogPortal`
|
|
846
894
|
- **Dropdown menu:** `DropdownMenu` · `DropdownMenuTrigger` · `DropdownMenuContent` · `DropdownMenuItem` · `DropdownMenuCheckboxItem` · `DropdownMenuRadioGroup` · `DropdownMenuRadioItem` · `DropdownMenuLabel` · `DropdownMenuSeparator` · `DropdownMenuShortcut` · `DropdownMenuGroup` · `DropdownMenuSub` · `DropdownMenuSubTrigger` · `DropdownMenuSubContent`
|
|
@@ -848,7 +896,22 @@ Radix-backed wrappers pre-styled with the design tokens (`bg-popover`, `border-b
|
|
|
848
896
|
- **Select:** `Select` · `SelectTrigger` · `SelectValue` · `SelectContent` · `SelectItem` · `SelectGroup` · `SelectLabel` · `SelectSeparator` · `SelectScrollUpButton` · `SelectScrollDownButton`
|
|
849
897
|
- **Tooltip:** `Tooltip` · `TooltipTrigger` · `TooltipContent` · `TooltipProvider`
|
|
850
898
|
- **Avatar:** `Avatar` · `AvatarImage` · `AvatarFallback`
|
|
851
|
-
- **
|
|
899
|
+
- **Form:** `Input` · `Textarea` · `Label` · `Checkbox` · `Switch` · `RadioGroup` · `RadioGroupItem` · `Form` (+ field/item/label/control/message/submit)
|
|
900
|
+
- **Navigation / chrome:** `Breadcrumb` (+ list/item/link/page/separator/ellipsis) · `Pagination` (+ content/item/link/previous/next/ellipsis) · `Menubar` (+ sub-parts) · `NavigationMenu` (+ sub-parts) · `Toolbar` (+ button/separator/toggle/link)
|
|
901
|
+
- **Command & date:** `Command` (+ dialog/input/list/group/item/…) · `Calendar` · `Combobox` (Popover + Command) · `DatePicker` (Popover + Calendar)
|
|
902
|
+
- **Input OTP:** `InputOTP` · `InputOTPGroup` · `InputOTPSlot` · `InputOTPHiddenInput` · `InputOTPSeparator` (Radix OTP field via unified `radix-ui`)
|
|
903
|
+
- **Misc:** `Kbd` · `KbdGroup` · `Shimmer`
|
|
904
|
+
- **Feedback / data:** `Slider` · `Progress` · `Badge`
|
|
905
|
+
- **Overlays:** `Sheet` · `AlertDialog` · `HoverCard` · `ContextMenu` (+ sub-parts) · `Toast` / `Toaster` / `toast()` / `useToast`
|
|
906
|
+
- **Surfaces:** `Card` (+ header/footer/title/description/content) · `Alert` · `Skeleton` · `Table` (+ header/body/row/cell)
|
|
907
|
+
- **Toggles:** `Toggle` · `ToggleGroup` · `Collapsible` · `ScrollArea`
|
|
908
|
+
- **Section navigation (pill switcher):** `PillSegmentedTabs` · `SubNav` (app kit) — **not** shadcn `Tabs`; Radix `Tabs` is not exported
|
|
909
|
+
- **Layout / disclosure:** `Accordion` · `AccordionItem` · `AccordionTrigger` · `AccordionContent` · `Separator` · `AspectRatio`
|
|
910
|
+
- **Input chrome:** `InputGroup` (+ addon/control/text) · `Spinner`
|
|
911
|
+
|
|
912
|
+
**Motion is built in.** Dialog, AlertDialog, Sheet, Popover, DropdownMenu, Select, Tooltip, Toast, NavigationMenu, and Accordion / Collapsible animate out of the box (fade / zoom / slide / height). The animation engine is **inlined in `styles.css`** — no `tailwindcss-animate` / `tw-animate-css` dependency and no consumer config. Duration flows from any `duration-*` utility (`--tw-duration`, default 150ms). When composing a custom overlay, reuse `overlayAnimationClass` rather than adding another animation library.
|
|
913
|
+
|
|
914
|
+
All primitives are Radix-backed (via the unified `radix-ui` package) or thin wrappers (`cmdk` for Command, `react-day-picker` for Calendar) and styled with the design tokens + the control-surface contract, so a new primitive matches the rest on arrival. Browse them live in the app-kit example: the **UI primitives** library (per-family audit) and the **Blocks** library (composed sections — Project settings, Confirm flow, Detail sheet, Empty states, Sign-in).
|
|
852
915
|
|
|
853
916
|
---
|
|
854
917
|
|