@runtypelabs/persona 4.17.0 → 4.18.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/dist/animations/glyph-cycle.d.cts +1 -1
- package/dist/animations/glyph-cycle.d.ts +1 -1
- package/dist/animations/{types-BpWGm7_6.d.cts → types-DsmTD8TO.d.cts} +12 -0
- package/dist/animations/{types-BpWGm7_6.d.ts → types-DsmTD8TO.d.ts} +12 -0
- package/dist/animations/wipe.d.cts +1 -1
- package/dist/animations/wipe.d.ts +1 -1
- package/dist/chunk-3I2S3I5P.js +1 -0
- package/dist/chunk-76IELU7F.js +1 -0
- package/dist/chunk-EFJBUH5F.js +1 -0
- package/dist/chunk-PDPVORUF.js +1 -0
- package/dist/chunk-Q735PSZL.js +1 -0
- package/dist/chunk-VK6JOIYJ.js +1 -0
- package/dist/codegen.cjs +4 -4
- package/dist/codegen.js +4 -4
- package/dist/{context-mentions-BTSTIBFC.js → context-mentions-MJL6S6P2.js} +1 -1
- package/dist/context-mentions.cjs +9 -8
- package/dist/context-mentions.d.cts +1224 -14
- package/dist/context-mentions.d.ts +1224 -14
- package/dist/context-mentions.js +9 -8
- package/dist/event-stream-view-4EZ7BGFK.js +1 -0
- package/dist/event-stream-view.cjs +129 -0
- package/dist/event-stream-view.d.cts +8384 -0
- package/dist/event-stream-view.d.ts +8384 -0
- package/dist/event-stream-view.js +129 -0
- package/dist/history-view-BD6OXLNA.js +898 -0
- package/dist/history-view.cjs +898 -0
- package/dist/history-view.d.cts +1461 -0
- package/dist/history-view.d.ts +1461 -0
- package/dist/history-view.js +898 -0
- package/dist/index.cjs +77 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2040 -21
- package/dist/index.d.ts +2040 -21
- package/dist/index.global.js +67 -66
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +77 -77
- package/dist/index.js.map +1 -1
- package/dist/launcher.global.js +5 -4
- package/dist/launcher.global.js.map +1 -1
- package/dist/plugin-kit.cjs +1 -1
- package/dist/plugin-kit.d.cts +0 -8
- package/dist/plugin-kit.d.ts +0 -8
- package/dist/plugin-kit.js +1 -1
- package/dist/smart-dom-reader.d.cts +1224 -14
- package/dist/smart-dom-reader.d.ts +1224 -14
- package/dist/theme-editor-preview.cjs +970 -73
- package/dist/theme-editor-preview.d.cts +1343 -15
- package/dist/theme-editor-preview.d.ts +1343 -15
- package/dist/theme-editor-preview.js +81 -81
- package/dist/theme-editor.cjs +7 -7
- package/dist/theme-editor.d.cts +1227 -15
- package/dist/theme-editor.d.ts +1227 -15
- package/dist/theme-editor.js +9 -9
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.d.cts +226 -7
- package/dist/theme-reference.d.ts +226 -7
- package/dist/theme-reference.js +1 -1
- package/dist/webmcp-polyfill.js +2 -2
- package/dist/widget.css +1 -1
- package/package.json +18 -6
- package/src/client-history-rest.test.ts +1034 -0
- package/src/client-visitor-history.test.ts +596 -0
- package/src/client.ts +1040 -24
- package/src/components/artifact-inline.ts +8 -1
- package/src/components/artifact-pane.test.ts +278 -1
- package/src/components/artifact-pane.ts +135 -67
- package/src/components/artifact-preview.test.ts +14 -1
- package/src/components/artifact-preview.ts +9 -0
- package/src/components/header-builder.ts +3 -0
- package/src/components/header-layouts.test.ts +171 -7
- package/src/components/header-layouts.ts +83 -53
- package/src/components/header-parts.test.ts +154 -1
- package/src/components/header-parts.ts +266 -138
- package/src/components/history-confirm-dialog.ts +177 -0
- package/src/components/history-shell-copy.ts +99 -0
- package/src/components/history-view/announcer.ts +40 -0
- package/src/components/history-view/copy.ts +105 -0
- package/src/components/history-view/css.ts +1078 -0
- package/src/components/history-view/grouping.test.ts +142 -0
- package/src/components/history-view/grouping.ts +142 -0
- package/src/components/history-view/icons.ts +73 -0
- package/src/components/history-view/rows.ts +341 -0
- package/src/components/history-view/state.ts +309 -0
- package/src/components/history-view.test.ts +2660 -0
- package/src/components/history-view.ts +1891 -0
- package/src/components/launcher-surface.test.ts +133 -0
- package/src/components/launcher.test.ts +18 -0
- package/src/components/launcher.ts +7 -7
- package/src/components/panel.ts +17 -7
- package/src/components/welcome.ts +72 -2
- package/src/defaults.ts +36 -3
- package/src/event-stream-view-bundle.test.ts +69 -0
- package/src/event-stream-view-entry.ts +19 -0
- package/src/event-stream-view-loader.ts +31 -0
- package/src/event-stream-view.ts +19 -0
- package/src/generated/runtype-openapi-contract.ts +54 -4
- package/src/history-render.ts +325 -0
- package/src/history-view-bundle.test.ts +78 -0
- package/src/history-view-entry.ts +41 -0
- package/src/history-view-loader.test.ts +30 -0
- package/src/history-view-loader.ts +32 -0
- package/src/history-view.ts +28 -0
- package/src/index-core.ts +50 -2
- package/src/index-global.ts +55 -0
- package/src/internal/demo-history-provider.test.ts +402 -0
- package/src/internal/demo-history-provider.ts +689 -0
- package/src/internal/history-provider-registry.ts +25 -0
- package/src/internal/history-provider.ts +150 -0
- package/src/internal/runtype-history-provider.test.ts +313 -0
- package/src/internal/runtype-history-provider.ts +240 -0
- package/src/plugin-kit.test.ts +16 -0
- package/src/plugin-kit.ts +13 -5
- package/src/plugins/types.ts +177 -1
- package/src/session-history.test.ts +1397 -0
- package/src/session.ts +1200 -26
- package/src/styles/widget-styles.test.ts +133 -0
- package/src/styles/widget.css +227 -8
- package/src/theme-editor/preview-utils.test.ts +19 -0
- package/src/theme-editor/preview-utils.ts +15 -1
- package/src/theme-editor/preview.ts +7 -1
- package/src/theme-editor/role-mappings.ts +4 -1
- package/src/theme-editor/sections.test.ts +168 -1
- package/src/theme-editor/sections.ts +136 -7
- package/src/theme-editor/webmcp/summary.ts +16 -2
- package/src/theme-reference.ts +20 -6
- package/src/types/theme.ts +213 -7
- package/src/types.ts +927 -7
- package/src/ui.artifact-rail-resize.test.ts +235 -0
- package/src/ui.attachments-drop.test.ts +1 -0
- package/src/ui.header-update-stability.test.ts +2 -2
- package/src/ui.history-chunk.test.ts +72 -0
- package/src/ui.history-config-provider.test.ts +318 -0
- package/src/ui.history-controller.test.ts +711 -0
- package/src/ui.history-lifecycle.test.ts +456 -0
- package/src/ui.history-render-hooks.test.ts +904 -0
- package/src/ui.history-shell.test.ts +1887 -0
- package/src/ui.rail-overlay.test.ts +573 -0
- package/src/ui.rail-resize.test.ts +284 -0
- package/src/ui.rebuild-composer.test.ts +21 -0
- package/src/ui.render-welcome.test.ts +42 -0
- package/src/ui.shortcuts.test.ts +166 -0
- package/src/ui.ts +3071 -240
- package/src/utils/__fixtures__/client-conversation-history-wire.json +108 -0
- package/src/utils/artifact-file.ts +15 -0
- package/src/utils/artifact-gate.test.ts +4 -0
- package/src/utils/artifact-gate.ts +13 -17
- package/src/utils/artifact-resize.test.ts +28 -0
- package/src/utils/artifact-resize.ts +9 -2
- package/src/utils/buttons.ts +188 -1
- package/src/utils/config-merge.test.ts +91 -0
- package/src/utils/dropdown.ts +10 -1
- package/src/utils/history-messages.test.ts +284 -0
- package/src/utils/history-messages.ts +284 -0
- package/src/utils/icons.ts +3 -0
- package/src/utils/shortcuts.test.ts +288 -0
- package/src/utils/shortcuts.ts +221 -0
- package/src/utils/theme.test.ts +501 -4
- package/src/utils/theme.ts +42 -3
- package/src/utils/tokens.ts +153 -15
- package/src/utils/tooltip-timing.ts +4 -0
- package/src/utils/tooltip.test.ts +249 -7
- package/src/utils/tooltip.ts +146 -4
- package/src/utils/visitor-store.test.ts +425 -0
- package/src/utils/visitor-store.ts +337 -0
- package/dist/chunk-QJ4LV2KW.js +0 -1
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
COMPONENT_COLOR_SECTIONS,
|
|
5
|
+
COMPONENT_SHAPE_SECTIONS,
|
|
6
|
+
COMPONENTS_SECTIONS,
|
|
7
|
+
CONFIGURE_SECTIONS,
|
|
8
|
+
INTERFACE_ROLES_SECTION,
|
|
9
|
+
STYLE_SECTIONS,
|
|
10
|
+
} from "./sections";
|
|
4
11
|
import { ALL_ROLES } from "./role-mappings";
|
|
5
12
|
|
|
6
13
|
describe("theme editor scroll-to-bottom controls", () => {
|
|
@@ -93,6 +100,166 @@ describe("theme editor scroll-to-bottom controls", () => {
|
|
|
93
100
|
);
|
|
94
101
|
});
|
|
95
102
|
|
|
103
|
+
it("exposes the launcher icon stroke as a unitless slider", () => {
|
|
104
|
+
const section = COMPONENT_SHAPE_SECTIONS.find(
|
|
105
|
+
(entry) => entry.id === "comp-launcher"
|
|
106
|
+
);
|
|
107
|
+
const stroke = section?.fields.find(
|
|
108
|
+
(field) => field.path === "theme.components.launcher.iconStrokeWidth"
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
expect(stroke?.defaultValue).toBe("1.5");
|
|
112
|
+
// Unitless slider: the stroke must never pick up a px suffix, and the
|
|
113
|
+
// WebMCP escape hatch coerces sliders to raw numbers while token
|
|
114
|
+
// resolution only walks string values.
|
|
115
|
+
expect(stroke?.slider?.unit).toBe("none");
|
|
116
|
+
expect(stroke?.parseValue?.(1.5)).toBe("1.5");
|
|
117
|
+
expect(stroke?.parseValue?.("1.75")).toBe("1.75");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("exposes the three shared header control knobs as live shape fields", () => {
|
|
121
|
+
const section = COMPONENT_SHAPE_SECTIONS.find(
|
|
122
|
+
(entry) => entry.id === "comp-header-controls"
|
|
123
|
+
);
|
|
124
|
+
const fieldsByPath = new Map(
|
|
125
|
+
section?.fields.map((field) => [field.path, field]) ?? []
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const size = fieldsByPath.get("theme.components.header.controlSize");
|
|
129
|
+
const iconSize = fieldsByPath.get("theme.components.header.controlIconSize");
|
|
130
|
+
const stroke = fieldsByPath.get("theme.components.header.controlStrokeWidth");
|
|
131
|
+
|
|
132
|
+
expect(size?.defaultValue).toBe("32px");
|
|
133
|
+
expect(iconSize?.defaultValue).toBe("20px");
|
|
134
|
+
expect(stroke?.defaultValue).toBe("1.5");
|
|
135
|
+
|
|
136
|
+
// Unitless slider: the stroke must never pick up a px suffix.
|
|
137
|
+
expect(stroke?.slider?.unit).toBe("none");
|
|
138
|
+
expect(size?.slider?.unit).toBeUndefined();
|
|
139
|
+
|
|
140
|
+
// The WebMCP escape hatch coerces sliders to raw numbers, and token
|
|
141
|
+
// resolution only walks string values.
|
|
142
|
+
expect(size?.parseValue?.(44)).toBe("44px");
|
|
143
|
+
expect(size?.parseValue?.("2.5rem")).toBe("2.5rem");
|
|
144
|
+
expect(stroke?.parseValue?.(2)).toBe("2");
|
|
145
|
+
expect(stroke?.parseValue?.("1.75")).toBe("1.75");
|
|
146
|
+
|
|
147
|
+
// Sizes are not colors: light/dark scoping must never fork them.
|
|
148
|
+
expect(
|
|
149
|
+
COMPONENT_COLOR_SECTIONS.some((entry) => entry.id === "comp-header-controls")
|
|
150
|
+
).toBe(false);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("exposes the header and rail header band controls", () => {
|
|
154
|
+
const headerControls = COMPONENT_SHAPE_SECTIONS.find(
|
|
155
|
+
(entry) => entry.id === "comp-header-controls"
|
|
156
|
+
);
|
|
157
|
+
const minHeight = headerControls?.fields.find(
|
|
158
|
+
(field) => field.path === "theme.components.header.minHeight"
|
|
159
|
+
);
|
|
160
|
+
expect(minHeight?.type).toBe("text");
|
|
161
|
+
// Blank keeps the built-in auto height instead of writing an empty token.
|
|
162
|
+
expect(minHeight?.parseValue?.(" 65px ")).toBe("65px");
|
|
163
|
+
expect(minHeight?.parseValue?.("")).toBeUndefined();
|
|
164
|
+
|
|
165
|
+
const railShape = COMPONENT_SHAPE_SECTIONS.find(
|
|
166
|
+
(entry) => entry.id === "comp-history-rail-header"
|
|
167
|
+
);
|
|
168
|
+
const railPaths = railShape?.fields.map((field) => field.path) ?? [];
|
|
169
|
+
expect(railPaths).toEqual([
|
|
170
|
+
"theme.components.history.railHeader.minHeight",
|
|
171
|
+
"theme.components.history.railHeader.border",
|
|
172
|
+
]);
|
|
173
|
+
|
|
174
|
+
const railColors = COMPONENT_COLOR_SECTIONS.find(
|
|
175
|
+
(entry) => entry.id === "comp-history-rail-header-colors"
|
|
176
|
+
);
|
|
177
|
+
const background = railColors?.fields.find(
|
|
178
|
+
(field) => field.path === "theme.components.history.railHeader.background"
|
|
179
|
+
);
|
|
180
|
+
expect(background?.type).toBe("token-ref");
|
|
181
|
+
expect(background?.tokenRef?.tokenType).toBe("color");
|
|
182
|
+
|
|
183
|
+
// Sizes are not colors: light/dark scoping must never fork them.
|
|
184
|
+
expect(
|
|
185
|
+
COMPONENT_COLOR_SECTIONS.some(
|
|
186
|
+
(entry) => entry.id === "comp-history-rail-header"
|
|
187
|
+
)
|
|
188
|
+
).toBe(false);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("exposes the floating rail surface controls", () => {
|
|
192
|
+
const shape = COMPONENT_SHAPE_SECTIONS.find(
|
|
193
|
+
(entry) => entry.id === "comp-history-overlay"
|
|
194
|
+
);
|
|
195
|
+
expect(shape?.fields.map((field) => field.path)).toEqual([
|
|
196
|
+
"theme.components.history.overlay.margin",
|
|
197
|
+
"theme.components.history.overlay.borderRadius",
|
|
198
|
+
"theme.components.history.overlay.shadow",
|
|
199
|
+
]);
|
|
200
|
+
// Blank keeps the built-in default instead of writing an empty token.
|
|
201
|
+
const margin = shape?.fields[0];
|
|
202
|
+
expect(margin?.type).toBe("text");
|
|
203
|
+
expect(margin?.parseValue?.(" 12px ")).toBe("12px");
|
|
204
|
+
expect(margin?.parseValue?.("")).toBeUndefined();
|
|
205
|
+
|
|
206
|
+
const colors = COMPONENT_COLOR_SECTIONS.find(
|
|
207
|
+
(entry) => entry.id === "comp-history-overlay-colors"
|
|
208
|
+
);
|
|
209
|
+
const background = colors?.fields.find(
|
|
210
|
+
(field) => field.path === "theme.components.history.overlay.background"
|
|
211
|
+
);
|
|
212
|
+
expect(background?.type).toBe("token-ref");
|
|
213
|
+
expect(background?.tokenRef?.tokenType).toBe("color");
|
|
214
|
+
|
|
215
|
+
// Geometry is not color: the shape section never forks per light/dark.
|
|
216
|
+
expect(
|
|
217
|
+
COMPONENT_COLOR_SECTIONS.some((entry) => entry.id === "comp-history-overlay")
|
|
218
|
+
).toBe(false);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it("exposes the tooltip shape and color controls", () => {
|
|
222
|
+
const shape = COMPONENT_SHAPE_SECTIONS.find(
|
|
223
|
+
(entry) => entry.id === "comp-tooltip"
|
|
224
|
+
);
|
|
225
|
+
const shapePaths = shape?.fields.map((field) => field.path) ?? [];
|
|
226
|
+
expect(shapePaths).toEqual([
|
|
227
|
+
"theme.components.tooltip.borderRadius",
|
|
228
|
+
"theme.components.tooltip.fontSize",
|
|
229
|
+
"theme.components.tooltip.arrow",
|
|
230
|
+
]);
|
|
231
|
+
|
|
232
|
+
const fontSize = shape?.fields.find(
|
|
233
|
+
(field) => field.path === "theme.components.tooltip.fontSize"
|
|
234
|
+
);
|
|
235
|
+
// Blank keeps the built-in 12px instead of writing an empty token.
|
|
236
|
+
expect(fontSize?.parseValue?.(" 13px ")).toBe("13px");
|
|
237
|
+
expect(fontSize?.parseValue?.("")).toBeUndefined();
|
|
238
|
+
|
|
239
|
+
const arrow = shape?.fields.find(
|
|
240
|
+
(field) => field.path === "theme.components.tooltip.arrow"
|
|
241
|
+
);
|
|
242
|
+
expect(arrow?.type).toBe("toggle");
|
|
243
|
+
expect(arrow?.defaultValue).toBe(true);
|
|
244
|
+
|
|
245
|
+
const colors = COMPONENT_COLOR_SECTIONS.find(
|
|
246
|
+
(entry) => entry.id === "comp-tooltip-colors"
|
|
247
|
+
);
|
|
248
|
+
expect(colors?.fields.map((field) => field.path)).toEqual([
|
|
249
|
+
"theme.components.tooltip.background",
|
|
250
|
+
"theme.components.tooltip.foreground",
|
|
251
|
+
"theme.components.tooltip.hintForeground",
|
|
252
|
+
]);
|
|
253
|
+
expect(
|
|
254
|
+
colors?.fields.every((field) => field.tokenRef?.tokenType === "color")
|
|
255
|
+
).toBe(true);
|
|
256
|
+
|
|
257
|
+
// Sizes are not colors: light/dark scoping must never fork them.
|
|
258
|
+
expect(
|
|
259
|
+
COMPONENT_COLOR_SECTIONS.some((entry) => entry.id === "comp-tooltip")
|
|
260
|
+
).toBe(false);
|
|
261
|
+
});
|
|
262
|
+
|
|
96
263
|
it("exposes a shadow control for every themeable component", () => {
|
|
97
264
|
const fieldPaths = COMPONENTS_SECTIONS.flatMap((section) => section.fields.map((field) => field.path));
|
|
98
265
|
|
|
@@ -27,6 +27,13 @@ const parseOptionalCssValue = (value: unknown): string | undefined => {
|
|
|
27
27
|
return normalized || undefined;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
+
// Slider controls emit CSS strings, but the WebMCP escape hatch coerces a
|
|
31
|
+
// slider to a raw number and token resolution only walks string values.
|
|
32
|
+
const parseSliderPxLength = (value: unknown): string =>
|
|
33
|
+
typeof value === 'number' ? `${value}px` : String(value ?? '').trim();
|
|
34
|
+
|
|
35
|
+
const parseSliderUnitless = (value: unknown): string => String(value ?? '').trim();
|
|
36
|
+
|
|
30
37
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
31
38
|
// STYLE TAB: brand colors, chat colors, typography, shape, etc.
|
|
32
39
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
@@ -72,11 +79,12 @@ const chatColorsSectionDef: SectionDef = {
|
|
|
72
79
|
collapsed: true,
|
|
73
80
|
fields: [
|
|
74
81
|
{ id: 'chat-header-bg', label: 'Header Background', type: 'token-ref', path: 'theme.components.header.background', defaultValue: 'semantic.colors.surface', tokenRef: { tokenType: 'color' } },
|
|
82
|
+
{ id: 'chat-header-fg', label: 'Header Foreground', description: 'Anchors the header text. The title takes it, the subtitle and button icons take a 72% mix of it over the background', type: 'token-ref', path: 'theme.components.header.foreground', defaultValue: '', tokenRef: { tokenType: 'color' } },
|
|
75
83
|
{ id: 'chat-header-icon-bg', label: 'Header Icon Background', type: 'token-ref', path: 'theme.components.header.iconBackground', defaultValue: 'semantic.colors.primary', tokenRef: { tokenType: 'color' } },
|
|
76
84
|
{ id: 'chat-header-icon-fg', label: 'Header Icon Color', type: 'token-ref', path: 'theme.components.header.iconForeground', defaultValue: 'semantic.colors.textInverse', tokenRef: { tokenType: 'color' } },
|
|
77
|
-
{ id: 'chat-header-title-fg', label: 'Header Title Color', type: 'token-ref', path: 'theme.components.header.titleForeground', defaultValue: '
|
|
78
|
-
{ id: 'chat-header-subtitle-fg', label: 'Header Subtitle Color', type: 'token-ref', path: 'theme.components.header.subtitleForeground', defaultValue: '
|
|
79
|
-
{ id: 'chat-header-action-icons-fg', label: 'Header Button Icons', type: 'token-ref', path: 'theme.components.header.actionIconForeground', defaultValue: '
|
|
85
|
+
{ id: 'chat-header-title-fg', label: 'Header Title Color', description: 'Blank follows the header foreground', type: 'token-ref', path: 'theme.components.header.titleForeground', defaultValue: '', tokenRef: { tokenType: 'color' } },
|
|
86
|
+
{ id: 'chat-header-subtitle-fg', label: 'Header Subtitle Color', description: 'Blank follows the 72% foreground mix', type: 'token-ref', path: 'theme.components.header.subtitleForeground', defaultValue: '', tokenRef: { tokenType: 'color' } },
|
|
87
|
+
{ id: 'chat-header-action-icons-fg', label: 'Header Button Icons', description: 'Blank follows the 72% foreground mix', type: 'token-ref', path: 'theme.components.header.actionIconForeground', defaultValue: '', tokenRef: { tokenType: 'color' } },
|
|
80
88
|
{ id: 'chat-msg-user-bg', label: 'User Message Background', type: 'token-ref', path: 'theme.components.message.user.background', defaultValue: 'semantic.colors.primary', tokenRef: { tokenType: 'color' } },
|
|
81
89
|
{ id: 'chat-msg-user-text', label: 'User Message Text', type: 'token-ref', path: 'theme.components.message.user.text', defaultValue: 'semantic.colors.textInverse', tokenRef: { tokenType: 'color' } },
|
|
82
90
|
{ id: 'chat-msg-assistant-bg', label: 'Assistant Message Background', type: 'token-ref', path: 'theme.components.message.assistant.background', defaultValue: 'semantic.colors.container', tokenRef: { tokenType: 'color' } },
|
|
@@ -316,6 +324,7 @@ const launcherLayoutSectionDef: SectionDef = {
|
|
|
316
324
|
fields: [
|
|
317
325
|
{ id: 'launcher-size', label: 'Size', type: 'slider', path: 'theme.components.launcher.size', defaultValue: '60px', slider: { min: 32, max: 80, step: 2 } },
|
|
318
326
|
{ id: 'launcher-icon-size', label: 'Icon Size', type: 'slider', path: 'theme.components.launcher.iconSize', defaultValue: '28px', slider: { min: 16, max: 48, step: 2 } },
|
|
327
|
+
{ id: 'launcher-icon-stroke-width', label: 'Icon Stroke Width', description: 'Unitless line weight for the agent glyph and the call-to-action arrow', type: 'slider', path: 'theme.components.launcher.iconStrokeWidth', defaultValue: '1.5', slider: { min: 1, max: 2.5, step: 0.25, unit: 'none' }, parseValue: parseSliderUnitless },
|
|
319
328
|
{ id: 'launcher-border-radius', label: 'Border Radius', type: 'select', path: 'theme.components.launcher.borderRadius', defaultValue: 'palette.radius.full', options: [
|
|
320
329
|
{ value: 'palette.radius.md', label: 'Medium' },
|
|
321
330
|
{ value: 'palette.radius.lg', label: 'Large' },
|
|
@@ -332,6 +341,115 @@ const launcherLayoutSectionDef: SectionDef = {
|
|
|
332
341
|
],
|
|
333
342
|
};
|
|
334
343
|
|
|
344
|
+
const headerControlsSectionDef: SectionDef = {
|
|
345
|
+
id: 'comp-header-controls',
|
|
346
|
+
title: 'Header Controls',
|
|
347
|
+
description:
|
|
348
|
+
'One box, glyph, and stroke shared by every header icon button: close, clear chat, trailing actions, and Messages, plus the strip height.',
|
|
349
|
+
collapsed: true,
|
|
350
|
+
fields: [
|
|
351
|
+
{ id: 'header-min-height', label: 'Header Min Height', description: 'CSS length, e.g. 65px. Blank stays at the natural height', type: 'text', path: 'theme.components.header.minHeight', defaultValue: '', parseValue: parseOptionalCssValue },
|
|
352
|
+
{ id: 'header-control-size', label: 'Control Size', description: 'The button box. Coarse pointers still floor the hit area at 40px', type: 'slider', path: 'theme.components.header.controlSize', defaultValue: '32px', slider: { min: 24, max: 64, step: 2 }, parseValue: parseSliderPxLength },
|
|
353
|
+
{ id: 'header-control-icon-size', label: 'Icon Size', description: 'The glyph inside the button', type: 'slider', path: 'theme.components.header.controlIconSize', defaultValue: '20px', slider: { min: 12, max: 40, step: 1 }, parseValue: parseSliderPxLength },
|
|
354
|
+
{ id: 'header-control-stroke-width', label: 'Icon Stroke Width', description: 'Unitless line weight. The close X renders at 0.7 of it so its sparser glyph matches', type: 'slider', path: 'theme.components.header.controlStrokeWidth', defaultValue: '1.5', slider: { min: 1, max: 2.5, step: 0.25, unit: 'none' }, parseValue: parseSliderUnitless },
|
|
355
|
+
],
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// The Messages rail's own top strip, beside the widget header in rail
|
|
359
|
+
// presentation. Its color lives in COMPONENT_COLOR_SECTIONS.
|
|
360
|
+
const historyRailHeaderShapeSectionDef: SectionDef = {
|
|
361
|
+
id: 'comp-history-rail-header',
|
|
362
|
+
title: 'Messages Rail Header',
|
|
363
|
+
description:
|
|
364
|
+
'The Messages rail top strip. Match its height to the header so both read as one band.',
|
|
365
|
+
collapsed: true,
|
|
366
|
+
fields: [
|
|
367
|
+
{ id: 'rail-header-min-height', label: 'Min Height', description: 'CSS length. Blank follows the header min height', type: 'text', path: 'theme.components.history.railHeader.minHeight', defaultValue: '', parseValue: parseOptionalCssValue },
|
|
368
|
+
{ id: 'rail-header-border', label: 'Bottom Border', description: 'Full border-bottom shorthand, e.g. 1px solid #333', type: 'text', path: 'theme.components.history.railHeader.border', defaultValue: '', parseValue: parseOptionalCssValue },
|
|
369
|
+
],
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
const historyRailHeaderColorsSectionDef: SectionDef = {
|
|
373
|
+
id: 'comp-history-rail-header-colors',
|
|
374
|
+
title: 'Messages Rail Header Colors',
|
|
375
|
+
collapsed: true,
|
|
376
|
+
fields: [
|
|
377
|
+
{ id: 'rail-header-bg', label: 'Background', type: 'token-ref', path: 'theme.components.history.railHeader.background', defaultValue: 'semantic.colors.container', tokenRef: { tokenType: 'color' } },
|
|
378
|
+
],
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
// The floating rail a collapsed overlay rail opens on hover. Its width and
|
|
382
|
+
// edge stay features.history.rail config; only the surface is themeable.
|
|
383
|
+
const historyOverlayShapeSectionDef: SectionDef = {
|
|
384
|
+
id: 'comp-history-overlay',
|
|
385
|
+
title: 'Messages Floating Rail',
|
|
386
|
+
description:
|
|
387
|
+
'The Messages rail floating over the conversation, when a collapsed rail opens on hover.',
|
|
388
|
+
collapsed: true,
|
|
389
|
+
fields: [
|
|
390
|
+
{ id: 'history-overlay-margin', label: 'Margin', description: 'Gap from the trigger, the docked edge and the bottom', type: 'text', path: 'theme.components.history.overlay.margin', defaultValue: '', parseValue: parseOptionalCssValue },
|
|
391
|
+
{ id: 'history-overlay-radius', label: 'Corner Radius', description: 'CSS length on all four corners. Blank keeps 16px', type: 'text', path: 'theme.components.history.overlay.borderRadius', defaultValue: '', parseValue: parseOptionalCssValue },
|
|
392
|
+
{ id: 'history-overlay-shadow', label: 'Shadow', description: 'Full box-shadow shorthand. Blank keeps the built-in elevation', type: 'text', path: 'theme.components.history.overlay.shadow', defaultValue: '', parseValue: parseOptionalCssValue },
|
|
393
|
+
],
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const historyOverlayColorsSectionDef: SectionDef = {
|
|
397
|
+
id: 'comp-history-overlay-colors',
|
|
398
|
+
title: 'Messages Floating Rail Colors',
|
|
399
|
+
collapsed: true,
|
|
400
|
+
fields: [
|
|
401
|
+
{ id: 'history-overlay-bg', label: 'Background', type: 'token-ref', path: 'theme.components.history.overlay.background', defaultValue: 'semantic.colors.container', tokenRef: { tokenType: 'color' } },
|
|
402
|
+
],
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
// Enter/exit motion of the Messages surface. Durations, not colors, so it
|
|
406
|
+
// stays a shape section and never forks per scheme.
|
|
407
|
+
const historyMotionSectionDef: SectionDef = {
|
|
408
|
+
id: 'comp-history-motion',
|
|
409
|
+
title: 'Messages Motion',
|
|
410
|
+
description:
|
|
411
|
+
'Enter and exit animation of the Messages body. The bar is persistent chrome and never animates; reduced-motion preferences always win.',
|
|
412
|
+
collapsed: true,
|
|
413
|
+
fields: [
|
|
414
|
+
{ id: 'history-motion-enter-ms', label: 'Enter Duration', description: 'Milliseconds, e.g. 180. 0 disables the entrance. Blank keeps 180', type: 'text', path: 'theme.components.history.motion.enterDurationMs', defaultValue: '', parseValue: parseOptionalCssValue },
|
|
415
|
+
{ id: 'history-motion-enter-easing', label: 'Enter Easing', description: 'CSS easing, e.g. ease-out or cubic-bezier(0, 0, 0.2, 1)', type: 'text', path: 'theme.components.history.motion.enterEasing', defaultValue: '', parseValue: parseOptionalCssValue },
|
|
416
|
+
{ id: 'history-motion-exit-ms', label: 'Exit Duration', description: 'Milliseconds, e.g. 160. 0 disables the exit. Blank keeps 160', type: 'text', path: 'theme.components.history.motion.exitDurationMs', defaultValue: '', parseValue: parseOptionalCssValue },
|
|
417
|
+
{ id: 'history-motion-exit-easing', label: 'Exit Easing', description: 'CSS easing, e.g. ease-in or cubic-bezier(0.4, 0, 1, 1)', type: 'text', path: 'theme.components.history.motion.exitEasing', defaultValue: '', parseValue: parseOptionalCssValue },
|
|
418
|
+
],
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
// The portaled tooltip on icon controls. Its colors live in
|
|
422
|
+
// COMPONENT_COLOR_SECTIONS.
|
|
423
|
+
const tooltipShapeSectionDef: SectionDef = {
|
|
424
|
+
id: 'comp-tooltip',
|
|
425
|
+
title: 'Tooltip',
|
|
426
|
+
description:
|
|
427
|
+
'The hover and focus tooltip on icon controls, including its shortcut hint chip.',
|
|
428
|
+
collapsed: true,
|
|
429
|
+
fields: [
|
|
430
|
+
{ id: 'tooltip-radius', label: 'Corner Radius', type: 'select', path: 'theme.components.tooltip.borderRadius', defaultValue: 'palette.radius.sm', options: [
|
|
431
|
+
{ value: 'palette.radius.none', label: 'None' },
|
|
432
|
+
{ value: 'palette.radius.sm', label: 'Small' },
|
|
433
|
+
{ value: 'palette.radius.md', label: 'Medium' },
|
|
434
|
+
{ value: 'palette.radius.lg', label: 'Large' },
|
|
435
|
+
{ value: 'palette.radius.xl', label: 'Extra Large' },
|
|
436
|
+
] },
|
|
437
|
+
{ id: 'tooltip-font-size', label: 'Font Size', description: 'CSS length. Blank stays at 12px', type: 'text', path: 'theme.components.tooltip.fontSize', defaultValue: '', parseValue: parseOptionalCssValue },
|
|
438
|
+
{ id: 'tooltip-arrow', label: 'Show Arrow', description: 'The caret pointing at the control', type: 'toggle', path: 'theme.components.tooltip.arrow', defaultValue: true },
|
|
439
|
+
],
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
const tooltipColorsSectionDef: SectionDef = {
|
|
443
|
+
id: 'comp-tooltip-colors',
|
|
444
|
+
title: 'Tooltip Colors',
|
|
445
|
+
collapsed: true,
|
|
446
|
+
fields: [
|
|
447
|
+
{ id: 'tooltip-bg', label: 'Background', type: 'token-ref', path: 'theme.components.tooltip.background', defaultValue: 'palette.colors.gray.900', tokenRef: { tokenType: 'color' } },
|
|
448
|
+
{ id: 'tooltip-fg', label: 'Label', type: 'token-ref', path: 'theme.components.tooltip.foreground', defaultValue: 'palette.colors.primary.50', tokenRef: { tokenType: 'color' } },
|
|
449
|
+
{ id: 'tooltip-hint-fg', label: 'Shortcut Hint', type: 'token-ref', path: 'theme.components.tooltip.hintForeground', defaultValue: 'palette.colors.gray.400', tokenRef: { tokenType: 'color' } },
|
|
450
|
+
],
|
|
451
|
+
};
|
|
452
|
+
|
|
335
453
|
const messageShapeSectionDef: SectionDef = {
|
|
336
454
|
id: 'comp-message-shape',
|
|
337
455
|
title: 'Message Shape',
|
|
@@ -401,12 +519,13 @@ const headerColorsSectionDef: SectionDef = {
|
|
|
401
519
|
collapsed: true,
|
|
402
520
|
fields: [
|
|
403
521
|
{ id: 'header-bg', label: 'Background', type: 'token-ref', path: 'theme.components.header.background', defaultValue: 'semantic.colors.surface', tokenRef: { tokenType: 'color' } },
|
|
522
|
+
{ id: 'header-fg', label: 'Foreground', description: 'Anchors the header text. Background and foreground together derive every color left blank below', type: 'token-ref', path: 'theme.components.header.foreground', defaultValue: '', tokenRef: { tokenType: 'color' } },
|
|
404
523
|
{ id: 'header-icon-bg', label: 'Icon background', type: 'token-ref', path: 'theme.components.header.iconBackground', defaultValue: 'semantic.colors.primary', tokenRef: { tokenType: 'color' } },
|
|
405
524
|
{ id: 'header-icon-fg', label: 'Icon color', type: 'token-ref', path: 'theme.components.header.iconForeground', defaultValue: 'semantic.colors.textInverse', tokenRef: { tokenType: 'color' } },
|
|
406
|
-
{ id: 'header-title-fg', label: 'Title color', type: 'token-ref', path: 'theme.components.header.titleForeground', defaultValue: '
|
|
407
|
-
{ id: 'header-subtitle-fg', label: 'Subtitle color', type: 'token-ref', path: 'theme.components.header.subtitleForeground', defaultValue: '
|
|
408
|
-
{ id: 'header-action-icons-fg', label: 'Clear / close icons', type: 'token-ref', path: 'theme.components.header.actionIconForeground', defaultValue: '
|
|
409
|
-
{ id: 'header-border', label: 'Border', type: 'token-ref', path: 'theme.components.header.border', defaultValue: '
|
|
525
|
+
{ id: 'header-title-fg', label: 'Title color', description: 'Blank follows the header foreground', type: 'token-ref', path: 'theme.components.header.titleForeground', defaultValue: '', tokenRef: { tokenType: 'color' } },
|
|
526
|
+
{ id: 'header-subtitle-fg', label: 'Subtitle color', description: 'Blank follows a 72% mix of the foreground over the background', type: 'token-ref', path: 'theme.components.header.subtitleForeground', defaultValue: '', tokenRef: { tokenType: 'color' } },
|
|
527
|
+
{ id: 'header-action-icons-fg', label: 'Clear / close icons', description: 'Blank follows the same 72% foreground mix as the subtitle', type: 'token-ref', path: 'theme.components.header.actionIconForeground', defaultValue: '', tokenRef: { tokenType: 'color' } },
|
|
528
|
+
{ id: 'header-border', label: 'Border', description: 'Blank follows a 14% mix of the foreground over the background', type: 'token-ref', path: 'theme.components.header.border', defaultValue: '', tokenRef: { tokenType: 'color' } },
|
|
410
529
|
],
|
|
411
530
|
};
|
|
412
531
|
|
|
@@ -566,6 +685,13 @@ const textStylesSectionDef: SectionDef = {
|
|
|
566
685
|
export const COMPONENT_SHAPE_SECTIONS: SectionDef[] = [
|
|
567
686
|
panelLayoutSectionDef,
|
|
568
687
|
launcherLayoutSectionDef,
|
|
688
|
+
// Sizes, not colors: kept out of COMPONENT_COLOR_SECTIONS so scopeSection
|
|
689
|
+
// never forks them per light/dark.
|
|
690
|
+
headerControlsSectionDef,
|
|
691
|
+
historyRailHeaderShapeSectionDef,
|
|
692
|
+
historyOverlayShapeSectionDef,
|
|
693
|
+
historyMotionSectionDef,
|
|
694
|
+
tooltipShapeSectionDef,
|
|
569
695
|
messageShapeSectionDef,
|
|
570
696
|
inputShapeSectionDef,
|
|
571
697
|
composerSpacingSectionDef,
|
|
@@ -577,6 +703,9 @@ export const COMPONENT_SHAPE_SECTIONS: SectionDef[] = [
|
|
|
577
703
|
/** Component color sections (can be scoped for light/dark) */
|
|
578
704
|
export const COMPONENT_COLOR_SECTIONS: SectionDef[] = [
|
|
579
705
|
headerColorsSectionDef,
|
|
706
|
+
historyRailHeaderColorsSectionDef,
|
|
707
|
+
historyOverlayColorsSectionDef,
|
|
708
|
+
tooltipColorsSectionDef,
|
|
580
709
|
messageColorsSectionDef,
|
|
581
710
|
inputColorsSectionDef,
|
|
582
711
|
buttonColorsSectionDef,
|
|
@@ -163,13 +163,15 @@ export interface ContrastPair {
|
|
|
163
163
|
key: string;
|
|
164
164
|
label: string;
|
|
165
165
|
fg: string;
|
|
166
|
+
/** Tried in order when `fg` is unset; suggestions still write to `fg`. */
|
|
167
|
+
fgFallbacks?: string[];
|
|
166
168
|
bg: string;
|
|
167
169
|
}
|
|
168
170
|
|
|
169
171
|
export const CONTRAST_PAIRS: ContrastPair[] = [
|
|
170
172
|
{ key: 'user-message', label: 'User message text', fg: 'components.message.user.text', bg: 'components.message.user.background' },
|
|
171
173
|
{ key: 'assistant-message', label: 'Assistant message text', fg: 'components.message.assistant.text', bg: 'components.message.assistant.background' },
|
|
172
|
-
{ key: 'header', label: 'Header title', fg: 'components.header.titleForeground', bg: 'components.header.background' },
|
|
174
|
+
{ key: 'header', label: 'Header title', fg: 'components.header.titleForeground', fgFallbacks: ['components.header.foreground'], bg: 'components.header.background' },
|
|
173
175
|
{ key: 'primary-button', label: 'Primary button label', fg: 'components.button.primary.foreground', bg: 'components.button.primary.background' },
|
|
174
176
|
{ key: 'input', label: 'Input placeholder', fg: 'components.input.placeholder', bg: 'components.input.background' },
|
|
175
177
|
{ key: 'link', label: 'Link text', fg: 'components.markdown.link.foreground', bg: 'semantic.colors.background' },
|
|
@@ -178,6 +180,18 @@ export const CONTRAST_PAIRS: ContrastPair[] = [
|
|
|
178
180
|
{ key: 'surface', label: 'Body text on surface', fg: 'semantic.colors.text', bg: 'semantic.colors.surface' },
|
|
179
181
|
];
|
|
180
182
|
|
|
183
|
+
function resolveContrastForeground(
|
|
184
|
+
state: ThemeEditorLike,
|
|
185
|
+
pair: ContrastPair,
|
|
186
|
+
prefix: 'theme' | 'darkTheme'
|
|
187
|
+
): string | null {
|
|
188
|
+
for (const path of [pair.fg, ...(pair.fgFallbacks ?? [])]) {
|
|
189
|
+
const color = resolveColor(state, path, prefix);
|
|
190
|
+
if (color) return color;
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
181
195
|
/**
|
|
182
196
|
* The contrast-pair keys relevant to a role, derived by intersecting the role's
|
|
183
197
|
* target token paths with the contrast pairs. This replaces a hand-maintained
|
|
@@ -275,7 +289,7 @@ export function runContrastChecks(
|
|
|
275
289
|
for (const v of variants) {
|
|
276
290
|
const prefix = v === 'light' ? 'theme' : 'darkTheme';
|
|
277
291
|
for (const pair of pairs) {
|
|
278
|
-
const fg =
|
|
292
|
+
const fg = resolveContrastForeground(state, pair, prefix);
|
|
279
293
|
const bg = resolveColor(state, pair.bg, prefix);
|
|
280
294
|
if (!fg || !bg) continue;
|
|
281
295
|
const ratio = round2(wcagContrastRatio(fg, bg));
|
package/src/theme-reference.ts
CHANGED
|
@@ -110,7 +110,8 @@ export const THEME_TOKEN_DOCS = {
|
|
|
110
110
|
},
|
|
111
111
|
launcher: {
|
|
112
112
|
description: 'Floating launcher button.',
|
|
113
|
-
properties:
|
|
113
|
+
properties:
|
|
114
|
+
'size (60px), iconSize (28px), iconStrokeWidth (2, unitless glyph stroke weight; applies to registry-icon launchers, inert for emoji and image icons), borderRadius, shadow.',
|
|
114
115
|
},
|
|
115
116
|
panel: {
|
|
116
117
|
description: 'Chat panel container.',
|
|
@@ -118,11 +119,24 @@ export const THEME_TOKEN_DOCS = {
|
|
|
118
119
|
'width, maxWidth (440px), height (600px), maxHeight, borderRadius, shadow, inset (16px, gap around a detached panel), canvasBackground (transparent, fills the region behind a detached panel in docked and inline embed modes; a no-op in sidebar mode, where the gap stays click-through and the host page shows through like floating). inset and canvasBackground apply only when launcher.detachedPanel is true or artifacts.layout.paneAppearance is "detached".',
|
|
119
120
|
},
|
|
120
121
|
header: {
|
|
121
|
-
description:
|
|
122
|
+
description:
|
|
123
|
+
'Chat panel header. background and foreground are the pair that colors the band: set those two and the rest of the header text follows.',
|
|
122
124
|
properties:
|
|
123
|
-
'background, border, borderRadius, padding, iconBackground, iconForeground, actionIconForeground, shadow, borderBottom, title and subtitle (each fontFamily, fontSize, fontWeight, lineHeight, letterSpacing, color).',
|
|
125
|
+
'background, foreground (anchors the header text; the title takes it directly, the subtitle and action icons take color-mix(in srgb, foreground 72%, background), and the border takes color-mix(in srgb, foreground 14%, background)), border, borderRadius, padding, iconBackground, iconForeground (the avatar tile, which keeps its own defaults and never derives), actionIconForeground, controlSize (32px, the box of every header icon button), controlIconSize (20px, the glyph inside it), controlStrokeWidth (1.5, unitless glyph stroke weight; sparse-viewBox glyphs such as the close X scale it by 0.7), shadow, borderBottom, minHeight (height floor for the header strip), title and subtitle (each fontFamily, fontSize, fontWeight, lineHeight, letterSpacing, color). Derivation only fills keys the theme leaves unset, so any explicit border, titleForeground, subtitleForeground, actionIconForeground, title.color, or subtitle.color wins. With no foreground either, each key falls back as before: the primary color for the title, the muted text color for the subtitle and action icons, the divider color for the border.',
|
|
124
126
|
legacy:
|
|
125
|
-
'titleForeground and subtitleForeground are legacy aliases of header.title.color and header.subtitle.color. Both still work; the title/subtitle color wins when both are set.',
|
|
127
|
+
'titleForeground and subtitleForeground are legacy aliases of header.title.color and header.subtitle.color. Both still work; the title/subtitle color wins when both are set, and either alias still outranks the foreground derivation.',
|
|
128
|
+
},
|
|
129
|
+
history: {
|
|
130
|
+
description:
|
|
131
|
+
'Messages (conversation history) chrome and motion. railHeader styles the rail sidebar top strip, which runs beside the widget header in rail presentation; overlay styles the floating rail a collapsed overlay rail opens on hover; motion times the surface entering and leaving.',
|
|
132
|
+
properties:
|
|
133
|
+
'railHeader.background (defaults to the rail surface), railHeader.border (full border-bottom shorthand, default 0), railHeader.minHeight (defaults to components.header.minHeight, then 56px). Pin railHeader.minHeight and header.minHeight to the same value so both top strips read as one band. railHeader.title takes TextStyleTokens for the strip view title ("Messages"): color (defaults to the text color; the sidebar identity reads at full strength), fontFamily, fontSize (14px), fontWeight (600), lineHeight, letterSpacing. listHeading takes the same TextStyleTokens for the rail-only "Conversations" heading over the list block (14px/600 in the text color); groupHeading styles the muted sub-headers, both the date groups ("Today", "Yesterday") and rail nav section titles (rail 13px/500, muted text color). Every key of all three is pinned in the widget CSS, so host-page h2/h3 rules cannot restyle them. overlay.margin (8px, the gap from the trigger, the docked edge and the bottom), overlay.borderRadius (16px), overlay.shadow (0 12px 40px rgba(0, 0, 0, 0.25)), overlay.background (defaults to the rail surface). The floating rail keeps features.history.rail width and side, which are config, not tokens. motion.enterDurationMs (180) and motion.exitDurationMs (160) are bare millisecond numbers, 0 disables that leg; motion.enterEasing (cubic-bezier(0, 0, 0.2, 1)) and motion.exitEasing (cubic-bezier(0.4, 0, 1, 1)) take any CSS easing. Only the body animates, and prefers-reduced-motion always wins.',
|
|
134
|
+
},
|
|
135
|
+
tooltip: {
|
|
136
|
+
description:
|
|
137
|
+
'The portaled tooltip on icon controls, plus the muted shortcut hint chip after its label.',
|
|
138
|
+
properties:
|
|
139
|
+
'background (#111827), foreground (#ffffff), hintForeground (rgba(255, 255, 255, 0.55)), borderRadius (palette.radius.sm), fontSize (12px), padding (6px 12px), shadow, maxWidth (min(320px, calc(100vw - 16px))), arrow (boolean, default true; false drops the caret). Unset keys keep the built-in dark look.',
|
|
126
140
|
},
|
|
127
141
|
message: {
|
|
128
142
|
description: 'Chat message bubbles.',
|
|
@@ -211,12 +225,12 @@ export const THEME_TOKEN_DOCS = {
|
|
|
211
225
|
'backgroundColor, textColor, borderWidth, borderColor, paddingX, paddingY, iconText, iconName, size.',
|
|
212
226
|
},
|
|
213
227
|
closeButton: {
|
|
214
|
-
description: 'Close button (on launcher config).',
|
|
228
|
+
description: 'Close button (on launcher config). Unset closeButtonSize means theme.components.header.controlSize owns the box.',
|
|
215
229
|
properties:
|
|
216
230
|
'closeButtonSize, closeButtonColor, closeButtonBackgroundColor, closeButtonBorderWidth, closeButtonBorderColor, closeButtonBorderRadius.',
|
|
217
231
|
},
|
|
218
232
|
clearChat: {
|
|
219
|
-
description: 'Clear chat button (on launcher.clearChat config).',
|
|
233
|
+
description: 'Clear chat button (on launcher.clearChat config). Unset size means theme.components.header.controlSize owns the box.',
|
|
220
234
|
properties:
|
|
221
235
|
'enabled, iconColor, backgroundColor, borderWidth, borderColor, borderRadius, size.',
|
|
222
236
|
},
|