Theming & Tokens
Match the widget to your brand with CSS variables. Light + dark mode, brand color, radius, fonts — overridable from your host stylesheet.
The default Helpway widget ships with a clean light + dark theme out of the box, but every visual primitive — surface colors, text contrast, brand accent, border radius — is exposed as a CSS variable on the widget root (.hw-widget). Override one variable in your own stylesheet and every component picks it up.
Quick start
/* in your app's global stylesheet, after Helpway's CSS loads */
.hw-widget {
--hw-brand: #7c5cff; /* your accent color */
--hw-on-brand: #ffffff; /* foreground that sits on --hw-brand */
--hw-radius: 14px; /* corner softness */
}That's it. Team avatars, primary CTAs, and any future brand-tinted surface adopt the new color immediately.
Dark mode
Three modes — pick one:
| Mode | How |
|---|---|
| Auto (default) | Follows the visitor's OS via prefers-color-scheme. No code needed. |
| Force light | Set data-theme="light" on the widget root, or pass theme="light" as a prop. |
| Force dark | Set data-theme="dark". |
<HelpwayWidget apiKey="pk_live_xxx" theme="dark" />When dark is active, every token below switches to its dark value — including --hw-brand, which inverts so a dark brand color stays visible on dark surfaces.
Token reference
All tokens live on .hw-widget. Override them on the same selector (or its inline style) to retheme.
Surfaces
| Token | Light | Dark | Used by |
|---|---|---|---|
--hw-bg | #ffffff | #1c1c1e | Window background, primary cards |
--hw-bg-subtle | #fafafa | #161618 | Inputs, deeper surfaces |
--hw-bg-hover | #f5f5f5 | #2c2c2e | Hover states, secondary buttons |
--hw-border | #f0f0f0 | rgba(255,255,255,0.08) | Subtle dividers |
--hw-border-md | #e5e5e5 | rgba(255,255,255,0.14) | Stronger dividers |
Text
| Token | Light | Dark | Used by |
|---|---|---|---|
--hw-text / --hw-text-1 | #111 | #f5f5f5 | Primary copy |
--hw-text-2 | #666 | #a1a1aa | Secondary copy, captions |
--hw-text-3 | #999 | #71717a | Placeholders, metadata |
--hw-text-4 | #bbb | #52525b | Disabled, faintest |
Brand
| Token | Light | Dark | Used by |
|---|---|---|---|
--hw-brand | #171717 | #f5f5f5 | Team avatar fallback, primary CTAs |
--hw-on-brand | #ffffff | #1c1c1e | Foreground on --hw-brand (text + svg) |
--hw-primary | #171717 | #171717 | Composer send button bg |
--hw-accent | #6366f1 | #6366f1 | Reserved for future highlight surfaces |
Note:
--hw-brandand--hw-on-brandcome as a pair. If you set a custom--hw-brand, set--hw-on-brandtoo to guarantee contrast — the default#fffwill not work on a light brand.
Bubbles
| Token | Light | Dark | Used by |
|---|---|---|---|
--hw-visitor-bubble-bg | #f0f0f0 | #2c2c2e | Visitor message bubble background |
--hw-visitor-bubble-text | #1a1a1a | #f5f5f5 | Visitor message text |
Focus & interaction
| Token | Light | Dark | Used by |
|---|---|---|---|
--hw-focus-border | #9ca3af | rgba(255,255,255,0.28) | Border on focused inputs |
--hw-focus-ring | rgba(0,0,0,0.06) | rgba(255,255,255,0.08) | Halo around focused inputs |
Geometry & typography
| Token | Default | Used by |
|---|---|---|
--hw-radius | 16px | Window + cards corner radius |
--hw-font | system stack | Whole widget font family |
Runtime tokens (don't override)
These are set programmatically by the widget. Listed for completeness:
--hw-position-left/--hw-position-right— launcher anchor--hw-window-left/--hw-window-right— open window anchor--hw-visible-height— viewport height tracker (mobile keyboard)
Recipes
Indigo brand on white
.hw-widget {
--hw-brand: #4f46e5;
--hw-on-brand: #ffffff;
}Brand color that stays consistent in dark mode
By default --hw-brand flips for contrast. If you want your exact brand color in both modes, override it in the dark scope too:
.hw-widget,
.hw-widget[data-theme="dark"] {
--hw-brand: #7c5cff;
--hw-on-brand: #ffffff;
}Match host font
.hw-widget {
--hw-font: "Inter", -apple-system, sans-serif;
}Tighter, sharper corners
.hw-widget {
--hw-radius: 10px;
}Things to avoid
- Don't invent token names.
var(--hw-surface)orvar(--hw-text-muted)won't resolve — they aren't defined. CSS variable fallbacks fail silently, so a typo will look like a dark-mode bug. The complete list is the table above. - Don't override hex inside selectors. Prefer overriding the token at the
.hw-widgetroot. That way every selector that reads the token (including future ones) picks up your value. - Don't override
--hw-primaryand--hw-brandto different values. They serve overlapping roles today; pick one as your accent and let the other inherit.
What's not (yet) tokenized
- Bubble corner radius — uses
--hw-radiusindirectly but not configurable per-side. - Animation timings — currently hard-coded
cubic-bezier(0.23, 1, 0.32, 1). - Composer attachment chips — share the surface tokens but no dedicated knob yet.