Get started
Languages and branding
Every string a reporter sees lives in a Locale: seven status messages —
the last of them optional, for the report's reference — and the widget's ui
labels. bugbottle/locales ships English, Danish, Swedish,
Norwegian, German, Dutch, French and Spanish, and resolveLocale(navigator.language)
picks one. Override any label, or write a locale of your own — the type tells
you what is required:
import { da, resolveLocale } from "bugbottle/locales";
useBugReport({ endpoint, messages: da.messages });
mountBugbottle({
endpoint,
locale: resolveLocale(navigator.language),
texts: { title: "Hjælp os med at gøre det bedre", trigger: "Fejl?" },
messages: { sent: "Tak — vi kigger på det i morgen tidlig" },
});The report's reference #
handleReport answers with the id it stored the report under, and both the
panel and useBugReport put it in the confirmation:
Thank you — the report is on its way. Reference: B-4711
A reporter who is only told the report is on its way has nothing to quote to
the person who will look for it. The sentence is the locale's
messages.sentWithId, with {id} where the reference goes, and the key is
optional: a locale without one is thanked with sent instead, so a
hand-written Messages keeps working. So is an endpoint that answers no id —
and an id longer than a reference could be, which is left out rather than shown
clipped, because half a reference finds nothing and still reads as though the
real one is in hand.
sentLine(messages, id) builds that sentence. It is the one place that knows
what {id} means, and the panel and the four framework bindings all share it,
so the hook and the panel say the same thing in the same language.
import { sentLine } from "bugbottle/locales";
sentLine(da.messages, "B-4711");
// → "Tak — rapporten er på vej. Rapport nummer: B-4711"Five more languages, imported on purpose #
A locale is data, and data is carried whole: everything that imports
bugbottle/locales pays for all eight languages in it. Italian, Polish,
Portuguese, Finnish and Ukrainian are in a second entry so that a site in one of
them can have its own language without every other site growing. Import the
whole map, or the single language the site is in:
import { en, locales, resolveLocale } from "bugbottle/locales";
import { localesExtra } from "bugbottle/locales-extra";
const all = { ...locales, ...localesExtra };
mountBugbottle({ endpoint, locale: resolveLocale(navigator.language, en, all) });resolveLocale takes the map to look in as its third argument, so nothing about
this reaches a bundle that does not ask for it — not the core, and not either
script-tag build, which still carry the eight. pt is European Portuguese and
pt-BR resolves to it, the way da-DK resolves to da.
Branding and theme #
The panel's look comes from theme and from brand (name, logo as an
image URL or inline SVG). Every value in theme is also a CSS custom property
on the host element, so a stylesheet can restyle the panel without touching
JavaScript:
[data-bugbottle="ui"] { --bb-primary: #0f766e; --bb-font: "Inter", sans-serif; }The whole list, and nothing else:
| CSS variable | theme key |
What it is |
|---|---|---|
--bb-primary |
primary |
The brand colour: the button, the send action, the marks the annotator draws |
--bb-on-primary |
onPrimary |
The text and icons that sit on the brand colour |
--bb-bg |
background |
The panel's ground |
--bb-text |
text |
The ink |
--bb-muted |
muted |
Hints, notes and the status line |
--bb-border |
border |
The rules around the panel and its fields |
--bb-radius |
radius |
The corner radius, as a CSS length |
--bb-font |
font |
The font stack the panel is set in |
--bb-shadow |
shadow |
The shadow under the panel |
--bb-z |
zIndex |
Where the panel sits against the application |
| — | position |
Which corner it lives in: "bottom-right" (the default), "bottom-left", "top-right" or "top-left" |
| — | scheme |
"light", "dark" or "auto" — "auto" follows the reader's system setting |
The last two are not custom properties: they are the data-pos and
data-scheme attributes on the host, which the panel's own stylesheet reads.
None of these survive Windows High Contrast, and they are not meant to. Under
forced-colors: active the browser throws every colour away and substitutes
one from the reporter's own palette, so the panel stops asking for its brand
colour and says the same things in system colours instead: ButtonText for the
edge of the trigger and the send button, whose background was their whole
shape; Highlight and HighlightText for the selected report type, the active
drawing tool and the armed element picker; Highlight for the focus ring; and
GrayText for a disabled action, since forced colours do not dim an opacity.
The attached picture and the annotator canvas keep their own pixels — a mark's
colour is the mark — and so does anything a mark was drawn in. There is nothing
to configure: it happens when the reporter's system asks for it.
The theme playground
on the documentation site restyles a real panel as you move these controls and
prints the mountBugbottle call and the CSS block to copy. It prints only the
keys you moved, so the block you copy leaves scheme alone and your panel goes
on following the reader's system setting.
Try it
Move a control and the panel beside it is restyled as you go, from the same values the table above lists. The two blocks below are the call and the stylesheet that produce what you are looking at. Nothing is saved: reloading the page brings back the defaults.