On this page
You can brand the widget in two ways, and combine them:
- In the Widget Studio (portal → Website widget): pick colours, corner radius, launcher text and icon, assistant name, header title and subtitle, welcome message, suggested questions, your logo and an optional invitation. Changes are delivered to your site with no code. The Studio shows a live preview of the real widget. Each field is described in the Widget Studio field reference. The Studio sets the main and accent colours, light or dark, corner radius, launcher text, icon, size and side;
themeDark,fontFamily,offset, avatars and the other colours are set in your page only. - In your page: pass
theme,launcher,headerand the other options from the configuration reference. Page options override Studio settings, field by field.
Colours#
All colours are #rgb or #rrggbb only. Anything else is ignored with a console warning.
theme key | Used for | Default (light) |
|---|---|---|
primary | Header, launcher, your visitors' messages, the main button | #0b5c4a |
accent | Active tab, bullets, highlights | the primary colour |
background | The chat panel and input fields | #ffffff |
surface | Cards and the assistant's message bubbles | #f3f5f7 |
text | Body text | #17202a |
mutedText | Secondary text, placeholders | #55606c |
border | Dividers and input borders | #d9dee3 |
focus | The keyboard focus ring | the primary colour |
Give only primary for a quick brand match. If you give a background, the text, surface, muted text and border are derived to match.
Readable contrast is enforced#
Whatever you choose, the widget raises colour pairs until they are readable, and writes a console warning when it changes something:
- text on the background and on surfaces: at least 4.5:1;
- the accent colour and the focus ring on the surfaces: at least 3:1;
- the text on the primary colour is chosen automatically (white or dark) to be readable.
So a very pale accent shows as a deeper shade than you picked. In the Studio, a warning appears next to the colour field when this will happen.
Dark mode#
appearance can be light, dark or auto (follow the visitor's system, live). Dark mode has its own palette. Your primary and accent carry over to dark mode (the accent is lightened if it would be hard to see). Use themeDark to override any colour for dark mode only:
import type { InitOptions } from '@recent-visits/widget'
export const dark: InitOptions = {
key: 'rvk_AAAAAAAAAAAAAAAAAAAAAAAA',
appearance: 'auto',
theme: { primary: '#0b5c4a' },
themeDark: { background: '#0f1720', surface: '#17212c' },
}Shape and type#
| Option | Range | Default |
|---|---|---|
theme.radius | 0 to 28 (px) | 16 (the Studio slider labels its default 14; move it to 16 for exactly 16) |
theme.fontFamily | A plain font-family list such as "Inter", system-ui, sans-serif | system fonts |
launcher.size | 44 to 72 (px) | 56 |
offset | 0 to 200 (px) | 16 |
fontFamily is validated: it may contain letters, digits, spaces, commas, quotes, dots, underscores and hyphens, and anything that looks like url, expression, import or javascript is refused. The widget does not load fonts; if you name a web font, your site must already load it.
Launcher, header and identity#
- Launcher: an icon button (
compass,chatorsparkle) with optional text (up to 30 characters). On a phone-sized screen (480 px and narrower) a launcher with text shrinks to its icon. You can use your own avatar image (launcher.avatarUrl). - Header:
header.title(default your agency name) andheader.subtitle, plus your logo (agency.logoUrl; in the Studio, the Show my agency logo switch uses your profile logo). The chat names the assistant withassistant.name. - Position:
position(leftorright) andoffsetmove the launcher so it clears your own floating buttons.
Images must be https (or a small base64 PNG, JPEG or WebP). If your site has a Content-Security-Policy you must allow their origin in img-src.
Inputs and states#
The text boxes, buttons and tabs follow the palette: their background, border, text and focus colours come from background, border, text and focus; the main button uses primary. The checkbox in the quote form is drawn in your primary colour. All text fields share hover, focus, invalid, disabled and read-only styles, and an invalid field is marked by an outline, an aria-invalid attribute and an error message beginning with "!", not by colour alone.
What you cannot style#
- No custom CSS. The stylesheet is fixed and lives inside a closed Shadow DOM: your page's CSS cannot restyle the widget, and the widget's CSS cannot leak into your page. Configuration can never inject CSS, markup or script.
- Individual form controls (an input's border colour alone, for example) cannot be coloured separately; they follow the palette.
- No custom launcher icon beyond the three built-ins plus your own avatar image.
- Only English text; wording the widget writes itself (such as the privacy note) cannot be changed.
- No exposed CSS variables for your page to read. Colours are set through the options above.
If you need a style the options cannot express, tell us what you need at partners@recent-visit.com (opens in a new tab).
Accessibility and mobile#
The launcher is a real button with an accessible name; the chat opens as a labelled dialog, moves focus in, returns it to the launcher on close and closes with Escape. Replies are announced politely. Animation is small and disabled when the visitor prefers reduced motion. At 480 px and narrower the panel is full-screen and respects the device's safe areas.
Last checked against the product:
Related articles
- SDK configuration reference · Every option the Recent Visits widget accepts: type, default, limits and an example. Invalid values are replaced by safe defaults.
- Widget Studio field reference · Every screen, tab, field and button of the Website widget page in the agency portal: websites and keys, settings, draft and publish, live preview, and what owners and managers can see.
- SDK examples · Copy-and-paste integration examples for the Recent Visits widget: minimal, agency configuration, themed, Next.js, React with the package, and a headless quote request.
- SDK troubleshooting · Fixes for the widget not appearing, wrong branding or content, options not applying, network and permission errors, Next.js and mobile problems, and quote requests that do not show up.
Still stuck? Contact us and tell us what you tried.