Skip to content

Adoption checklist

Finish a migration on the library's behaviour, not on green gates. Find what the app still builds by hand and replace it.

On this page

A migration is done when the app runs on the library's behaviour, not when the gates are green. Walk this list after the app compiles and runs on the new version, whether it comes from bitboss-ui v2, from another component library or from controls it built itself.

Why a second walk

One app passed every gate after its upgrade: vue-tsc, about 900 tests, bitboss-ui check and screenshot diffs against the old version. It still kept about 25 controls it had built by hand while the library shipped them: radio cards, tag groups, segmented controls, check squares, steppers, sortable headers, a nested table, notice boxes, its own mobile sheets. Each was a place where keyboard support, ARIA, focus, mobile behaviour and the look drifted from the rest of the app. Moving them onto the library took a second full pass. This checklist is that pass, done the first time.

What to adopt, and what to leave

Judge each case by its gain.

  • Adopt where the library removes a sizable amount of hand-rolled code or behaviour: each of those 25 controls dropped its own keyboard handling, ARIA and styling for the library's.
  • Leave a low-gain nicety that would mean refactoring shared code, such as a newer confirm option that would rework the app's shared confirm composable.

Adoption is part of the migration; tidying unrelated code is not. A hand-rolled control you decide to keep gets one line in a HANDROLLED.md with the reason, so the next reader knows it was a decision.

How to find them

bash
npx bitboss-ui check --idioms

It runs the regular check, then lists every pattern below that is still in the app, with the file, the line and the replacement. It is report-only: the patterns are guesses from markup (a raw <table> can be an email template), so they never change the exit code, and a plain check never runs them. --json adds an idioms array of { file, line, id, use }. The package carries the same list with an rg command per row, in node_modules/bitboss-ui/dist/ai/guides/migration/adoption-checklist.md.

Switch views or pick a value

The two look alike and are not interchangeable. Decide by the job:

  • Switch views → BbTabs, whose default pill look is the segmented strip. The choice changes what the page shows: Board / Table, Info / Users. It gets the tab roles, the sliding pill and, with navigation, a URL.
  • Pick a value → BbRadioGroup with variant="pill" or "line", the tab strip's looks. The choice is a value a form or a filter submits: a status filter, a plan. It stays a radio group: arrow keys select, "2 of 4" is announced, and legend, errors and required work.

Several values at once is BbCheckboxGroup, with the same two looks. Independent on/off toggles are BbButton with v-model.

The patterns

What you find, and what replaces it. The id in brackets is what check --idioms reports.

You findUse instead
Radio cards, a pill row, role="radiogroup", a raw <input type="radio"> [radio-group]BbRadioGroup
role="checkbox" on your markup, a raw <input type="checkbox"> [checkbox]BbCheckbox / BbCheckboxGroup
role="tablist" / role="tab" on your markup [tabs]BbTabs
A v-for of aria-pressed buttons, a SegmentedControl / TagGroup of your own [toggle-group]BbTabs, BbRadioGroup or BbCheckboxGroup, by the job
Your own aria-sort, sort arrows and click handlers on <th> [sort-header]BbTable sortable columns and v-model:sort
A raw <table>, a hand-made nested or expanding one [table]BbTable, with #expand for rows that open
A check icon in #option, or a class hiding the library's own check [option-check]The selected row draws its own check in BbSelect, BbSelectPopover and BbDropdown
Minus / plus buttons around a number [stepper]BbNumberInput
A styled <div role="status"> or role="alert" [notice]BbAlert
A whole card wrapped in a link [clickable-card]BbBaseButton as an overlay link; keep the box
A useBottomSheet of your own, a v-if'd BbOffCanvas, a side switched on isMobile [app-sheet]The adaptive overlays, or BbOffCanvas with :side="{ default: 'bottom', md: 'right' }"
A raw <dialog>, window.confirm(), an app ConfirmDialog [app-dialog]BbDialog and v-bb-dialog, or confirm()
A delete confirm without the destructive look [destructive-confirm]confirm({ variant: 'destructive' })
Your own useIsMobile, matchMedia or innerWidth check [media-query]useMobile(), the breakpoint the overlays switch at
Page-number buttons, an app Pagination [pagination]BbPagination
A raw <details> / <summary> [disclosure]BbAccordion
A raw <input>, <textarea> or <select> [form-control]BbTextInput, BbNumberInput, BbDatePickerInput, BbTimePickerInput, BbTextarea, BbSelect
A raw <button> [raw-button]BbButton, or BbBaseButton for your own look
A raw <progress> or role="progressbar" [progress]BbProgress
An InitialsAvatar of your own [avatar]BbAvatar
adaptive: false or :adaptive="false" [adaptive-false]Remove it in the final phase

Some patterns have no reliable search. Look for them by eye on the same walk: a tinted pill standing for a status is a BbBadge with a registered variant, a count pinned over a control is a BbIndicator, and a read-only value drawn as a styled div is the field itself with readonly.

Final phase, go adaptive

A migration from v2 often turns adaptive off at first, to keep the floating panels while everything else moves. That is a temporary crutch, not a destination. Once the app is stable on the new version:

  1. Remove adaptive: false from the plugin options and every :adaptive="false", so dialogs, dropdowns, selects, popovers and the pickers open as bottom sheets on a phone.
  2. Delete the app's own sheets and every isMobile ? 'bottom' : 'right'. A panel at the side on desktop and at the bottom on a phone is :side="{ default: 'bottom', md: 'right' }" with draggable.
  3. Walk the app at phone width and review every overlay once.

Keep :adaptive="false" only on a surface that must never become a sheet, with a comment that says why.

Last step, rebuild

Rebuild and redeploy the production assets. A committed or cached build keeps serving the old library until it is rebuilt, and every review of the migrated app on that server looks at the old version.