@runtypelabs/persona 3.5.2 → 3.7.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/index.cjs +46 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.global.js +70 -70
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +46 -46
- package/dist/index.js.map +1 -1
- package/dist/theme-editor.cjs +18015 -0
- package/dist/theme-editor.d.cts +3888 -0
- package/dist/theme-editor.d.ts +3888 -0
- package/dist/theme-editor.js +17909 -0
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.d.cts +33 -0
- package/dist/theme-reference.d.ts +33 -0
- package/dist/theme-reference.js +1 -1
- package/dist/widget.css +69 -25
- package/package.json +9 -7
- package/src/components/artifact-card.ts +1 -1
- package/src/components/composer-builder.ts +16 -29
- package/src/components/demo-carousel.ts +5 -5
- package/src/components/event-stream-view.test.ts +142 -0
- package/src/components/event-stream-view.ts +68 -29
- package/src/components/header-builder.ts +2 -2
- package/src/components/launcher.ts +9 -0
- package/src/components/message-bubble.ts +9 -3
- package/src/components/suggestions.ts +1 -1
- package/src/defaults.ts +24 -9
- package/src/scroll-to-bottom-defaults.test.ts +13 -0
- package/src/styles/widget.css +69 -25
- package/src/theme-editor/color-utils.ts +252 -0
- package/src/theme-editor/index.ts +131 -0
- package/src/theme-editor/presets.ts +144 -0
- package/src/theme-editor/preview-utils.ts +265 -0
- package/src/theme-editor/preview.ts +445 -0
- package/src/theme-editor/role-mappings.ts +343 -0
- package/src/theme-editor/sections.test.ts +43 -0
- package/src/theme-editor/sections.ts +994 -0
- package/src/theme-editor/state.ts +298 -0
- package/src/theme-editor/types.ts +177 -0
- package/src/theme-editor.ts +2 -0
- package/src/theme-reference.ts +8 -0
- package/src/types/theme.ts +11 -0
- package/src/types.ts +22 -0
- package/src/ui.scroll.test.ts +554 -0
- package/src/ui.ts +223 -133
- package/src/utils/auto-follow.test.ts +110 -0
- package/src/utils/auto-follow.ts +112 -0
- package/src/utils/plugins.ts +1 -1
- package/src/utils/theme.test.ts +44 -8
- package/src/utils/theme.ts +11 -11
- package/src/utils/tokens.ts +137 -41
- package/widget.css +0 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
createFollowStateController,
|
|
5
|
+
getScrollBottomOffset,
|
|
6
|
+
isElementNearBottom,
|
|
7
|
+
resolveFollowStateFromScroll,
|
|
8
|
+
resolveFollowStateFromWheel
|
|
9
|
+
} from "./auto-follow";
|
|
10
|
+
|
|
11
|
+
describe("auto-follow utilities", () => {
|
|
12
|
+
it("tracks pause and resume state", () => {
|
|
13
|
+
const state = createFollowStateController();
|
|
14
|
+
|
|
15
|
+
expect(state.isFollowing()).toBe(true);
|
|
16
|
+
expect(state.pause()).toBe(true);
|
|
17
|
+
expect(state.isFollowing()).toBe(false);
|
|
18
|
+
expect(state.pause()).toBe(false);
|
|
19
|
+
expect(state.resume()).toBe(true);
|
|
20
|
+
expect(state.isFollowing()).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("computes bottom offset and near-bottom status", () => {
|
|
24
|
+
const element = {
|
|
25
|
+
scrollTop: 590,
|
|
26
|
+
scrollHeight: 1000,
|
|
27
|
+
clientHeight: 400
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
expect(getScrollBottomOffset(element)).toBe(600);
|
|
31
|
+
expect(isElementNearBottom(element, 10)).toBe(true);
|
|
32
|
+
expect(isElementNearBottom({ ...element, scrollTop: 560 }, 10)).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("pauses transcript-style auto-follow on upward scroll immediately", () => {
|
|
36
|
+
const result = resolveFollowStateFromScroll({
|
|
37
|
+
following: true,
|
|
38
|
+
currentScrollTop: 597,
|
|
39
|
+
lastScrollTop: 600,
|
|
40
|
+
nearBottom: true,
|
|
41
|
+
userScrollThreshold: 1,
|
|
42
|
+
pauseOnUpwardScroll: true,
|
|
43
|
+
pauseWhenAwayFromBottom: false
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
expect(result.action).toBe("pause");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("resumes event-log-style auto-follow only when scrolling down near bottom", () => {
|
|
50
|
+
const stayPaused = resolveFollowStateFromScroll({
|
|
51
|
+
following: false,
|
|
52
|
+
currentScrollTop: 550,
|
|
53
|
+
lastScrollTop: 560,
|
|
54
|
+
nearBottom: true,
|
|
55
|
+
userScrollThreshold: 1,
|
|
56
|
+
resumeRequiresDownwardScroll: true
|
|
57
|
+
});
|
|
58
|
+
const resume = resolveFollowStateFromScroll({
|
|
59
|
+
following: false,
|
|
60
|
+
currentScrollTop: 590,
|
|
61
|
+
lastScrollTop: 550,
|
|
62
|
+
nearBottom: true,
|
|
63
|
+
userScrollThreshold: 1,
|
|
64
|
+
resumeRequiresDownwardScroll: true
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
expect(stayPaused.action).toBe("none");
|
|
68
|
+
expect(resume.action).toBe("resume");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("keeps transcript-style auto-follow paused near the bottom until scrolling down", () => {
|
|
72
|
+
const stayPaused = resolveFollowStateFromScroll({
|
|
73
|
+
following: false,
|
|
74
|
+
currentScrollTop: 597,
|
|
75
|
+
lastScrollTop: 600,
|
|
76
|
+
nearBottom: true,
|
|
77
|
+
userScrollThreshold: 1,
|
|
78
|
+
resumeRequiresDownwardScroll: true
|
|
79
|
+
});
|
|
80
|
+
const resume = resolveFollowStateFromScroll({
|
|
81
|
+
following: false,
|
|
82
|
+
currentScrollTop: 599,
|
|
83
|
+
lastScrollTop: 597,
|
|
84
|
+
nearBottom: true,
|
|
85
|
+
userScrollThreshold: 1,
|
|
86
|
+
resumeRequiresDownwardScroll: true
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
expect(stayPaused.action).toBe("none");
|
|
90
|
+
expect(resume.action).toBe("resume");
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("resolves wheel intent for pause and resume", () => {
|
|
94
|
+
expect(
|
|
95
|
+
resolveFollowStateFromWheel({
|
|
96
|
+
following: true,
|
|
97
|
+
deltaY: -12
|
|
98
|
+
})
|
|
99
|
+
).toBe("pause");
|
|
100
|
+
|
|
101
|
+
expect(
|
|
102
|
+
resolveFollowStateFromWheel({
|
|
103
|
+
following: false,
|
|
104
|
+
deltaY: 12,
|
|
105
|
+
nearBottom: true,
|
|
106
|
+
resumeWhenNearBottom: true
|
|
107
|
+
})
|
|
108
|
+
).toBe("resume");
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export type FollowStateAction = "none" | "pause" | "resume";
|
|
2
|
+
|
|
3
|
+
export type FollowStateController = {
|
|
4
|
+
isFollowing: () => boolean;
|
|
5
|
+
pause: () => boolean;
|
|
6
|
+
resume: () => boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type FollowStateScrollInput = {
|
|
10
|
+
following: boolean;
|
|
11
|
+
currentScrollTop: number;
|
|
12
|
+
lastScrollTop: number;
|
|
13
|
+
nearBottom: boolean;
|
|
14
|
+
userScrollThreshold: number;
|
|
15
|
+
isAutoScrolling?: boolean;
|
|
16
|
+
pauseOnUpwardScroll?: boolean;
|
|
17
|
+
pauseWhenAwayFromBottom?: boolean;
|
|
18
|
+
resumeRequiresDownwardScroll?: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type FollowStateWheelInput = {
|
|
22
|
+
following: boolean;
|
|
23
|
+
deltaY: number;
|
|
24
|
+
nearBottom?: boolean;
|
|
25
|
+
resumeWhenNearBottom?: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export function createFollowStateController(initiallyFollowing = true): FollowStateController {
|
|
29
|
+
let following = initiallyFollowing;
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
isFollowing: () => following,
|
|
33
|
+
pause: () => {
|
|
34
|
+
if (!following) return false;
|
|
35
|
+
following = false;
|
|
36
|
+
return true;
|
|
37
|
+
},
|
|
38
|
+
resume: () => {
|
|
39
|
+
if (following) return false;
|
|
40
|
+
following = true;
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function getScrollBottomOffset(element: Pick<HTMLElement, "scrollHeight" | "clientHeight">): number {
|
|
47
|
+
return Math.max(0, element.scrollHeight - element.clientHeight);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function isElementNearBottom(
|
|
51
|
+
element: Pick<HTMLElement, "scrollTop" | "scrollHeight" | "clientHeight">,
|
|
52
|
+
threshold: number
|
|
53
|
+
): boolean {
|
|
54
|
+
return getScrollBottomOffset(element) - element.scrollTop <= threshold;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function resolveFollowStateFromScroll(
|
|
58
|
+
input: FollowStateScrollInput
|
|
59
|
+
): { action: FollowStateAction; delta: number; nextLastScrollTop: number } {
|
|
60
|
+
const {
|
|
61
|
+
following,
|
|
62
|
+
currentScrollTop,
|
|
63
|
+
lastScrollTop,
|
|
64
|
+
nearBottom,
|
|
65
|
+
userScrollThreshold,
|
|
66
|
+
isAutoScrolling = false,
|
|
67
|
+
pauseOnUpwardScroll = false,
|
|
68
|
+
pauseWhenAwayFromBottom = true,
|
|
69
|
+
resumeRequiresDownwardScroll = false
|
|
70
|
+
} = input;
|
|
71
|
+
|
|
72
|
+
const delta = currentScrollTop - lastScrollTop;
|
|
73
|
+
|
|
74
|
+
if (isAutoScrolling || Math.abs(delta) < userScrollThreshold) {
|
|
75
|
+
return { action: "none", delta, nextLastScrollTop: currentScrollTop };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!following && nearBottom && (!resumeRequiresDownwardScroll || delta > 0)) {
|
|
79
|
+
return { action: "resume", delta, nextLastScrollTop: currentScrollTop };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (following && pauseOnUpwardScroll && delta < 0) {
|
|
83
|
+
return { action: "pause", delta, nextLastScrollTop: currentScrollTop };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (following && pauseWhenAwayFromBottom && !nearBottom) {
|
|
87
|
+
return { action: "pause", delta, nextLastScrollTop: currentScrollTop };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { action: "none", delta, nextLastScrollTop: currentScrollTop };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function resolveFollowStateFromWheel(
|
|
94
|
+
input: FollowStateWheelInput
|
|
95
|
+
): FollowStateAction {
|
|
96
|
+
const {
|
|
97
|
+
following,
|
|
98
|
+
deltaY,
|
|
99
|
+
nearBottom = false,
|
|
100
|
+
resumeWhenNearBottom = false
|
|
101
|
+
} = input;
|
|
102
|
+
|
|
103
|
+
if (following && deltaY < 0) {
|
|
104
|
+
return "pause";
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!following && resumeWhenNearBottom && deltaY > 0 && nearBottom) {
|
|
108
|
+
return "resume";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return "none";
|
|
112
|
+
}
|
package/src/utils/plugins.ts
CHANGED
|
@@ -22,7 +22,7 @@ export function accessibilityPlugin(): PersonaThemePlugin {
|
|
|
22
22
|
},
|
|
23
23
|
cssVariables: {
|
|
24
24
|
'--persona-accessibility-focus-ring':
|
|
25
|
-
'0 0 0 2px var(--persona-semantic-colors-surface, #fff), 0 0 0 4px var(--persona-semantic-colors-interactive-focus, #
|
|
25
|
+
'0 0 0 2px var(--persona-semantic-colors-surface, #fff), 0 0 0 4px var(--persona-semantic-colors-interactive-focus, #0f0f0f)',
|
|
26
26
|
},
|
|
27
27
|
};
|
|
28
28
|
}
|
package/src/utils/theme.test.ts
CHANGED
|
@@ -139,15 +139,16 @@ describe('theme utils', () => {
|
|
|
139
139
|
expect(cssVars['--persona-md-prose-font-family']).toBe('Georgia, serif');
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
-
it('maps header chrome tokens to dedicated CSS variables with
|
|
142
|
+
it('maps header chrome tokens to dedicated CSS variables with palette refs', () => {
|
|
143
143
|
const theme = createTheme();
|
|
144
144
|
const cssVars = themeToCssVariables(theme);
|
|
145
145
|
|
|
146
|
-
|
|
147
|
-
expect(cssVars['--persona-header-icon-
|
|
148
|
-
expect(cssVars['--persona-header-
|
|
149
|
-
expect(cssVars['--persona-header-
|
|
150
|
-
expect(cssVars['--persona-header-
|
|
146
|
+
// Default header uses solid primary role: icon-bg=primary.600, icon-fg=primary.50, etc.
|
|
147
|
+
expect(cssVars['--persona-header-icon-bg']).toBe('#0f0f0f'); // primary.600
|
|
148
|
+
expect(cssVars['--persona-header-icon-fg']).toBe('#ffffff'); // primary.50
|
|
149
|
+
expect(cssVars['--persona-header-title-fg']).toBe('#ffffff'); // primary.50
|
|
150
|
+
expect(cssVars['--persona-header-subtitle-fg']).toBe('#d4d4d4'); // primary.200
|
|
151
|
+
expect(cssVars['--persona-header-action-icon-fg']).toBe('#d4d4d4'); // primary.200
|
|
151
152
|
|
|
152
153
|
const custom = createTheme({
|
|
153
154
|
components: {
|
|
@@ -172,8 +173,9 @@ describe('theme utils', () => {
|
|
|
172
173
|
const theme = createTheme();
|
|
173
174
|
const cssVars = themeToCssVariables(theme);
|
|
174
175
|
|
|
175
|
-
|
|
176
|
-
expect(cssVars['--persona-artifact-
|
|
176
|
+
// container defaults to gray.50 now (soft gray surfaces role)
|
|
177
|
+
expect(cssVars['--persona-components-artifact-pane-background']).toBe('#f9fafb');
|
|
178
|
+
expect(cssVars['--persona-artifact-toolbar-bg']).toBe('#f9fafb');
|
|
177
179
|
|
|
178
180
|
const surfacePane = createTheme({
|
|
179
181
|
components: {
|
|
@@ -216,6 +218,40 @@ describe('theme utils', () => {
|
|
|
216
218
|
expect(cssVars['--persona-composer-shadow']).toBe('none');
|
|
217
219
|
});
|
|
218
220
|
|
|
221
|
+
it('maps scroll-to-bottom component tokens to dedicated CSS variables', () => {
|
|
222
|
+
const theme = createTheme({
|
|
223
|
+
components: {
|
|
224
|
+
scrollToBottom: {
|
|
225
|
+
background: 'palette.colors.accent.500',
|
|
226
|
+
foreground: 'palette.colors.gray.50',
|
|
227
|
+
border: 'palette.colors.gray.900',
|
|
228
|
+
size: '40px',
|
|
229
|
+
borderRadius: 'palette.radius.full',
|
|
230
|
+
shadow: 'palette.shadows.md',
|
|
231
|
+
padding: '0.5rem 0.875rem',
|
|
232
|
+
gap: '0.5rem',
|
|
233
|
+
fontSize: '0.875rem',
|
|
234
|
+
iconSize: '14px',
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
} as any);
|
|
238
|
+
|
|
239
|
+
const cssVars = themeToCssVariables(theme);
|
|
240
|
+
|
|
241
|
+
expect(cssVars['--persona-scroll-to-bottom-bg']).toBe('#06b6d4');
|
|
242
|
+
expect(cssVars['--persona-scroll-to-bottom-fg']).toBe('#f9fafb');
|
|
243
|
+
expect(cssVars['--persona-scroll-to-bottom-border']).toBe('#111827');
|
|
244
|
+
expect(cssVars['--persona-scroll-to-bottom-size']).toBe('40px');
|
|
245
|
+
expect(cssVars['--persona-scroll-to-bottom-radius']).toBe('9999px');
|
|
246
|
+
expect(cssVars['--persona-scroll-to-bottom-shadow']).toBe(
|
|
247
|
+
'0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)'
|
|
248
|
+
);
|
|
249
|
+
expect(cssVars['--persona-scroll-to-bottom-padding']).toBe('0.5rem 0.875rem');
|
|
250
|
+
expect(cssVars['--persona-scroll-to-bottom-gap']).toBe('0.5rem');
|
|
251
|
+
expect(cssVars['--persona-scroll-to-bottom-font-size']).toBe('0.875rem');
|
|
252
|
+
expect(cssVars['--persona-scroll-to-bottom-icon-size']).toBe('14px');
|
|
253
|
+
});
|
|
254
|
+
|
|
219
255
|
it('lets config.toolCall.shadow override theme tool bubble shadow on the root element', () => {
|
|
220
256
|
const el = document.createElement('div');
|
|
221
257
|
applyThemeVariables(el, {
|
package/src/utils/theme.ts
CHANGED
|
@@ -16,17 +16,17 @@ type WidgetConfig = PersonaWidgetConfig | AgentWidgetConfig;
|
|
|
16
16
|
const DARK_PALETTE = {
|
|
17
17
|
colors: {
|
|
18
18
|
primary: {
|
|
19
|
-
50: '#
|
|
20
|
-
100: '#
|
|
21
|
-
200: '#
|
|
22
|
-
300: '#
|
|
23
|
-
400: '#
|
|
24
|
-
500: '#
|
|
25
|
-
600: '#
|
|
26
|
-
700: '#
|
|
27
|
-
800: '#
|
|
28
|
-
900: '#
|
|
29
|
-
950: '#
|
|
19
|
+
50: '#ffffff',
|
|
20
|
+
100: '#f5f5f5',
|
|
21
|
+
200: '#d4d4d4',
|
|
22
|
+
300: '#a3a3a3',
|
|
23
|
+
400: '#737373',
|
|
24
|
+
500: '#171717',
|
|
25
|
+
600: '#0f0f0f',
|
|
26
|
+
700: '#0a0a0a',
|
|
27
|
+
800: '#050505',
|
|
28
|
+
900: '#030303',
|
|
29
|
+
950: '#000000',
|
|
30
30
|
},
|
|
31
31
|
secondary: {
|
|
32
32
|
50: '#f5f3ff',
|
package/src/utils/tokens.ts
CHANGED
|
@@ -12,17 +12,17 @@ import type {
|
|
|
12
12
|
export const DEFAULT_PALETTE = {
|
|
13
13
|
colors: {
|
|
14
14
|
primary: {
|
|
15
|
-
50: '#
|
|
16
|
-
100: '#
|
|
17
|
-
200: '#
|
|
18
|
-
300: '#
|
|
19
|
-
400: '#
|
|
20
|
-
500: '#
|
|
21
|
-
600: '#
|
|
22
|
-
700: '#
|
|
23
|
-
800: '#
|
|
24
|
-
900: '#
|
|
25
|
-
950: '#
|
|
15
|
+
50: '#ffffff',
|
|
16
|
+
100: '#f5f5f5',
|
|
17
|
+
200: '#d4d4d4',
|
|
18
|
+
300: '#a3a3a3',
|
|
19
|
+
400: '#737373',
|
|
20
|
+
500: '#171717',
|
|
21
|
+
600: '#0f0f0f',
|
|
22
|
+
700: '#0a0a0a',
|
|
23
|
+
800: '#050505',
|
|
24
|
+
900: '#030303',
|
|
25
|
+
950: '#000000',
|
|
26
26
|
},
|
|
27
27
|
secondary: {
|
|
28
28
|
50: '#f5f3ff',
|
|
@@ -99,6 +99,19 @@ export const DEFAULT_PALETTE = {
|
|
|
99
99
|
800: '#991b1b',
|
|
100
100
|
900: '#7f1d1d',
|
|
101
101
|
},
|
|
102
|
+
info: {
|
|
103
|
+
50: '#eff6ff',
|
|
104
|
+
100: '#dbeafe',
|
|
105
|
+
200: '#bfdbfe',
|
|
106
|
+
300: '#93c5fd',
|
|
107
|
+
400: '#60a5fa',
|
|
108
|
+
500: '#3b82f6',
|
|
109
|
+
600: '#2563eb',
|
|
110
|
+
700: '#1d4ed8',
|
|
111
|
+
800: '#1e40af',
|
|
112
|
+
900: '#1e3a8a',
|
|
113
|
+
950: '#172554',
|
|
114
|
+
},
|
|
102
115
|
},
|
|
103
116
|
spacing: {
|
|
104
117
|
0: '0px',
|
|
@@ -176,28 +189,33 @@ export const DEFAULT_PALETTE = {
|
|
|
176
189
|
export const DEFAULT_SEMANTIC: SemanticTokens = {
|
|
177
190
|
colors: {
|
|
178
191
|
primary: 'palette.colors.primary.500',
|
|
179
|
-
secondary: 'palette.colors.
|
|
192
|
+
secondary: 'palette.colors.secondary.500',
|
|
193
|
+
// Links/Focus role — solid primary
|
|
180
194
|
accent: 'palette.colors.primary.600',
|
|
195
|
+
// Surfaces role — soft gray
|
|
181
196
|
surface: 'palette.colors.gray.50',
|
|
182
197
|
background: 'palette.colors.gray.50',
|
|
183
|
-
container: 'palette.colors.gray.
|
|
198
|
+
container: 'palette.colors.gray.50',
|
|
184
199
|
text: 'palette.colors.gray.900',
|
|
185
200
|
textMuted: 'palette.colors.gray.500',
|
|
186
201
|
textInverse: 'palette.colors.gray.50',
|
|
202
|
+
// Borders role — soft gray
|
|
187
203
|
border: 'palette.colors.gray.200',
|
|
188
204
|
divider: 'palette.colors.gray.200',
|
|
189
205
|
interactive: {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
206
|
+
// Primary Actions role — solid primary
|
|
207
|
+
default: 'palette.colors.primary.600',
|
|
208
|
+
hover: 'palette.colors.primary.700',
|
|
209
|
+
// Links/Focus role — solid primary
|
|
210
|
+
focus: 'palette.colors.primary.600',
|
|
211
|
+
active: 'palette.colors.primary.600',
|
|
194
212
|
disabled: 'palette.colors.gray.300',
|
|
195
213
|
},
|
|
196
214
|
feedback: {
|
|
197
215
|
success: 'palette.colors.success.500',
|
|
198
216
|
warning: 'palette.colors.warning.500',
|
|
199
217
|
error: 'palette.colors.error.500',
|
|
200
|
-
info: 'palette.colors.
|
|
218
|
+
info: 'palette.colors.info.500',
|
|
201
219
|
},
|
|
202
220
|
},
|
|
203
221
|
spacing: {
|
|
@@ -219,14 +237,15 @@ export const DEFAULT_SEMANTIC: SemanticTokens = {
|
|
|
219
237
|
export const DEFAULT_COMPONENTS: ComponentTokens = {
|
|
220
238
|
button: {
|
|
221
239
|
primary: {
|
|
222
|
-
|
|
223
|
-
|
|
240
|
+
// Primary Actions role — solid primary
|
|
241
|
+
background: 'palette.colors.primary.500',
|
|
242
|
+
foreground: 'palette.colors.primary.50',
|
|
224
243
|
borderRadius: 'palette.radius.lg',
|
|
225
244
|
padding: 'semantic.spacing.md',
|
|
226
245
|
},
|
|
227
246
|
secondary: {
|
|
228
247
|
background: 'semantic.colors.surface',
|
|
229
|
-
foreground: 'semantic.colors.
|
|
248
|
+
foreground: 'semantic.colors.secondary',
|
|
230
249
|
borderRadius: 'palette.radius.lg',
|
|
231
250
|
padding: 'semantic.spacing.md',
|
|
232
251
|
},
|
|
@@ -238,16 +257,20 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
|
|
|
238
257
|
},
|
|
239
258
|
},
|
|
240
259
|
input: {
|
|
241
|
-
|
|
242
|
-
|
|
260
|
+
// Input role — soft gray
|
|
261
|
+
background: 'palette.colors.gray.50',
|
|
262
|
+
placeholder: 'palette.colors.gray.400',
|
|
243
263
|
borderRadius: 'palette.radius.lg',
|
|
244
264
|
padding: 'semantic.spacing.md',
|
|
245
265
|
focus: {
|
|
246
|
-
border: '
|
|
247
|
-
ring: '
|
|
266
|
+
border: 'palette.colors.gray.400',
|
|
267
|
+
ring: 'palette.colors.gray.400',
|
|
248
268
|
},
|
|
249
269
|
},
|
|
250
270
|
launcher: {
|
|
271
|
+
background: 'palette.colors.primary.500',
|
|
272
|
+
foreground: 'palette.colors.primary.50',
|
|
273
|
+
border: 'palette.colors.gray.200',
|
|
251
274
|
size: '60px',
|
|
252
275
|
iconSize: '28px',
|
|
253
276
|
borderRadius: 'palette.radius.full',
|
|
@@ -262,28 +285,31 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
|
|
|
262
285
|
shadow: 'palette.shadows.xl',
|
|
263
286
|
},
|
|
264
287
|
header: {
|
|
265
|
-
|
|
266
|
-
|
|
288
|
+
// Header role — solid primary
|
|
289
|
+
background: 'palette.colors.primary.500',
|
|
290
|
+
border: 'palette.colors.primary.600',
|
|
267
291
|
borderRadius: 'palette.radius.xl palette.radius.xl 0 0',
|
|
268
292
|
padding: 'semantic.spacing.md',
|
|
269
|
-
iconBackground: '
|
|
270
|
-
iconForeground: '
|
|
271
|
-
titleForeground: '
|
|
272
|
-
subtitleForeground: '
|
|
273
|
-
actionIconForeground: '
|
|
293
|
+
iconBackground: 'palette.colors.primary.600',
|
|
294
|
+
iconForeground: 'palette.colors.primary.50',
|
|
295
|
+
titleForeground: 'palette.colors.primary.50',
|
|
296
|
+
subtitleForeground: 'palette.colors.primary.200',
|
|
297
|
+
actionIconForeground: 'palette.colors.primary.200',
|
|
274
298
|
},
|
|
275
299
|
message: {
|
|
276
300
|
user: {
|
|
277
|
-
|
|
278
|
-
|
|
301
|
+
// User Messages role — solid primary
|
|
302
|
+
background: 'palette.colors.primary.500',
|
|
303
|
+
text: 'palette.colors.primary.50',
|
|
279
304
|
borderRadius: 'palette.radius.lg',
|
|
280
305
|
shadow: 'palette.shadows.sm',
|
|
281
306
|
},
|
|
282
307
|
assistant: {
|
|
283
|
-
|
|
284
|
-
|
|
308
|
+
// Assistant Messages role — soft gray
|
|
309
|
+
background: 'palette.colors.gray.50',
|
|
310
|
+
text: 'palette.colors.gray.900',
|
|
285
311
|
borderRadius: 'palette.radius.lg',
|
|
286
|
-
border: '
|
|
312
|
+
border: 'palette.colors.gray.200',
|
|
287
313
|
shadow: 'palette.shadows.sm',
|
|
288
314
|
},
|
|
289
315
|
},
|
|
@@ -298,11 +324,12 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
|
|
|
298
324
|
},
|
|
299
325
|
markdown: {
|
|
300
326
|
inlineCode: {
|
|
301
|
-
background: '
|
|
302
|
-
foreground: '
|
|
327
|
+
background: 'palette.colors.gray.50',
|
|
328
|
+
foreground: 'palette.colors.gray.900',
|
|
303
329
|
},
|
|
304
330
|
link: {
|
|
305
|
-
|
|
331
|
+
// Links/Focus role — solid primary
|
|
332
|
+
foreground: 'palette.colors.primary.600',
|
|
306
333
|
},
|
|
307
334
|
prose: {
|
|
308
335
|
fontFamily: 'inherit',
|
|
@@ -347,6 +374,18 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
|
|
|
347
374
|
border: 'palette.colors.gray.200',
|
|
348
375
|
},
|
|
349
376
|
},
|
|
377
|
+
scrollToBottom: {
|
|
378
|
+
background: 'components.button.primary.background',
|
|
379
|
+
foreground: 'components.button.primary.foreground',
|
|
380
|
+
border: 'semantic.colors.primary',
|
|
381
|
+
size: '40px',
|
|
382
|
+
borderRadius: 'palette.radius.full',
|
|
383
|
+
shadow: 'palette.shadows.sm',
|
|
384
|
+
padding: '0.5rem 0.875rem',
|
|
385
|
+
gap: '0.5rem',
|
|
386
|
+
fontSize: '0.875rem',
|
|
387
|
+
iconSize: '14px',
|
|
388
|
+
},
|
|
350
389
|
artifact: {
|
|
351
390
|
pane: {
|
|
352
391
|
background: 'semantic.colors.container',
|
|
@@ -629,10 +668,26 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
629
668
|
cssVars['--persona-radius-md'] = cssVars['--persona-palette-radius-md'] ?? '0.375rem';
|
|
630
669
|
cssVars['--persona-radius-lg'] = cssVars['--persona-palette-radius-lg'] ?? '0.5rem';
|
|
631
670
|
cssVars['--persona-radius-xl'] = cssVars['--persona-palette-radius-xl'] ?? '0.75rem';
|
|
671
|
+
cssVars['--persona-radius-full'] = cssVars['--persona-palette-radius-full'] ?? '9999px';
|
|
632
672
|
cssVars['--persona-launcher-radius'] =
|
|
633
673
|
cssVars['--persona-components-launcher-borderRadius'] ??
|
|
634
674
|
cssVars['--persona-palette-radius-full'] ??
|
|
635
675
|
'9999px';
|
|
676
|
+
cssVars['--persona-launcher-bg'] =
|
|
677
|
+
cssVars['--persona-components-launcher-background'] ??
|
|
678
|
+
cssVars['--persona-primary'];
|
|
679
|
+
cssVars['--persona-launcher-fg'] =
|
|
680
|
+
cssVars['--persona-components-launcher-foreground'] ??
|
|
681
|
+
cssVars['--persona-text-inverse'];
|
|
682
|
+
cssVars['--persona-launcher-border'] =
|
|
683
|
+
cssVars['--persona-components-launcher-border'] ??
|
|
684
|
+
cssVars['--persona-border'];
|
|
685
|
+
cssVars['--persona-button-primary-bg'] =
|
|
686
|
+
cssVars['--persona-components-button-primary-background'] ??
|
|
687
|
+
cssVars['--persona-primary'];
|
|
688
|
+
cssVars['--persona-button-primary-fg'] =
|
|
689
|
+
cssVars['--persona-components-button-primary-foreground'] ??
|
|
690
|
+
cssVars['--persona-text-inverse'];
|
|
636
691
|
cssVars['--persona-button-radius'] =
|
|
637
692
|
cssVars['--persona-components-button-primary-borderRadius'] ??
|
|
638
693
|
cssVars['--persona-palette-radius-full'] ??
|
|
@@ -681,6 +736,11 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
681
736
|
if (headerTokens?.shadow) cssVars['--persona-header-shadow'] = headerTokens.shadow;
|
|
682
737
|
if (headerTokens?.borderBottom) cssVars['--persona-header-border-bottom'] = headerTokens.borderBottom;
|
|
683
738
|
|
|
739
|
+
cssVars['--persona-input-background'] =
|
|
740
|
+
cssVars['--persona-components-input-background'] ?? cssVars['--persona-surface'];
|
|
741
|
+
cssVars['--persona-input-placeholder'] =
|
|
742
|
+
cssVars['--persona-components-input-placeholder'] ?? cssVars['--persona-text-muted'];
|
|
743
|
+
|
|
684
744
|
cssVars['--persona-message-user-bg'] =
|
|
685
745
|
cssVars['--persona-components-message-user-background'] ?? cssVars['--persona-accent'];
|
|
686
746
|
cssVars['--persona-message-user-text'] =
|
|
@@ -695,6 +755,42 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
695
755
|
cssVars['--persona-components-message-assistant-border'] ?? cssVars['--persona-border'];
|
|
696
756
|
cssVars['--persona-message-assistant-shadow'] =
|
|
697
757
|
cssVars['--persona-components-message-assistant-shadow'] ?? '0 1px 2px 0 rgb(0 0 0 / 0.05)';
|
|
758
|
+
cssVars['--persona-scroll-to-bottom-bg'] =
|
|
759
|
+
cssVars['--persona-components-scrollToBottom-background'] ??
|
|
760
|
+
cssVars['--persona-button-primary-bg'] ??
|
|
761
|
+
cssVars['--persona-accent'];
|
|
762
|
+
cssVars['--persona-scroll-to-bottom-fg'] =
|
|
763
|
+
cssVars['--persona-components-scrollToBottom-foreground'] ??
|
|
764
|
+
cssVars['--persona-button-primary-fg'] ??
|
|
765
|
+
cssVars['--persona-text-inverse'];
|
|
766
|
+
cssVars['--persona-scroll-to-bottom-border'] =
|
|
767
|
+
cssVars['--persona-components-scrollToBottom-border'] ??
|
|
768
|
+
cssVars['--persona-primary'];
|
|
769
|
+
cssVars['--persona-scroll-to-bottom-size'] =
|
|
770
|
+
cssVars['--persona-components-scrollToBottom-size'] ??
|
|
771
|
+
'40px';
|
|
772
|
+
cssVars['--persona-scroll-to-bottom-radius'] =
|
|
773
|
+
cssVars['--persona-components-scrollToBottom-borderRadius'] ??
|
|
774
|
+
cssVars['--persona-button-radius'] ??
|
|
775
|
+
cssVars['--persona-radius-full'] ??
|
|
776
|
+
'9999px';
|
|
777
|
+
cssVars['--persona-scroll-to-bottom-shadow'] =
|
|
778
|
+
cssVars['--persona-components-scrollToBottom-shadow'] ??
|
|
779
|
+
cssVars['--persona-palette-shadows-sm'] ??
|
|
780
|
+
'0 1px 2px 0 rgb(0 0 0 / 0.05)';
|
|
781
|
+
cssVars['--persona-scroll-to-bottom-padding'] =
|
|
782
|
+
cssVars['--persona-components-scrollToBottom-padding'] ??
|
|
783
|
+
'0.5rem 0.875rem';
|
|
784
|
+
cssVars['--persona-scroll-to-bottom-gap'] =
|
|
785
|
+
cssVars['--persona-components-scrollToBottom-gap'] ??
|
|
786
|
+
'0.5rem';
|
|
787
|
+
cssVars['--persona-scroll-to-bottom-font-size'] =
|
|
788
|
+
cssVars['--persona-components-scrollToBottom-fontSize'] ??
|
|
789
|
+
cssVars['--persona-palette-typography-fontSize-sm'] ??
|
|
790
|
+
'0.875rem';
|
|
791
|
+
cssVars['--persona-scroll-to-bottom-icon-size'] =
|
|
792
|
+
cssVars['--persona-components-scrollToBottom-iconSize'] ??
|
|
793
|
+
'14px';
|
|
698
794
|
|
|
699
795
|
cssVars['--persona-tool-bubble-shadow'] =
|
|
700
796
|
cssVars['--persona-components-toolBubble-shadow'] ?? '0 5px 15px rgba(15, 23, 42, 0.08)';
|
|
@@ -711,7 +807,7 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
711
807
|
cssVars['--persona-md-link-color'] =
|
|
712
808
|
cssVars['--persona-components-markdown-link-foreground'] ??
|
|
713
809
|
cssVars['--persona-accent'] ??
|
|
714
|
-
'#
|
|
810
|
+
'#0f0f0f';
|
|
715
811
|
|
|
716
812
|
const mdH1Size = cssVars['--persona-components-markdown-heading-h1-fontSize'];
|
|
717
813
|
if (mdH1Size) cssVars['--persona-md-h1-size'] = mdH1Size;
|
package/widget.css
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@import "./src/widget.css";
|