Overview
Every aspect of the tour — from step definitions to the appearance of each UI element — is controlled through a single configuration object, BordaConfig, passed to borda.mount(). The only required field is steps; everything else has a sensible default or can be disabled entirely.
import { useBorda, ComponentPlacement, BordaTourProgressVariant } from '@retoo/borda';
import '@retoo/borda/styles';
const borda = useBorda();
const instance = await borda.mount({
steps: [
{
target: '#nav-sidebar',
title: 'Navigation',
description: 'Every section is one click away.',
placement: ComponentPlacement.MIDDLE_END,
},
{
target: '#search-bar',
title: 'Search',
description: 'Find any page or setting instantly.',
placement: ComponentPlacement.BOTTOM_CENTER,
},
{
target: '#main-content',
title: 'Main area',
description: 'Your primary content lives here.',
placement: ComponentPlacement.MIDDLE_START,
},
{
target: '#user-menu',
title: 'Account',
description: 'Manage your profile and preferences.',
placement: ComponentPlacement.BOTTOM_END,
},
],
tourProgress: {
variant: BordaTourProgressVariant.DOTS,
},
});
Config structure
BordaConfig combines component overrides and feature configs:
| Key | Description |
|---|---|
steps | Array of step definitions. Required. |
size | Widget size — xs, sm, md, lg, xl, xxl |
shape | Widget shape — circle, square, portrait, landscape |
container | Outer container props — custom classes/styles |
tourOverlay | Spotlight overlay. Pass false to disable. |
tourTooltip | Tooltip with title/description. Pass false to disable. |
tourImage | Image inside the tooltip. Pass false to disable. |
tourButtons | Prev/next/finish/skip buttons. Pass false to disable. |
tourProgress | Progress indicator. Pass false to disable. |
tourSkip | "Don't show again" checkbox. Pass false to disable. |
closeButton | Close button. Pass false to disable. |
tour | Tour behavior — startStep, lifecycle callbacks, keyboard control |
visibility | Initial visibility state and animation |
responsive | Breakpoint-specific overrides |
scroll | Smooth scroll to target. Pass false to disable. |
skip | Skip feature persistence. Pass false to disable. |
animation | Tooltip/overlay animations. Pass false to disable. |
Disabling components
Pass false to any component key to remove it from the tour entirely:
Compare this to the live demo above the fold: that one shows every component enabled with progress dots; this one strips them all down to the spotlight and tooltip text.
await borda.mount({
steps: [
{
target: '#announcement-banner',
title: 'New feature available',
description: 'A one-off spotlight with no navigation chrome — pair it with your own dismiss logic.',
placement: ComponentPlacement.BOTTOM_CENTER,
},
],
tourSkip: false,
tourButtons: false,
tourProgress: false,
closeButton: false,
});
This is different from hiding — a disabled component is never rendered in the DOM.
Runtime updates
After mount, modify any config property through the instance — useful for reacting to screen size, user plan, or A/B test variant without unmounting:
import { useBorda, ComponentSize } from '@retoo/borda';
import '@retoo/borda/styles';
const borda = useBorda();
const instance = await borda.mount({
steps: [
{
target: '#trial-banner',
title: "You're on a free trial",
description: 'Upgrade any time from account settings.',
placement: 'bottom-center',
},
],
});
// Deep merge — only the specified fields are updated
// e.g. enlarge the widget and hide skip once the user is on their 3rd session
instance.config.mergeConfig({
size: ComponentSize.LG,
tourButtons: { skip: false },
});
// Full replacement — e.g. switch to a different flow after the user upgrades
instance.config.setConfig({
steps: [
{
target: '#billing-section',
title: "You're on the Pro plan",
description: 'Manage your subscription and invoices here.',
placement: 'bottom-center',
},
],
});
Both methods trigger a reactive update — the widget re-renders immediately without remounting.
Customization
Most components accept customClasses and customStyles for visual overrides without modifying the source. Classes are merged with the defaults; styles are applied as inline CSS.
await borda.mount({
steps: [
{
target: '#cta-button',
title: 'Branded tooltip',
description: 'Custom classes and inline styles, no source modification required.',
placement: ComponentPlacement.BOTTOM_CENTER,
},
],
tourTooltip: {
customClasses: {
root: 'my-tooltip',
title: 'text-lg font-bold',
},
customStyles: {
root: {
borderRadius: '4px',
background: '#fafaf9',
border: '2px solid #18181b',
},
},
},
});