@corbits/react-ui 0.1.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/LICENSE +501 -0
- package/README.md +125 -0
- package/dist/blocks/login/auth-layout.d.ts +38 -0
- package/dist/blocks/login/auth-layout.js +52 -0
- package/dist/blocks/login/login-form.d.ts +60 -0
- package/dist/blocks/login/login-form.js +151 -0
- package/dist/hooks/use-command-palette-navigation.d.ts +25 -0
- package/dist/hooks/use-command-palette-navigation.js +52 -0
- package/dist/hooks/use-controllable-state.d.ts +28 -0
- package/dist/hooks/use-controllable-state.js +44 -0
- package/dist/hooks/use-delayed-autofocus.d.ts +9 -0
- package/dist/hooks/use-delayed-autofocus.js +20 -0
- package/dist/hooks/use-dismissable-popover.d.ts +37 -0
- package/dist/hooks/use-dismissable-popover.js +64 -0
- package/dist/hooks/use-list-selection.d.ts +66 -0
- package/dist/hooks/use-list-selection.js +147 -0
- package/dist/hooks/use-prefers-reduced-motion.d.ts +13 -0
- package/dist/hooks/use-prefers-reduced-motion.js +28 -0
- package/dist/hooks/use-scroll-current-into-view.d.ts +19 -0
- package/dist/hooks/use-scroll-current-into-view.js +33 -0
- package/dist/index.d.ts +122 -0
- package/dist/index.js +131 -0
- package/dist/lib/artifact.d.ts +72 -0
- package/dist/lib/artifact.js +67 -0
- package/dist/lib/chart-geometry.d.ts +62 -0
- package/dist/lib/chart-geometry.js +86 -0
- package/dist/lib/chart-palette.d.ts +76 -0
- package/dist/lib/chart-palette.js +92 -0
- package/dist/lib/chat-message.d.ts +115 -0
- package/dist/lib/chat-message.js +41 -0
- package/dist/lib/chat-parts.d.ts +64 -0
- package/dist/lib/chat-parts.js +16 -0
- package/dist/lib/csv.d.ts +60 -0
- package/dist/lib/csv.js +108 -0
- package/dist/lib/metrics.d.ts +70 -0
- package/dist/lib/metrics.js +101 -0
- package/dist/lib/now-item.d.ts +65 -0
- package/dist/lib/now-item.js +59 -0
- package/dist/lib/relative-time.d.ts +9 -0
- package/dist/lib/relative-time.js +47 -0
- package/dist/lib/theme.d.ts +30 -0
- package/dist/lib/theme.js +77 -0
- package/dist/lib/url.d.ts +26 -0
- package/dist/lib/url.js +37 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +5 -0
- package/dist/lib/workflow-display-flow.d.ts +83 -0
- package/dist/lib/workflow-display-flow.js +104 -0
- package/dist/lib/workflow-registry.d.ts +90 -0
- package/dist/lib/workflow-registry.js +56 -0
- package/dist/lib/workflow-run-error.d.ts +31 -0
- package/dist/lib/workflow-run-error.js +105 -0
- package/dist/lib/workflow-run-progress.d.ts +97 -0
- package/dist/lib/workflow-run-progress.js +135 -0
- package/dist/lib/workflow-run.d.ts +43 -0
- package/dist/lib/workflow-run.js +56 -0
- package/dist/styles.css +3080 -0
- package/dist/test/render-hook.d.ts +14 -0
- package/dist/test/render-hook.js +38 -0
- package/dist/theme.css +628 -0
- package/dist/ui/agent-turn.d.ts +26 -0
- package/dist/ui/agent-turn.js +60 -0
- package/dist/ui/animated-number.d.ts +25 -0
- package/dist/ui/animated-number.js +63 -0
- package/dist/ui/approval-card.d.ts +46 -0
- package/dist/ui/approval-card.js +116 -0
- package/dist/ui/artifact-body.d.ts +26 -0
- package/dist/ui/artifact-body.js +170 -0
- package/dist/ui/artifact-notice.d.ts +21 -0
- package/dist/ui/artifact-notice.js +36 -0
- package/dist/ui/avatar.d.ts +37 -0
- package/dist/ui/avatar.js +73 -0
- package/dist/ui/badge.d.ts +10 -0
- package/dist/ui/badge.js +35 -0
- package/dist/ui/bar-chart.d.ts +38 -0
- package/dist/ui/bar-chart.js +118 -0
- package/dist/ui/block-card.d.ts +29 -0
- package/dist/ui/block-card.js +66 -0
- package/dist/ui/boot-screen.d.ts +23 -0
- package/dist/ui/boot-screen.js +49 -0
- package/dist/ui/bulk-action-bar.d.ts +37 -0
- package/dist/ui/bulk-action-bar.js +64 -0
- package/dist/ui/button.d.ts +12 -0
- package/dist/ui/button.js +73 -0
- package/dist/ui/card.d.ts +6 -0
- package/dist/ui/card.js +37 -0
- package/dist/ui/category-bars.d.ts +20 -0
- package/dist/ui/category-bars.js +69 -0
- package/dist/ui/chart-frame.d.ts +54 -0
- package/dist/ui/chart-frame.js +108 -0
- package/dist/ui/chat-composer.d.ts +24 -0
- package/dist/ui/chat-composer.js +32 -0
- package/dist/ui/chat-dock-timing.d.ts +15 -0
- package/dist/ui/chat-dock-timing.js +11 -0
- package/dist/ui/chat-input.d.ts +38 -0
- package/dist/ui/chat-input.js +138 -0
- package/dist/ui/chat-panel.d.ts +20 -0
- package/dist/ui/chat-panel.js +56 -0
- package/dist/ui/chat-thread.d.ts +28 -0
- package/dist/ui/chat-thread.js +61 -0
- package/dist/ui/checkbox.d.ts +25 -0
- package/dist/ui/checkbox.js +63 -0
- package/dist/ui/command-palette.d.ts +100 -0
- package/dist/ui/command-palette.js +341 -0
- package/dist/ui/compare-body.d.ts +52 -0
- package/dist/ui/compare-body.js +140 -0
- package/dist/ui/confirm-button.d.ts +29 -0
- package/dist/ui/confirm-button.js +41 -0
- package/dist/ui/corbits-mark.d.ts +29 -0
- package/dist/ui/corbits-mark.js +33 -0
- package/dist/ui/csv-table.d.ts +22 -0
- package/dist/ui/csv-table.js +85 -0
- package/dist/ui/dialog.d.ts +37 -0
- package/dist/ui/dialog.js +105 -0
- package/dist/ui/dictation-status-line.d.ts +20 -0
- package/dist/ui/dictation-status-line.js +38 -0
- package/dist/ui/dither-canvas.d.ts +31 -0
- package/dist/ui/dither-canvas.js +169 -0
- package/dist/ui/embed-body.d.ts +30 -0
- package/dist/ui/embed-body.js +92 -0
- package/dist/ui/empty-state.d.ts +26 -0
- package/dist/ui/empty-state.js +42 -0
- package/dist/ui/file-input.d.ts +25 -0
- package/dist/ui/file-input.js +66 -0
- package/dist/ui/filter-bar.d.ts +42 -0
- package/dist/ui/filter-bar.js +95 -0
- package/dist/ui/filter-chip.d.ts +14 -0
- package/dist/ui/filter-chip.js +23 -0
- package/dist/ui/gate-block.d.ts +16 -0
- package/dist/ui/gate-block.js +37 -0
- package/dist/ui/horizontal-stepper.d.ts +13 -0
- package/dist/ui/horizontal-stepper.js +65 -0
- package/dist/ui/input.d.ts +2 -0
- package/dist/ui/input.js +14 -0
- package/dist/ui/inspector-shell.d.ts +47 -0
- package/dist/ui/inspector-shell.js +98 -0
- package/dist/ui/intake-form.d.ts +39 -0
- package/dist/ui/intake-form.js +119 -0
- package/dist/ui/kind-card-grid.d.ts +23 -0
- package/dist/ui/kind-card-grid.js +43 -0
- package/dist/ui/library-page-header.d.ts +20 -0
- package/dist/ui/library-page-header.js +43 -0
- package/dist/ui/list-detail.d.ts +28 -0
- package/dist/ui/list-detail.js +55 -0
- package/dist/ui/live-run-banner.d.ts +13 -0
- package/dist/ui/live-run-banner.js +23 -0
- package/dist/ui/live-status-line.d.ts +22 -0
- package/dist/ui/live-status-line.js +37 -0
- package/dist/ui/menu.d.ts +18 -0
- package/dist/ui/menu.js +45 -0
- package/dist/ui/message-bubble.d.ts +24 -0
- package/dist/ui/message-bubble.js +64 -0
- package/dist/ui/mic-button.d.ts +35 -0
- package/dist/ui/mic-button.js +61 -0
- package/dist/ui/mic-permission-dialog.d.ts +20 -0
- package/dist/ui/mic-permission-dialog.js +50 -0
- package/dist/ui/notifications-bell.d.ts +28 -0
- package/dist/ui/notifications-bell.js +69 -0
- package/dist/ui/now-cards.d.ts +37 -0
- package/dist/ui/now-cards.js +116 -0
- package/dist/ui/page-panel.d.ts +37 -0
- package/dist/ui/page-panel.js +23 -0
- package/dist/ui/page-shell.d.ts +21 -0
- package/dist/ui/page-shell.js +26 -0
- package/dist/ui/parts-renderer.d.ts +22 -0
- package/dist/ui/parts-renderer.js +234 -0
- package/dist/ui/profile-card.d.ts +39 -0
- package/dist/ui/profile-card.js +124 -0
- package/dist/ui/progress-checklist.d.ts +25 -0
- package/dist/ui/progress-checklist.js +70 -0
- package/dist/ui/provider-mark.d.ts +32 -0
- package/dist/ui/provider-mark.js +31 -0
- package/dist/ui/quick-reply-chips.d.ts +14 -0
- package/dist/ui/quick-reply-chips.js +24 -0
- package/dist/ui/quote-card.d.ts +39 -0
- package/dist/ui/quote-card.js +66 -0
- package/dist/ui/reasoning-block.d.ts +35 -0
- package/dist/ui/reasoning-block.js +60 -0
- package/dist/ui/research-body.d.ts +70 -0
- package/dist/ui/research-body.js +270 -0
- package/dist/ui/rich-empty-state.d.ts +35 -0
- package/dist/ui/rich-empty-state.js +65 -0
- package/dist/ui/run-now-button.d.ts +23 -0
- package/dist/ui/run-now-button.js +42 -0
- package/dist/ui/section.d.ts +20 -0
- package/dist/ui/section.js +48 -0
- package/dist/ui/select.d.ts +2 -0
- package/dist/ui/select.js +22 -0
- package/dist/ui/selection-checkbox.d.ts +42 -0
- package/dist/ui/selection-checkbox.js +54 -0
- package/dist/ui/settings-panel.d.ts +35 -0
- package/dist/ui/settings-panel.js +68 -0
- package/dist/ui/shimmer-text.d.ts +19 -0
- package/dist/ui/shimmer-text.js +20 -0
- package/dist/ui/sidebar-item-row.d.ts +40 -0
- package/dist/ui/sidebar-item-row.js +64 -0
- package/dist/ui/sidebar-panel.d.ts +25 -0
- package/dist/ui/sidebar-panel.js +56 -0
- package/dist/ui/sidebar.d.ts +46 -0
- package/dist/ui/sidebar.js +111 -0
- package/dist/ui/skeleton.d.ts +13 -0
- package/dist/ui/skeleton.js +20 -0
- package/dist/ui/sortable-table.d.ts +43 -0
- package/dist/ui/sortable-table.js +103 -0
- package/dist/ui/sparkline.d.ts +27 -0
- package/dist/ui/sparkline.js +68 -0
- package/dist/ui/stat-grid.d.ts +55 -0
- package/dist/ui/stat-grid.js +87 -0
- package/dist/ui/status-dot.d.ts +13 -0
- package/dist/ui/status-dot.js +51 -0
- package/dist/ui/step-list.d.ts +21 -0
- package/dist/ui/step-list.js +77 -0
- package/dist/ui/switch.d.ts +23 -0
- package/dist/ui/switch.js +29 -0
- package/dist/ui/table.d.ts +8 -0
- package/dist/ui/table.js +48 -0
- package/dist/ui/tabs.d.ts +44 -0
- package/dist/ui/tabs.js +101 -0
- package/dist/ui/textarea.d.ts +8 -0
- package/dist/ui/textarea.js +32 -0
- package/dist/ui/theme-provider.d.ts +36 -0
- package/dist/ui/theme-provider.js +126 -0
- package/dist/ui/theme-toggle.d.ts +11 -0
- package/dist/ui/theme-toggle.js +32 -0
- package/dist/ui/thinking-indicator.d.ts +7 -0
- package/dist/ui/thinking-indicator.js +19 -0
- package/dist/ui/thinking-label.d.ts +19 -0
- package/dist/ui/thinking-label.js +54 -0
- package/dist/ui/thinking-mark.d.ts +10 -0
- package/dist/ui/thinking-mark.js +153 -0
- package/dist/ui/time-series-chart.d.ts +55 -0
- package/dist/ui/time-series-chart.js +249 -0
- package/dist/ui/toast.d.ts +16 -0
- package/dist/ui/toast.js +41 -0
- package/dist/ui/token-mosaic.d.ts +22 -0
- package/dist/ui/token-mosaic.js +65 -0
- package/dist/ui/tool-block.d.ts +54 -0
- package/dist/ui/tool-block.js +170 -0
- package/dist/ui/tool-narrative.d.ts +22 -0
- package/dist/ui/tool-narrative.js +77 -0
- package/dist/ui/tool-picker.d.ts +44 -0
- package/dist/ui/tool-picker.js +200 -0
- package/dist/ui/tooltip.d.ts +21 -0
- package/dist/ui/tooltip.js +48 -0
- package/dist/ui/top-bar.d.ts +53 -0
- package/dist/ui/top-bar.js +98 -0
- package/dist/ui/trace-waterfall.d.ts +38 -0
- package/dist/ui/trace-waterfall.js +121 -0
- package/dist/ui/typing-indicator.d.ts +9 -0
- package/dist/ui/typing-indicator.js +25 -0
- package/dist/ui/view-toggle.d.ts +17 -0
- package/dist/ui/view-toggle.js +46 -0
- package/dist/ui/voice-waveform.d.ts +16 -0
- package/dist/ui/voice-waveform.js +23 -0
- package/package.json +583 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type RenderedHook<T> = {
|
|
2
|
+
readonly result: {
|
|
3
|
+
readonly current: T;
|
|
4
|
+
};
|
|
5
|
+
rerender(): void;
|
|
6
|
+
unmount(): void;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* The smallest possible hook-testing harness: mount a component that calls
|
|
10
|
+
* `callback` and stashes its return value, re-render it on demand, and clean
|
|
11
|
+
* up. No `@testing-library` dependency — `act` plus `react-dom/client` cover
|
|
12
|
+
* everything a hook test in this package needs.
|
|
13
|
+
*/
|
|
14
|
+
export declare function renderHook<T>(callback: () => T): RenderedHook<T>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { act } from "react";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
/**
|
|
5
|
+
* The smallest possible hook-testing harness: mount a component that calls
|
|
6
|
+
* `callback` and stashes its return value, re-render it on demand, and clean
|
|
7
|
+
* up. No `@testing-library` dependency — `act` plus `react-dom/client` cover
|
|
8
|
+
* everything a hook test in this package needs.
|
|
9
|
+
*/ export function renderHook(callback) {
|
|
10
|
+
const container = document.createElement("div");
|
|
11
|
+
document.body.appendChild(container);
|
|
12
|
+
let root;
|
|
13
|
+
const resultBox = {
|
|
14
|
+
current: undefined
|
|
15
|
+
};
|
|
16
|
+
function Probe() {
|
|
17
|
+
resultBox.current = callback();
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
act(()=>{
|
|
21
|
+
root = createRoot(container);
|
|
22
|
+
root.render(/*#__PURE__*/ _jsx(Probe, {}));
|
|
23
|
+
});
|
|
24
|
+
return {
|
|
25
|
+
result: resultBox,
|
|
26
|
+
rerender () {
|
|
27
|
+
act(()=>{
|
|
28
|
+
root.render(/*#__PURE__*/ _jsx(Probe, {}));
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
unmount () {
|
|
32
|
+
act(()=>{
|
|
33
|
+
root.unmount();
|
|
34
|
+
});
|
|
35
|
+
container.remove();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
package/dist/theme.css
ADDED
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
/* The Corbits theme: design tokens, motion, and the base layer.
|
|
2
|
+
This is the one source for all of it — dist/styles.css is compiled from it,
|
|
3
|
+
and dist/theme.css is this file, so the two can never drift.
|
|
4
|
+
|
|
5
|
+
The @source below is why a Tailwind v4 consumer needs a single directive.
|
|
6
|
+
Tailwind resolves it relative to *this file*, so it means src/ when we build
|
|
7
|
+
the standalone stylesheet and dist/ when a consumer imports it out of
|
|
8
|
+
node_modules. Either way it points at the code that uses the classes. */
|
|
9
|
+
@source "./";
|
|
10
|
+
|
|
11
|
+
@custom-variant dark (&:is(.dark *));
|
|
12
|
+
|
|
13
|
+
/* Corbits brand tokens.
|
|
14
|
+
|
|
15
|
+
Backgrounds are White in light and pure Black in dark — never cream. Cream is
|
|
16
|
+
an *element* color: it carries text, borders and surfaces on dark grounds
|
|
17
|
+
only, and gray carries them on light grounds. The two element neutrals never
|
|
18
|
+
cross over — gray never sits on black, cream never sits on white.
|
|
19
|
+
|
|
20
|
+
Because the ground is correct, the orange needs no correction: brand dark
|
|
21
|
+
orange #bf6b20 measures 5.34:1 against black and is the dark --primary as
|
|
22
|
+
shipped by the brand. #d4791f is no longer a primary; it is the hover/pressed
|
|
23
|
+
step, darker than #e98428 in light (ink label 4.65:1) and brighter than
|
|
24
|
+
#bf6b20 in dark (black label 6.55:1), so one hex serves both modes.
|
|
25
|
+
|
|
26
|
+
--primary-emphasis is orange as *text or border* on the ground, where the
|
|
27
|
+
fill orange does not qualify (#e98428 on white is only 2.44:1).
|
|
28
|
+
--input is the control-boundary token and clears the 3:1 UI-component
|
|
29
|
+
threshold on both the page and the card; --border stays soft and decorative.
|
|
30
|
+
|
|
31
|
+
--primary-foreground is the ink label, not white. White on the primary
|
|
32
|
+
orange measures 2.69:1 — a hard AA failure — so please do not "correct" it
|
|
33
|
+
to white; the contrast gate will reject it anyway.
|
|
34
|
+
|
|
35
|
+
Every pair below is enforced by scripts/contrast-test.mjs, which runs as part
|
|
36
|
+
of `npm run build` against the published dist/styles.css. */
|
|
37
|
+
:root {
|
|
38
|
+
--radius: 0.5rem;
|
|
39
|
+
|
|
40
|
+
/* One named icon-size scale, keyed to where a glyph sits rather than an
|
|
41
|
+
abstract xs/sm/md/lg — a call site names its context, not a pixel value,
|
|
42
|
+
so nothing hardcodes its own size or repeats a `size=` prop. Matches the
|
|
43
|
+
owner's mock CSS 1:1 (mock-spec.md §1): rail nav glyphs sit at 15px,
|
|
44
|
+
top-bar icon buttons at 16px inside a 32x32 hit target, inline button
|
|
45
|
+
glyphs (and dense list/menu-item icons — a row and a context-menu item
|
|
46
|
+
read at the same density) at 13px, and the row-selection checkbox tick
|
|
47
|
+
at 10px. Consume as `text-icon-nav` / `text-icon-topbar` /
|
|
48
|
+
`text-icon-button` / `text-icon-checkbox` (Tailwind font-size utilities,
|
|
49
|
+
re-exposed below) on the glyph's wrapping element, sized in `em` against
|
|
50
|
+
that font-size — this is also the fix for icons rendering unsized
|
|
51
|
+
(the browser's 300x150 replaced-element fallback) wherever no ancestor
|
|
52
|
+
rule or `size=` prop already constrained them. */
|
|
53
|
+
--icon-size-nav: 0.9375rem;
|
|
54
|
+
--icon-size-topbar: 1rem;
|
|
55
|
+
--icon-size-button: 0.8125rem;
|
|
56
|
+
--icon-size-checkbox: 0.625rem;
|
|
57
|
+
|
|
58
|
+
--background: #ffffff;
|
|
59
|
+
--foreground: #2b2627;
|
|
60
|
+
--card: #f2f4f5;
|
|
61
|
+
--card-foreground: #2b2627;
|
|
62
|
+
--popover: #ffffff;
|
|
63
|
+
--popover-foreground: #2b2627;
|
|
64
|
+
--primary: #e98428;
|
|
65
|
+
--primary-foreground: #2b2627;
|
|
66
|
+
--primary-active: #d4791f;
|
|
67
|
+
--primary-emphasis: #9a5416;
|
|
68
|
+
--secondary: #c5d2de;
|
|
69
|
+
--secondary-foreground: #2b2627;
|
|
70
|
+
--muted: #eceff1;
|
|
71
|
+
--muted-foreground: #5c5555;
|
|
72
|
+
--thinking-base: #77716a;
|
|
73
|
+
--accent: #c5d2de;
|
|
74
|
+
--accent-foreground: #2b2627;
|
|
75
|
+
--success: #c1d1be;
|
|
76
|
+
--success-foreground: #2b2627;
|
|
77
|
+
--destructive: #9e2b25;
|
|
78
|
+
--destructive-foreground: #ffffff;
|
|
79
|
+
--border: #dfe3e6;
|
|
80
|
+
--border-strong: #c3ccd2;
|
|
81
|
+
--input: #8a8080;
|
|
82
|
+
--ring: #9a5416;
|
|
83
|
+
|
|
84
|
+
/* Status text, not a fill/foreground pair — used where a step or delivery
|
|
85
|
+
state needs to read as "good"/"caution" beyond what --success/--destructive
|
|
86
|
+
already carry (those are fills). --warn also colours a medium/high
|
|
87
|
+
RiskBadge; low risk stays --muted-foreground so only the levels worth
|
|
88
|
+
flagging draw the eye. Matches Workbench's app.css exactly, so a block
|
|
89
|
+
lifted from a consumer app keeps its colours. */
|
|
90
|
+
--ok: #37904a;
|
|
91
|
+
--warn: #b7791f;
|
|
92
|
+
|
|
93
|
+
/* The chrome's elevation. The design is flat — floating chrome separates
|
|
94
|
+
itself with --border-strong, not depth — so the token ships as `none`
|
|
95
|
+
and exists as the single knob if elevation ever returns. */
|
|
96
|
+
--shadow: none;
|
|
97
|
+
|
|
98
|
+
/* Chart series, a fixed order rather than a pool — slot 1 is always the first
|
|
99
|
+
series in the data. See lib/chart-palette.ts for why these steps and this
|
|
100
|
+
ordering. The orange family is deliberately absent: orange is the reserved
|
|
101
|
+
action accent and never paints a passive data series. Green- and red-family
|
|
102
|
+
slots never neighbour each other — under deuteranopia adjacent green/red
|
|
103
|
+
collapse into one hue — and adjacent same-family steps differ by lightness,
|
|
104
|
+
a channel colour-vision deficiency preserves. Every step clears 3:1 against
|
|
105
|
+
the page and the card in both modes (re-checked by the contrast gate). */
|
|
106
|
+
--chart-1: #1f5fa8;
|
|
107
|
+
--chart-2: #37904a;
|
|
108
|
+
--chart-3: #1f6132;
|
|
109
|
+
--chart-4: #143e70;
|
|
110
|
+
--chart-5: #9e2b25;
|
|
111
|
+
|
|
112
|
+
/* Named durations for the three motion sizes the theme actually uses:
|
|
113
|
+
micro for a hover/pressed state or an icon swap, standard for a toast or
|
|
114
|
+
dropdown, large for a dialog, drawer or panel swap. Declared here, on
|
|
115
|
+
:root, so a consumer can also read `var(--duration-standard)` directly
|
|
116
|
+
in a hand-written transition — the @theme inline block below re-exposes
|
|
117
|
+
them under Tailwind's real `--transition-duration-*` namespace so
|
|
118
|
+
`duration-standard` etc. compile to a utility class too. The theme's
|
|
119
|
+
existing hand-tuned keyframes/transitions (220ms/280ms/160ms) predate
|
|
120
|
+
these and are left as they are; treat these three as the anchors for
|
|
121
|
+
new motion going forward, not a retrofit of what already shipped. */
|
|
122
|
+
--duration-micro: 150ms;
|
|
123
|
+
--duration-standard: 200ms;
|
|
124
|
+
--duration-large: 300ms;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.dark {
|
|
128
|
+
--background: #000000;
|
|
129
|
+
--foreground: #e4d5bc;
|
|
130
|
+
--card: #2b2627;
|
|
131
|
+
--card-foreground: #e4d5bc;
|
|
132
|
+
--popover: #332c2d;
|
|
133
|
+
--popover-foreground: #e4d5bc;
|
|
134
|
+
--primary: #bf6b20;
|
|
135
|
+
--primary-foreground: #000000;
|
|
136
|
+
--primary-active: #d4791f;
|
|
137
|
+
--primary-emphasis: #e98428;
|
|
138
|
+
--secondary: #2d455c;
|
|
139
|
+
--secondary-foreground: #e4d5bc;
|
|
140
|
+
--muted: #1a1718;
|
|
141
|
+
--muted-foreground: #a99c86;
|
|
142
|
+
--thinking-base: #aaa39a;
|
|
143
|
+
--accent: #2d455c;
|
|
144
|
+
--accent-foreground: #e4d5bc;
|
|
145
|
+
--success: #425a3d;
|
|
146
|
+
--success-foreground: #e4d5bc;
|
|
147
|
+
--destructive: #e6796f;
|
|
148
|
+
--destructive-foreground: #000000;
|
|
149
|
+
--border: #423a3b;
|
|
150
|
+
--border-strong: #5c5254;
|
|
151
|
+
--input: #8a8080;
|
|
152
|
+
--ring: #e98428;
|
|
153
|
+
--shadow: none;
|
|
154
|
+
|
|
155
|
+
--ok: #5cb573;
|
|
156
|
+
--warn: #d9a441;
|
|
157
|
+
|
|
158
|
+
--chart-1: #5a95d8;
|
|
159
|
+
--chart-2: #63a86a;
|
|
160
|
+
--chart-3: #9fd8a8;
|
|
161
|
+
--chart-4: #9db8e8;
|
|
162
|
+
--chart-5: #cc4f47;
|
|
163
|
+
color-scheme: dark;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* Dark by default: a fresh install on a dark-OS host gets dark tokens with
|
|
167
|
+
zero JS and zero explicit `.dark` class. The `:not(.dark):not(.light)`
|
|
168
|
+
guard means ThemeProvider still wins in both directions once it mounts —
|
|
169
|
+
an explicit "dark" adds `.dark` (already true, no-op here) and an explicit
|
|
170
|
+
"light" adds `.light`, which this selector excludes.
|
|
171
|
+
|
|
172
|
+
Native CSS cannot attach one declaration list to both `.dark` (any OS) and
|
|
173
|
+
a media-qualified `:root` without `light-dark()` — and `light-dark()` would
|
|
174
|
+
break the contrast gate, which parses hex off `.dark {`. So the two blocks
|
|
175
|
+
stay token-identical on purpose; tests/theme.test.ts fails the build if
|
|
176
|
+
they drift. `color-scheme: dark` is part of that shared set so zero-JS
|
|
177
|
+
dark paints native controls dark too. */
|
|
178
|
+
@media (prefers-color-scheme: dark) {
|
|
179
|
+
:root:not(.dark):not(.light) {
|
|
180
|
+
--background: #000000;
|
|
181
|
+
--foreground: #e4d5bc;
|
|
182
|
+
--card: #2b2627;
|
|
183
|
+
--card-foreground: #e4d5bc;
|
|
184
|
+
--popover: #332c2d;
|
|
185
|
+
--popover-foreground: #e4d5bc;
|
|
186
|
+
--primary: #bf6b20;
|
|
187
|
+
--primary-foreground: #000000;
|
|
188
|
+
--primary-active: #d4791f;
|
|
189
|
+
--primary-emphasis: #e98428;
|
|
190
|
+
--secondary: #2d455c;
|
|
191
|
+
--secondary-foreground: #e4d5bc;
|
|
192
|
+
--muted: #1a1718;
|
|
193
|
+
--muted-foreground: #a99c86;
|
|
194
|
+
--thinking-base: #aaa39a;
|
|
195
|
+
--accent: #2d455c;
|
|
196
|
+
--accent-foreground: #e4d5bc;
|
|
197
|
+
--success: #425a3d;
|
|
198
|
+
--success-foreground: #e4d5bc;
|
|
199
|
+
--destructive: #e6796f;
|
|
200
|
+
--destructive-foreground: #000000;
|
|
201
|
+
--border: #423a3b;
|
|
202
|
+
--border-strong: #5c5254;
|
|
203
|
+
--input: #8a8080;
|
|
204
|
+
--ring: #e98428;
|
|
205
|
+
--shadow: none;
|
|
206
|
+
|
|
207
|
+
--ok: #5cb573;
|
|
208
|
+
--warn: #d9a441;
|
|
209
|
+
|
|
210
|
+
--chart-1: #5a95d8;
|
|
211
|
+
--chart-2: #63a86a;
|
|
212
|
+
--chart-3: #9fd8a8;
|
|
213
|
+
--chart-4: #9db8e8;
|
|
214
|
+
--chart-5: #cc4f47;
|
|
215
|
+
color-scheme: dark;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* Named preset overlays. Applied as data-theme on the same root that carries
|
|
220
|
+
`.dark` (see ThemeProvider). Only surface tints shift — foreground, primary,
|
|
221
|
+
and chart tokens stay on the base theme so the contrast gate and the brand
|
|
222
|
+
orange remain authoritative. */
|
|
223
|
+
:root[data-theme="warm"] {
|
|
224
|
+
--card: #f3efe8;
|
|
225
|
+
--muted: #ebe6df;
|
|
226
|
+
--border: #e2d9ce;
|
|
227
|
+
--border-strong: #c9bcab;
|
|
228
|
+
--secondary: #d4cfc6;
|
|
229
|
+
--secondary-foreground: #2b2627;
|
|
230
|
+
--accent: #d4cfc6;
|
|
231
|
+
--accent-foreground: #2b2627;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.dark[data-theme="warm"] {
|
|
235
|
+
--card: #322a26;
|
|
236
|
+
--muted: #1c1614;
|
|
237
|
+
--border: #4a3f3a;
|
|
238
|
+
--border-strong: #665750;
|
|
239
|
+
--secondary: #3d342e;
|
|
240
|
+
--secondary-foreground: #e4d5bc;
|
|
241
|
+
--accent: #3d342e;
|
|
242
|
+
--accent-foreground: #e4d5bc;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
:root[data-theme="cool"] {
|
|
246
|
+
--card: #eef2f6;
|
|
247
|
+
--muted: #e8edf2;
|
|
248
|
+
--border: #d5dde6;
|
|
249
|
+
--border-strong: #b6c3d0;
|
|
250
|
+
--secondary: #b8c9d9;
|
|
251
|
+
--secondary-foreground: #2b2627;
|
|
252
|
+
--accent: #b8c9d9;
|
|
253
|
+
--accent-foreground: #2b2627;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.dark[data-theme="cool"] {
|
|
257
|
+
--card: #1e242c;
|
|
258
|
+
--muted: #14181e;
|
|
259
|
+
--border: #3a424c;
|
|
260
|
+
--border-strong: #525c68;
|
|
261
|
+
--secondary: #2a3d52;
|
|
262
|
+
--secondary-foreground: #e4d5bc;
|
|
263
|
+
--accent: #2a3d52;
|
|
264
|
+
--accent-foreground: #e4d5bc;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* SidebarItemRow's own restyle points, deliberately outside `@theme inline`:
|
|
268
|
+
a Tailwind `bg-primary/10`/`rounded-md` pair is undefeatable without a
|
|
269
|
+
specificity war, since the utility and its override compile to the same
|
|
270
|
+
specificity and whichever rule is later in the sheet wins. A CSS variable
|
|
271
|
+
read at render time has none of that — a consumer sets it once on their own
|
|
272
|
+
root/scope and the row already reads it, no `!important` and no rebuild.
|
|
273
|
+
`color-mix` re-derives from `--primary` so both modes stay correct without
|
|
274
|
+
a `.dark` override of their own. */
|
|
275
|
+
:root {
|
|
276
|
+
--sidebar-row-radius: var(--radius);
|
|
277
|
+
--sidebar-row-selected-bg: color-mix(in srgb, var(--primary) 10%, transparent);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
@theme inline {
|
|
281
|
+
--color-background: var(--background);
|
|
282
|
+
--color-foreground: var(--foreground);
|
|
283
|
+
--color-card: var(--card);
|
|
284
|
+
--color-card-foreground: var(--card-foreground);
|
|
285
|
+
--color-popover: var(--popover);
|
|
286
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
287
|
+
--color-primary: var(--primary);
|
|
288
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
289
|
+
--color-primary-active: var(--primary-active);
|
|
290
|
+
--color-primary-emphasis: var(--primary-emphasis);
|
|
291
|
+
--color-secondary: var(--secondary);
|
|
292
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
293
|
+
--color-muted: var(--muted);
|
|
294
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
295
|
+
--color-thinking-base: var(--thinking-base);
|
|
296
|
+
--color-accent: var(--accent);
|
|
297
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
298
|
+
--color-success: var(--success);
|
|
299
|
+
--color-success-foreground: var(--success-foreground);
|
|
300
|
+
--color-destructive: var(--destructive);
|
|
301
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
302
|
+
--color-border: var(--border);
|
|
303
|
+
--color-border-strong: var(--border-strong);
|
|
304
|
+
--color-input: var(--input);
|
|
305
|
+
--color-ring: var(--ring);
|
|
306
|
+
--color-ok: var(--ok);
|
|
307
|
+
--color-warn: var(--warn);
|
|
308
|
+
--shadow-surface: var(--shadow);
|
|
309
|
+
|
|
310
|
+
/* The brand faces are named directly and are not bundled — the package ships
|
|
311
|
+
no font files. A consumer that loads Red Hat Display / Space Mono gets the
|
|
312
|
+
brand type; one that does not falls through the stack. To point these at a
|
|
313
|
+
face loaded under a generated name, override --font-sans / --font-mono. */
|
|
314
|
+
--font-sans: "Red Hat Display", "Open Sans", Roboto, Arial, sans-serif;
|
|
315
|
+
--font-mono: "Space Mono", "Fira Code", Monaco, Consolas, monospace;
|
|
316
|
+
|
|
317
|
+
--radius-sm: calc(var(--radius) - 2px);
|
|
318
|
+
--radius-md: var(--radius);
|
|
319
|
+
--radius-lg: calc(var(--radius) + 2px);
|
|
320
|
+
|
|
321
|
+
--text-icon-nav: var(--icon-size-nav);
|
|
322
|
+
--text-icon-topbar: var(--icon-size-topbar);
|
|
323
|
+
--text-icon-button: var(--icon-size-button);
|
|
324
|
+
--text-icon-checkbox: var(--icon-size-checkbox);
|
|
325
|
+
|
|
326
|
+
/* Overrides Tailwind's built-in ease-out with the brand's decelerate curve,
|
|
327
|
+
so every existing and new `ease-out` usage picks it up in one place. */
|
|
328
|
+
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
|
|
329
|
+
|
|
330
|
+
/* Symmetric in-out curve for morphs — something growing/shrinking in place
|
|
331
|
+
rather than entering or exiting — paired with `--ease-out`'s decelerate
|
|
332
|
+
shape so the two read as one curve family. */
|
|
333
|
+
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
|
|
334
|
+
|
|
335
|
+
/* A springier decelerate for entrances that should feel like they land with
|
|
336
|
+
a touch of overshoot — a dock, a popover, a toast arriving — distinct
|
|
337
|
+
from `--ease-out`'s straight decelerate, which suits exits and resizes
|
|
338
|
+
that must never overshoot their target. */
|
|
339
|
+
--ease-spring: cubic-bezier(0.2, 0.9, 0.3, 1.15);
|
|
340
|
+
|
|
341
|
+
/* Tailwind v4's real namespace for duration utilities is
|
|
342
|
+
`--transition-duration-*`, not `--duration-*` — an unreferenced name in
|
|
343
|
+
this inline block is dropped from the build entirely, so re-exporting
|
|
344
|
+
under the correct namespace is what actually emits `duration-micro`,
|
|
345
|
+
`duration-standard` and `duration-large` as utility classes. */
|
|
346
|
+
--transition-duration-micro: var(--duration-micro);
|
|
347
|
+
--transition-duration-standard: var(--duration-standard);
|
|
348
|
+
--transition-duration-large: var(--duration-large);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/* Dialog motion. Written as real keyframes rather than pulled in from an
|
|
352
|
+
animation plugin: one dependency fewer, and a consumer who inherits
|
|
353
|
+
dialog.tsx can read and edit the animation in the same repo as the markup.
|
|
354
|
+
Only `transform` is animated — Tailwind centers the dialog with the separate
|
|
355
|
+
`translate` property, so the two compose and the box never jumps. */
|
|
356
|
+
@keyframes corbits-fade-in {
|
|
357
|
+
from {
|
|
358
|
+
opacity: 0;
|
|
359
|
+
}
|
|
360
|
+
to {
|
|
361
|
+
opacity: 1;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
@keyframes corbits-fade-out {
|
|
366
|
+
from {
|
|
367
|
+
opacity: 1;
|
|
368
|
+
}
|
|
369
|
+
to {
|
|
370
|
+
opacity: 0;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
@keyframes corbits-dialog-in {
|
|
375
|
+
from {
|
|
376
|
+
opacity: 0;
|
|
377
|
+
transform: scale(0.96);
|
|
378
|
+
}
|
|
379
|
+
to {
|
|
380
|
+
opacity: 1;
|
|
381
|
+
transform: scale(1);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
@keyframes corbits-dialog-out {
|
|
386
|
+
from {
|
|
387
|
+
opacity: 1;
|
|
388
|
+
transform: scale(1);
|
|
389
|
+
}
|
|
390
|
+
to {
|
|
391
|
+
opacity: 0;
|
|
392
|
+
transform: scale(0.96);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/* Drawer motion: the sheet slides from the edge it is anchored to. Only
|
|
397
|
+
`transform` moves, so the panel is composited and never reflows the page
|
|
398
|
+
under it. Used by the drawer variant of ui/dialog. */
|
|
399
|
+
@keyframes corbits-drawer-in-right {
|
|
400
|
+
from {
|
|
401
|
+
transform: translateX(100%);
|
|
402
|
+
}
|
|
403
|
+
to {
|
|
404
|
+
transform: translateX(0);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
@keyframes corbits-drawer-out-right {
|
|
409
|
+
from {
|
|
410
|
+
transform: translateX(0);
|
|
411
|
+
}
|
|
412
|
+
to {
|
|
413
|
+
transform: translateX(100%);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
@keyframes corbits-drawer-in-left {
|
|
418
|
+
from {
|
|
419
|
+
transform: translateX(-100%);
|
|
420
|
+
}
|
|
421
|
+
to {
|
|
422
|
+
transform: translateX(0);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
@keyframes corbits-drawer-out-left {
|
|
427
|
+
from {
|
|
428
|
+
transform: translateX(0);
|
|
429
|
+
}
|
|
430
|
+
to {
|
|
431
|
+
transform: translateX(-100%);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/* The live-status ring. Scales and fades outward from the dot rather than
|
|
436
|
+
pulsing its opacity in place, so "still changing" reads at 8px where an
|
|
437
|
+
opacity blink does not. Used by ui/status-dot. */
|
|
438
|
+
@keyframes corbits-status-pulse {
|
|
439
|
+
0% {
|
|
440
|
+
opacity: 0.6;
|
|
441
|
+
transform: scale(1);
|
|
442
|
+
}
|
|
443
|
+
100% {
|
|
444
|
+
opacity: 0;
|
|
445
|
+
transform: scale(2.6);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/* The block card's header dot: a plain opacity blink, distinct from the
|
|
450
|
+
status dot's outward-scaling ring — this one sits inline in a dense header
|
|
451
|
+
row where a scaling ring would collide with the title text next to it.
|
|
452
|
+
Used by ui/block-card. */
|
|
453
|
+
@keyframes corbits-block-pulse {
|
|
454
|
+
0%,
|
|
455
|
+
100% {
|
|
456
|
+
opacity: 1;
|
|
457
|
+
}
|
|
458
|
+
50% {
|
|
459
|
+
opacity: 0.35;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/* The boot screen's progress sweep. An indeterminate bar rather than a spinner:
|
|
464
|
+
it says "still working" without implying a percentage nobody knows. Ships
|
|
465
|
+
by ui/boot-screen. */
|
|
466
|
+
@keyframes corbits-boot-sweep {
|
|
467
|
+
0% {
|
|
468
|
+
transform: translateX(-100%);
|
|
469
|
+
}
|
|
470
|
+
100% {
|
|
471
|
+
transform: translateX(300%);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/* The block swap: a small slide-and-fade for whichever block just became
|
|
476
|
+
active, including the empty-state's own transition into the first block.
|
|
477
|
+
Keyed by block id so React remounts a fresh node per swap and this plays
|
|
478
|
+
every time. Used by ui/parts-renderer and ui/tool-block. */
|
|
479
|
+
@keyframes corbits-rail-block-in {
|
|
480
|
+
from {
|
|
481
|
+
opacity: 0;
|
|
482
|
+
transform: translateY(6px) scale(0.98);
|
|
483
|
+
}
|
|
484
|
+
to {
|
|
485
|
+
opacity: 1;
|
|
486
|
+
transform: translateY(0) scale(1);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/* The typing indicator's three dots. Each dot offsets its own
|
|
491
|
+
animation-delay, so the bounce travels left to right. Used by
|
|
492
|
+
ui/typing-indicator. */
|
|
493
|
+
@keyframes corbits-typing-bounce {
|
|
494
|
+
0%,
|
|
495
|
+
80%,
|
|
496
|
+
100% {
|
|
497
|
+
opacity: 0.35;
|
|
498
|
+
transform: translateY(0);
|
|
499
|
+
}
|
|
500
|
+
40% {
|
|
501
|
+
opacity: 1;
|
|
502
|
+
transform: translateY(-3px);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/* SelectionCheckbox's pop on select: a small overshoot so the check reads as
|
|
506
|
+
a deliberate snap rather than a plain fade. No `--spring-*` token exists
|
|
507
|
+
yet in this theme — the overshoot curve below is a literal cubic-bezier
|
|
508
|
+
rather than a token reference; re-point it at a shared spring token if one
|
|
509
|
+
lands. Used by ui/selection-checkbox. */
|
|
510
|
+
@keyframes corbits-selection-pop {
|
|
511
|
+
0% {
|
|
512
|
+
transform: scale(0.6);
|
|
513
|
+
}
|
|
514
|
+
60% {
|
|
515
|
+
transform: scale(1.15);
|
|
516
|
+
}
|
|
517
|
+
100% {
|
|
518
|
+
transform: scale(1);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/* BulkActionBar's rise into view. Plays on an inner element, not the
|
|
523
|
+
outer fixed/centered one — the outer element's horizontal centering
|
|
524
|
+
transform is a plain, unconditional class rather than something this
|
|
525
|
+
keyframe has to restate, so a `prefers-reduced-motion` viewer (who never
|
|
526
|
+
runs this animation at all) still ends up centered. Used by
|
|
527
|
+
ui/bulk-action-bar. */
|
|
528
|
+
@keyframes corbits-bulk-action-bar-in {
|
|
529
|
+
from {
|
|
530
|
+
opacity: 0;
|
|
531
|
+
transform: translateY(12px);
|
|
532
|
+
}
|
|
533
|
+
to {
|
|
534
|
+
opacity: 1;
|
|
535
|
+
transform: translateY(0);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/* ShimmerText's sweep: a `background-clip: text` gradient sliding across
|
|
540
|
+
its own background-size, so the brighter band travels through the words.
|
|
541
|
+
Used by ui/shimmer-text (and, through it, ui/thinking-label). */
|
|
542
|
+
@keyframes corbits-shimmer-sweep {
|
|
543
|
+
0% {
|
|
544
|
+
background-position: 150% 0;
|
|
545
|
+
}
|
|
546
|
+
100% {
|
|
547
|
+
background-position: -50% 0;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/* Toast motion: a pure 160ms fade, centered above the bottom edge — no
|
|
552
|
+
slide, no lift. Sonner enters and exits by transitioning translateY, so
|
|
553
|
+
the transform is pinned (!important, since sonner injects its stylesheet
|
|
554
|
+
at runtime after any linked sheet) and only opacity is left to move. The
|
|
555
|
+
durations stay normal-weight declarations so the reduced-motion override
|
|
556
|
+
below still collapses them. Ships by ui/toast. */
|
|
557
|
+
[data-sonner-toaster] [data-sonner-toast].corbits-toast {
|
|
558
|
+
left: 50%;
|
|
559
|
+
transform: translateX(-50%) !important;
|
|
560
|
+
transition-property: opacity;
|
|
561
|
+
transition-duration: 160ms;
|
|
562
|
+
transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
|
|
563
|
+
}
|
|
564
|
+
[data-sonner-toaster] [data-sonner-toast].corbits-toast[data-removed="true"] {
|
|
565
|
+
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/* Motion is opt-out at the foundation, not per component: anything animated
|
|
569
|
+
anywhere collapses to a single frame when the OS asks for reduced motion.
|
|
570
|
+
Component families added later inherit this for free. */
|
|
571
|
+
@media (prefers-reduced-motion: reduce) {
|
|
572
|
+
*,
|
|
573
|
+
*::before,
|
|
574
|
+
*::after {
|
|
575
|
+
animation-duration: 0.01ms !important;
|
|
576
|
+
animation-iteration-count: 1 !important;
|
|
577
|
+
transition-duration: 0.01ms !important;
|
|
578
|
+
scroll-behavior: auto !important;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/* The theme's base layer, so a consumer
|
|
583
|
+
gets the default border color, the ground, the type and — critically — one
|
|
584
|
+
focus ring for the whole app. Before this shipped, three primitives each
|
|
585
|
+
re-declared the same focus-visible outline by hand. Plain CSS rather than
|
|
586
|
+
@apply so a consumer reading the shipped CSS sees the same rules written here. */
|
|
587
|
+
@layer base {
|
|
588
|
+
* {
|
|
589
|
+
border-color: var(--border);
|
|
590
|
+
}
|
|
591
|
+
body {
|
|
592
|
+
background-color: var(--background);
|
|
593
|
+
color: var(--foreground);
|
|
594
|
+
font-family: var(--font-sans);
|
|
595
|
+
-webkit-font-smoothing: antialiased;
|
|
596
|
+
-moz-osx-font-smoothing: grayscale;
|
|
597
|
+
}
|
|
598
|
+
:focus-visible {
|
|
599
|
+
outline: 2px solid var(--ring);
|
|
600
|
+
outline-offset: 2px;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/* Ridge-study motion: keep geometry and timing in the original 100 x 70 space. */
|
|
605
|
+
@keyframes corbits-thinking-sweep {
|
|
606
|
+
0% { transform: translateX(8px); opacity: 0; }
|
|
607
|
+
8%, 86% { opacity: 1; }
|
|
608
|
+
100% { transform: translateX(130px); opacity: 0; }
|
|
609
|
+
}
|
|
610
|
+
@keyframes corbits-thinking-rise {
|
|
611
|
+
0% { transform: translateY(88px); }
|
|
612
|
+
100% { transform: translateY(-30px); }
|
|
613
|
+
}
|
|
614
|
+
@keyframes corbits-thinking-wave {
|
|
615
|
+
0% { transform: scale(.03); opacity: 0; }
|
|
616
|
+
10% { opacity: 1; }
|
|
617
|
+
75% { opacity: .9; }
|
|
618
|
+
100% { transform: scale(1.35); opacity: 0; }
|
|
619
|
+
}
|
|
620
|
+
@media (prefers-reduced-motion: reduce) {
|
|
621
|
+
/* Static poses land the gradient mid-stroke. These offsets mirror the SVG
|
|
622
|
+
geometry in thinking-mark.tsx — change the rect/circle geometry there and
|
|
623
|
+
these poses have to be re-picked to match. */
|
|
624
|
+
.corbits-thinking-silk, .corbits-thinking-strata, .corbits-thinking-echo { animation: none; }
|
|
625
|
+
.corbits-thinking-silk { transform: translateX(44px); }
|
|
626
|
+
.corbits-thinking-strata { transform: translateY(30px); }
|
|
627
|
+
.corbits-thinking-echo { transform: scale(.6); }
|
|
628
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { type AgentIdentity, type ChatMessage } from "../lib/chat-message.js";
|
|
3
|
+
export type AgentTurnProps = {
|
|
4
|
+
readonly message: ChatMessage;
|
|
5
|
+
readonly identity: AgentIdentity;
|
|
6
|
+
/** Rich body for the answer — a markdown renderer. */
|
|
7
|
+
readonly children?: ReactNode;
|
|
8
|
+
readonly now?: number;
|
|
9
|
+
/** e.g. "Thought for 4s". Shown on the reasoning block once it stops streaming. */
|
|
10
|
+
readonly reasoningDurationLabel?: string;
|
|
11
|
+
readonly className?: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* One agent reply, in the order it happened: what it thought, what it did, what
|
|
15
|
+
* it said.
|
|
16
|
+
*
|
|
17
|
+
* Parts are rendered in the order the model produced them rather than grouped
|
|
18
|
+
* by kind — a turn that thinks, calls a tool, thinks again and then answers
|
|
19
|
+
* reads as a sequence, and sorting it into "all thinking / all tools / answer"
|
|
20
|
+
* describes a turn that never happened.
|
|
21
|
+
*
|
|
22
|
+
* The avatar is `aria-hidden` and the turn is a labelled region instead: a
|
|
23
|
+
* screen reader should hear "Ada said …" once, not two initials followed by the
|
|
24
|
+
* name.
|
|
25
|
+
*/
|
|
26
|
+
export declare function AgentTurn({ message, identity, children, now, reasoningDurationLabel, className, }: AgentTurnProps): import("react").JSX.Element;
|