@helpai/elements 1.8.0 → 1.10.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/README.md +34 -12
- package/configurator.mjs +1 -1
- package/docs/README.md +183 -0
- package/docs/analytics.md +551 -0
- package/docs/api-reference.md +637 -0
- package/docs/browser-support.md +302 -0
- package/docs/configuration.md +1014 -0
- package/docs/events-and-hooks.md +483 -0
- package/docs/faq.md +435 -0
- package/docs/frameworks.md +643 -0
- package/docs/installation.md +626 -0
- package/docs/options.md +323 -0
- package/docs/quickstart.md +229 -0
- package/docs/recipes.md +725 -0
- package/docs/security-privacy.md +636 -0
- package/docs/theming.md +570 -0
- package/docs/troubleshooting.md +523 -0
- package/elements-web-component.esm.js +39 -39
- package/elements-web-component.esm.js.map +4 -4
- package/elements.cjs.js +39 -39
- package/elements.cjs.js.map +4 -4
- package/elements.esm.js +39 -39
- package/elements.esm.js.map +4 -4
- package/elements.js +39 -39
- package/elements.js.map +4 -4
- package/index.d.ts +107 -3
- package/index.mjs +13 -13
- package/jsx-react.d.ts +15 -0
- package/jsx-svelte.d.ts +14 -0
- package/jsx-vue.d.ts +14 -0
- package/llms-full.txt +7954 -0
- package/llms.txt +37 -0
- package/loader.js +3 -3
- package/loader.min.js +1 -1
- package/package.json +36 -1
- package/react.d.ts +3575 -0
- package/react.mjs +62 -0
- package/schema.d.ts +56 -0
- package/schema.json +24 -2
- package/schema.mjs +1 -1
- package/web-component.d.ts +1583 -17
- package/web-component.mjs +14 -14
package/docs/theming.md
ADDED
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
# Theming & customization
|
|
2
|
+
|
|
3
|
+
Make the widget match your brand — colors, shapes, typography, and
|
|
4
|
+
launcher style.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## TL;DR
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
init({
|
|
12
|
+
publicKey: 'agent_pk_...',
|
|
13
|
+
aiAgentDeploymentId: '01900000-0000-7000-8000-000000000000',
|
|
14
|
+
theme: {
|
|
15
|
+
accent: '#ff3e00', // your brand primary
|
|
16
|
+
accentText: '#ffffff', // on-accent text
|
|
17
|
+
radius: '12px', // corner rounding
|
|
18
|
+
fontFamily: 'Inter, system-ui, sans-serif',
|
|
19
|
+
},
|
|
20
|
+
launcher: {
|
|
21
|
+
variant: 'pill', // circle / pill / bar / minimal
|
|
22
|
+
label: 'Ask us',
|
|
23
|
+
icon: 'spark', // chat / message / bubbles / spark / wand / bot / help / lifebuoy / headset / search / sparkles / concierge / wave
|
|
24
|
+
},
|
|
25
|
+
composer: {
|
|
26
|
+
sendButton: { shape: 'pill', variant: 'outline' },
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Rest of this page goes deep on each knob.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Theme modes
|
|
36
|
+
|
|
37
|
+
Four modes:
|
|
38
|
+
|
|
39
|
+
- **`"auto"`** — follows the visitor's OS preference (`prefers-color-scheme`).
|
|
40
|
+
- **`"light"`** — force light mode.
|
|
41
|
+
- **`"dark"`** — force dark mode.
|
|
42
|
+
- **`"host"`** — follows your page's own light/dark and flips with your site's toggle. The widget reads, in order, a
|
|
43
|
+
`dark` / `light` class on `<html>` or `<body>`, a `data-theme`, `data-color-scheme`, `data-mode` or `data-bs-theme`
|
|
44
|
+
attribute there, then the page's `color-scheme`, then the OS.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
init({ theme: 'auto' }); // default
|
|
48
|
+
init({ theme: 'light' });
|
|
49
|
+
init({ theme: 'dark' });
|
|
50
|
+
init({ theme: 'host' }); // or <web-ai-chat theme="host">, data-theme="host" on the script tag
|
|
51
|
+
init({ theme: { mode: 'host', accent: '#635146' } }); // a mode beside token overrides
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
A page that sets only the mode keeps the deployment's token overrides from the dashboard (its brand accent) — so
|
|
55
|
+
`<web-ai-chat theme="host">` follows your site without losing the brand colours.
|
|
56
|
+
|
|
57
|
+
### Runtime switching
|
|
58
|
+
|
|
59
|
+
End users can flip the theme through the `theme` row in the header's ⋯ menu.
|
|
60
|
+
Their choice persists across conversations and syncs
|
|
61
|
+
across devices.
|
|
62
|
+
|
|
63
|
+
If you don't want a runtime picker, remove the action:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
init({
|
|
67
|
+
header: {
|
|
68
|
+
actions: ['textSize', 'history', 'close', 'clear', 'expand', 'fullscreen', 'sound', 'language'],
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Color overrides
|
|
76
|
+
|
|
77
|
+
Theme properties you can override:
|
|
78
|
+
|
|
79
|
+
| Option | CSS token | Purpose | Default (help.ai brand) |
|
|
80
|
+
| ----------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
|
|
81
|
+
| `theme.accent` | `--helpai-accent` | Primary brand color | `#10B981` |
|
|
82
|
+
| `theme.accentText` | `--helpai-accent-text` | Text shown on the accent color | `#FFFFFF` |
|
|
83
|
+
| `theme.radius` | `--helpai-radius` | Corner rounding for buttons, cards, pills | `10px` |
|
|
84
|
+
| `theme.fontFamily` | `--helpai-font` | Widget-wide font stack | `Inter, system-ui, -apple-system, Segoe UI, sans-serif` |
|
|
85
|
+
| `theme.contentMaxWidth` | `--helpai-conversation-max` | Max width of the readable content column on a **wide** surface (fullscreen / page / standalone / wide inline) — content centres, bars stay full-bleed. `100%` disables the cap. Modal + drawer fill their card by default. | `768px` |
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
init({
|
|
89
|
+
theme: {
|
|
90
|
+
accent: '#ff3e00',
|
|
91
|
+
accentText: '#fff',
|
|
92
|
+
radius: '16px',
|
|
93
|
+
fontFamily: '"Söhne", -apple-system, sans-serif',
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
All of these are optional — any you don't set inherits the brand default.
|
|
99
|
+
|
|
100
|
+
### Where the accent shows up
|
|
101
|
+
|
|
102
|
+
Anywhere the widget draws "chrome" in your brand color:
|
|
103
|
+
|
|
104
|
+
- The launcher FAB background.
|
|
105
|
+
- Send / Stop button (when `composer.sendButton.variant: "filled"`).
|
|
106
|
+
- Active language/theme menu checkmarks.
|
|
107
|
+
- Link colors in rendered markdown.
|
|
108
|
+
- Agent badge status dot.
|
|
109
|
+
- Focus rings.
|
|
110
|
+
|
|
111
|
+
### Picking an accent
|
|
112
|
+
|
|
113
|
+
Pick any brand color — the widget adapts it per theme so it stays readable, so a
|
|
114
|
+
low-contrast raw color won't render an unreadable widget:
|
|
115
|
+
|
|
116
|
+
- `accent`'s hue + chroma are honored; only its **lightness** is nudged into the
|
|
117
|
+
visible band for the active theme (a near-black accent lightens on dark, a
|
|
118
|
+
near-white one darkens on light).
|
|
119
|
+
- **On-accent text** (the FAB / send glyph) is auto-derived to black or white, so
|
|
120
|
+
`accentText` is **optional** — set it only to force a specific on-fill color
|
|
121
|
+
(it's used as-is only on browsers without CSS relative-color support).
|
|
122
|
+
- **Accent-colored text** (links, active tabs) uses a separate readable shade
|
|
123
|
+
that clears **WCAG AA (4.5:1)** on the panel background for every hue.
|
|
124
|
+
|
|
125
|
+
The one thing to verify yourself is the **FAB against your own page background** —
|
|
126
|
+
it sits on your site, outside the widget's themed surface.
|
|
127
|
+
|
|
128
|
+
Quick contrast check (optional):
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
// Paste in DevTools to check contrast
|
|
132
|
+
function contrast(a, b) {
|
|
133
|
+
// WCAG relative luminance formula
|
|
134
|
+
const lum = (hex) => {
|
|
135
|
+
const [r, g, b] = [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255);
|
|
136
|
+
const lin = (c) => (c < 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));
|
|
137
|
+
return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);
|
|
138
|
+
};
|
|
139
|
+
const [la, lb] = [lum(a), lum(b)].sort((x, y) => y - x);
|
|
140
|
+
return ((la + 0.05) / (lb + 0.05)).toFixed(2);
|
|
141
|
+
}
|
|
142
|
+
contrast('#ff3e00', '#ffffff'); // 3.79 — OK for large text, fail for small
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Launcher
|
|
148
|
+
|
|
149
|
+
The floating bubble + its nudges. `floating` mode only.
|
|
150
|
+
|
|
151
|
+
### Variants
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
init({ launcher: { variant: 'circle' } }); // default — icon only, round
|
|
155
|
+
init({ launcher: { variant: 'pill', label: 'Ask AI' } }); // rounded rectangle
|
|
156
|
+
init({ launcher: { variant: 'bar', label: 'Need help?' } }); // wider rectangle
|
|
157
|
+
init({ launcher: { variant: 'minimal', label: 'Chat' } }); // text-only
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
| Variant | Visual | Best for |
|
|
161
|
+
| --------- | ---------------------- | ------------------------------ |
|
|
162
|
+
| `circle` | 56px round bubble | Classic support chat |
|
|
163
|
+
| `pill` | Icon + label rounded | "Ask AI" marketing CTA |
|
|
164
|
+
| `bar` | Wider prominent bar | High-intent pages |
|
|
165
|
+
| `minimal` | Transparent, text-only | Blends into custom site chrome |
|
|
166
|
+
|
|
167
|
+
### Sizes
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
init({ launcher: { size: 'sm' } }); // 44px — compact
|
|
171
|
+
init({ launcher: { size: 'md' } }); // 56px — default
|
|
172
|
+
init({ launcher: { size: 'lg' } }); // 68px — prominent
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Icons
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
init({ launcher: { icon: 'chat' } }); // default — speech bubble
|
|
179
|
+
init({ launcher: { icon: 'message' } }); // message square
|
|
180
|
+
init({ launcher: { icon: 'bubbles' } }); // stacked chat bubbles
|
|
181
|
+
init({ launcher: { icon: 'spark' } }); // sparkle / magic
|
|
182
|
+
init({ launcher: { icon: 'wand' } }); // wand / magic
|
|
183
|
+
init({ launcher: { icon: 'bot' } }); // robot face
|
|
184
|
+
init({ launcher: { icon: 'help' } }); // question mark
|
|
185
|
+
init({ launcher: { icon: 'lifebuoy' } }); // support ring
|
|
186
|
+
init({ launcher: { icon: 'headset' } }); // support agent
|
|
187
|
+
init({ launcher: { icon: 'search' } }); // friendly magnifier (search + smile)
|
|
188
|
+
init({ launcher: { icon: 'sparkles' } }); // multi-point sparkles (AI / magic)
|
|
189
|
+
init({ launcher: { icon: 'concierge' } }); // concierge bell (front-desk)
|
|
190
|
+
init({ launcher: { icon: 'wave' } }); // waving hand (say hi)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Or pass raw SVG source for a fully custom icon:
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
init({
|
|
197
|
+
launcher: {
|
|
198
|
+
icon: `<svg viewBox="0 0 24 24"><path d="M..." /></svg>`,
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
SVG must be 24×24 viewbox with currentColor strokes/fills.
|
|
204
|
+
|
|
205
|
+
### Callout
|
|
206
|
+
|
|
207
|
+
A single pre-engagement bubble next to the FAB. One component,
|
|
208
|
+
configured for the use case — greeting, attention nudge, or
|
|
209
|
+
onboarding tip.
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
init({
|
|
213
|
+
launcher: {
|
|
214
|
+
callout: {
|
|
215
|
+
text: "Hey! I'm Aria. What can I help with?",
|
|
216
|
+
shape: 'pill', // pill / bubble / callout
|
|
217
|
+
position: 'auto', // auto / horizontal / vertical
|
|
218
|
+
delayMs: 1200,
|
|
219
|
+
autoDismissMs: 0, // 0 = never (dismiss on click). Or 5000 for auto-dismiss after 5s.
|
|
220
|
+
animated: true, // subtle horizontal nudge animation
|
|
221
|
+
persistent: true, // default — re-show on every visit (greeting behaviour)
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### Dismissal lifecycles
|
|
228
|
+
|
|
229
|
+
`persistent` is the only behavioural difference between the two
|
|
230
|
+
typical patterns:
|
|
231
|
+
|
|
232
|
+
- **Recurring greeting (`persistent: true`, default)** — the bubble
|
|
233
|
+
re-shows on every visit regardless of prior dismissal. Use for
|
|
234
|
+
warm "Hi! 👋" copy that should always greet visitors.
|
|
235
|
+
- **One-time hint (`persistent: false`)** — the exact text is
|
|
236
|
+
persisted to localStorage. Once the user clicks the X (or opens
|
|
237
|
+
the widget once), the same copy stays hidden across visits.
|
|
238
|
+
Reconfiguring with NEW text bypasses the prior dismissal — a new
|
|
239
|
+
message is a new ask.
|
|
240
|
+
|
|
241
|
+
Pick `persistent: false` when the bubble is a CTA you don't want to
|
|
242
|
+
nag with after the first dismissal.
|
|
243
|
+
|
|
244
|
+
Tone: short, conversational. Think "Hi! 👋" or "Click here →" — not
|
|
245
|
+
"CLICK HERE FOR DISCOUNTS".
|
|
246
|
+
|
|
247
|
+
### Hiding the launcher entirely
|
|
248
|
+
|
|
249
|
+
Want a custom "open chat" button elsewhere on your site?
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
const chat = init({
|
|
253
|
+
publicKey: 'agent_pk_...',
|
|
254
|
+
aiAgentDeploymentId: '01900000-0000-7000-8000-000000000000',
|
|
255
|
+
launcher: { hidden: true },
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// Your button
|
|
259
|
+
document.querySelector('#my-chat-btn').onclick = () => chat.open();
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Composer
|
|
265
|
+
|
|
266
|
+
The input area.
|
|
267
|
+
|
|
268
|
+
### Send button
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
init({
|
|
272
|
+
composer: {
|
|
273
|
+
sendButton: {
|
|
274
|
+
shape: 'pill', // circle / square / pill
|
|
275
|
+
icon: 'arrowUp', // arrowUp / paperPlane / send / chevron
|
|
276
|
+
variant: 'filled', // filled / outline / ghost
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
3 × 4 × 3 = 36 combinations. Pick what matches your brand.
|
|
283
|
+
|
|
284
|
+
Quick recipes:
|
|
285
|
+
|
|
286
|
+
- **Minimal outline** — `{ shape: 'circle', variant: 'outline', icon: 'arrowUp' }`
|
|
287
|
+
- **Bold filled** — `{ shape: 'pill', variant: 'filled', icon: 'paperPlane' }`
|
|
288
|
+
- **Ghost text** — `{ shape: 'square', variant: 'ghost', icon: 'send' }`
|
|
289
|
+
|
|
290
|
+
### Disclaimer line
|
|
291
|
+
|
|
292
|
+
Below the textarea, small grey text. Classic "AI can make mistakes"
|
|
293
|
+
pattern.
|
|
294
|
+
|
|
295
|
+
```ts
|
|
296
|
+
init({ footer: { composerDisclaimer: 'AI-generated. Verify important details.' } });
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Empty string = hidden. Keep it short (< 60 chars for mobile).
|
|
300
|
+
|
|
301
|
+
### Powered-by row
|
|
302
|
+
|
|
303
|
+
Optional attribution below the disclaimer.
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
init({
|
|
307
|
+
footer: {
|
|
308
|
+
poweredBy: {
|
|
309
|
+
text: 'Powered by Help AI',
|
|
310
|
+
href: 'https://help.ai',
|
|
311
|
+
logoUrl: 'https://cdn.help.ai/logo.svg',
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
- Omitted fields inherit the active brand's attribution defaults. Set
|
|
318
|
+
`footer.poweredBy.text` to `""` (without a logo) to hide the row.
|
|
319
|
+
- `href` wraps the row in a link with `target="_blank"
|
|
320
|
+
rel="noopener noreferrer"`.
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Header actions
|
|
325
|
+
|
|
326
|
+
See [Configuration § Header actions](./configuration.md#header-actions)
|
|
327
|
+
for the full semantics. Quick customization examples:
|
|
328
|
+
|
|
329
|
+
### Minimal chrome
|
|
330
|
+
|
|
331
|
+
Strip everything but close:
|
|
332
|
+
|
|
333
|
+
```ts
|
|
334
|
+
init({
|
|
335
|
+
header: { actions: ['close'] },
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Language-enabled
|
|
340
|
+
|
|
341
|
+
Enable the language row for multilingual marketing. Placement and ordering are
|
|
342
|
+
fixed by the widget; the array is only an enabled set.
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
init({
|
|
346
|
+
i18n: { availableLocales: ['en', 'fr', 'es', 'de'] },
|
|
347
|
+
header: { actions: ['language', 'theme', 'textSize', 'history', 'close', 'clear', 'expand', 'fullscreen', 'sound'] },
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### History-focused chrome
|
|
352
|
+
|
|
353
|
+
Keep the header focused on history and basic preferences:
|
|
354
|
+
|
|
355
|
+
```ts
|
|
356
|
+
init({
|
|
357
|
+
header: { actions: ['history', 'close', 'clear', 'sound', 'language', 'theme'] },
|
|
358
|
+
features: { disableFileUpload: true, voice: 'disabled' },
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Internationalization
|
|
365
|
+
|
|
366
|
+
### Language switcher
|
|
367
|
+
|
|
368
|
+
Enable the `language` action — when more than one locale is available, the
|
|
369
|
+
header's ⋯ menu shows one segmented language row:
|
|
370
|
+
|
|
371
|
+
```ts
|
|
372
|
+
init({
|
|
373
|
+
i18n: {
|
|
374
|
+
availableLocales: ['en', 'fr', 'es', 'de', 'ja'],
|
|
375
|
+
defaultLocale: 'auto', // sniff navigator.language
|
|
376
|
+
},
|
|
377
|
+
header: { actions: ['language', 'theme', 'history', 'close'] },
|
|
378
|
+
});
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Locale display names come from `Intl.DisplayNames` in the active
|
|
382
|
+
locale — so a French user sees "anglais, français, espagnol", not
|
|
383
|
+
"English, French, Spanish".
|
|
384
|
+
|
|
385
|
+
The user's pick persists across devices (via the backend).
|
|
386
|
+
|
|
387
|
+
### Strings overrides
|
|
388
|
+
|
|
389
|
+
Every UI string is configurable. Two shapes:
|
|
390
|
+
|
|
391
|
+
**Flat** (applies to active locale):
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
init({
|
|
395
|
+
i18n: {
|
|
396
|
+
strings: {
|
|
397
|
+
composerPlaceholder: 'Ask me anything…',
|
|
398
|
+
send: 'Go',
|
|
399
|
+
newConversation: 'Start over',
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
});
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
**Nested** (per-locale):
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
init({
|
|
409
|
+
i18n: {
|
|
410
|
+
strings: {
|
|
411
|
+
en: { send: 'Go', composerPlaceholder: 'Ask me anything…' },
|
|
412
|
+
fr: { send: 'Envoyer', composerPlaceholder: 'Demandez-moi…' },
|
|
413
|
+
es: { send: 'Enviar', composerPlaceholder: 'Pregúntame…' },
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Full list of string keys
|
|
420
|
+
|
|
421
|
+
```
|
|
422
|
+
attach, attachmentMimeRejected, attachmentTooLarge,
|
|
423
|
+
attachmentTooMany, conversationClosed, close, collapse,
|
|
424
|
+
composerPlaceholder, dateLastWeek, dateOlder, dateToday,
|
|
425
|
+
dateYesterday, dropZone, errorGeneric, errorRetry, expand,
|
|
426
|
+
exitFullscreen, fullscreen, history, historyBack, historyEmpty,
|
|
427
|
+
historyLoading, historyTitle, language, launcherOpen,
|
|
428
|
+
conversationLoading, loadMoreConversations, loadPreviousMessages, micStart, micStop, micUnsupported, moreActions,
|
|
429
|
+
newConversation, panelTitle, resizeHandle, send, soundOff,
|
|
430
|
+
soundOn, startNewConversation, stop, theme, themeAuto, themeDark,
|
|
431
|
+
themeLight, thinking, usedTool
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
Any key you don't override keeps its default English value.
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Dashboard vs client-side
|
|
439
|
+
|
|
440
|
+
**Every theming option above can also be set in your Help AI
|
|
441
|
+
dashboard.** The dashboard lets non-engineers tune colors, copy, and
|
|
442
|
+
launcher chrome without redeploying your site.
|
|
443
|
+
|
|
444
|
+
Precedence:
|
|
445
|
+
|
|
446
|
+
1. Options you pass to `init()` win.
|
|
447
|
+
2. Dashboard settings fill in anything you leave unset.
|
|
448
|
+
3. Built-in defaults are the final fallback.
|
|
449
|
+
|
|
450
|
+
This means you can:
|
|
451
|
+
|
|
452
|
+
- Hardcode brand colors in code (so they never drift even if someone
|
|
453
|
+
edits the dashboard).
|
|
454
|
+
- Let the dashboard own launcher copy (so marketing can A/B-test
|
|
455
|
+
without asking engineering).
|
|
456
|
+
- Mix freely — every option is independently controlled.
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
## CSS-level customization (advanced)
|
|
461
|
+
|
|
462
|
+
The widget renders inside a shadow root, so your page CSS can't reach
|
|
463
|
+
it. If you need to go beyond the `theme` overrides, the widget exposes
|
|
464
|
+
~40 CSS custom properties on its host element you can tweak directly:
|
|
465
|
+
|
|
466
|
+
```css
|
|
467
|
+
web-ai-chat,
|
|
468
|
+
helpai-chat-host {
|
|
469
|
+
/* Colors */
|
|
470
|
+
--helpai-bg: #fafafa;
|
|
471
|
+
--helpai-fg: #111;
|
|
472
|
+
--helpai-border: #e5e5e5;
|
|
473
|
+
/* Set the accent via the `-user` slots — the widget DERIVES the theme-adapted
|
|
474
|
+
`--helpai-accent` / `--helpai-accent-text` / `--helpai-accent-fg` from these,
|
|
475
|
+
so overriding the derived tokens directly has no effect on modern browsers. */
|
|
476
|
+
--helpai-accent-user: #ff3e00;
|
|
477
|
+
--helpai-accent-text-user: #fff;
|
|
478
|
+
|
|
479
|
+
/* Panel dimensions */
|
|
480
|
+
--helpai-panel-w: 420px;
|
|
481
|
+
--helpai-panel-h: 640px;
|
|
482
|
+
--helpai-expanded-w: 640px;
|
|
483
|
+
--helpai-expanded-h: 820px;
|
|
484
|
+
|
|
485
|
+
/* Launcher */
|
|
486
|
+
--helpai-fab-size: 56px;
|
|
487
|
+
|
|
488
|
+
/* Typography */
|
|
489
|
+
--helpai-font: "Inter", system-ui, sans-serif;
|
|
490
|
+
--helpai-radius: 10px;
|
|
491
|
+
|
|
492
|
+
/* Motion */
|
|
493
|
+
--helpai-dur-base: 240ms;
|
|
494
|
+
--helpai-dur-quick: 120ms;
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
These cascade through the shadow root — a single rule on the host
|
|
499
|
+
element propagates to every component inside. Full list in
|
|
500
|
+
`src/styles/tokens.css` in the source.
|
|
501
|
+
|
|
502
|
+
### Styling parts
|
|
503
|
+
|
|
504
|
+
Five elements carry `part` names, so your own CSS restyles them through the shadow root with `::part()` — no
|
|
505
|
+
reaching into the widget, and names that stay stable across releases:
|
|
506
|
+
|
|
507
|
+
| Part | Element |
|
|
508
|
+
| ---------- | -------------------------------------------------------------------------- |
|
|
509
|
+
| `launcher` | The floating launcher button |
|
|
510
|
+
| `panel` | The open panel (chat, tabbed messenger or empty state) |
|
|
511
|
+
| `header` | The bar at the top of the panel (the chat, history and sub-screen headers) |
|
|
512
|
+
| `messages` | The scrolling message list |
|
|
513
|
+
| `composer` | The message box area |
|
|
514
|
+
|
|
515
|
+
```css
|
|
516
|
+
web-ai-chat::part(launcher) {
|
|
517
|
+
box-shadow: 0 8px 24px rgb(0 0 0 / 0.25);
|
|
518
|
+
}
|
|
519
|
+
web-ai-chat::part(panel) {
|
|
520
|
+
border-radius: 20px;
|
|
521
|
+
}
|
|
522
|
+
web-ai-chat::part(header) {
|
|
523
|
+
border-bottom-color: transparent;
|
|
524
|
+
}
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
Use `helpai-chat-host::part(…)` for a widget mounted with `init()` / the script tag. Parts don't cross an iframe, so
|
|
528
|
+
`presentation.iframe: true` widgets are styled with tokens only. Prefer the tokens above for colour and size; parts
|
|
529
|
+
are for what tokens don't cover (shadows, corners, borders).
|
|
530
|
+
|
|
531
|
+
For truly bespoke designs (e.g., replacing the launcher with your
|
|
532
|
+
own component), use `launcher.hidden: true` + custom trigger, or a
|
|
533
|
+
[no-script trigger](./api-reference.md#no-script-triggers).
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
## Per-deployment vs per-instance
|
|
538
|
+
|
|
539
|
+
Some knobs are set at the **deployment** level (in your Help AI
|
|
540
|
+
dashboard) and apply to every widget mounted for that deployment:
|
|
541
|
+
|
|
542
|
+
- Theme defaults
|
|
543
|
+
- Launcher chrome defaults
|
|
544
|
+
- Welcome messages + suggestion chips
|
|
545
|
+
- Agent persona (name, avatar, status)
|
|
546
|
+
- Model routing
|
|
547
|
+
- Tool allowlist
|
|
548
|
+
- Action layout defaults
|
|
549
|
+
- I18n strings
|
|
550
|
+
|
|
551
|
+
Other knobs are best set **per-instance** in your `init()` call:
|
|
552
|
+
|
|
553
|
+
- `widgetId` (for multi-widget pages)
|
|
554
|
+
- `target` (for inline/standalone)
|
|
555
|
+
- `user` identity
|
|
556
|
+
- `onMessage` / `onOpen` / `onError` callbacks
|
|
557
|
+
|
|
558
|
+
Any option set in `init()` wins over the deployment default, so you
|
|
559
|
+
can always override.
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## Next
|
|
564
|
+
|
|
565
|
+
- [Events & hooks](./events-and-hooks.md) — listening to chat
|
|
566
|
+
interactions, integrating with analytics.
|
|
567
|
+
- [Recipes](./recipes.md) — copy-paste examples for common
|
|
568
|
+
customization scenarios.
|
|
569
|
+
- [Configuration reference](./configuration.md) — the full option
|
|
570
|
+
table.
|