Skip to main content

Migrating from Takeoff UI v1

@takeoff-ui/react-spar is not a drop-in replacement for v1. v1 uses Stencil-backed Tk* components and CustomEvent values; v2 uses React 19 components, compound children, and direct-value callbacks. Migrate one screen at a time and keep the two packages installed together until the remaining v1 usage is intentional.

For the product overview, component catalog, and current Takeoff UI resources, visit takeoffui.com.

React 19 required​

@takeoff-ui/react-spar throws at runtime on React 18. Upgrade react and react-dom before migrating the first component.

The migration skill ships in the package​

@takeoff-ui/react-spar 0.5.0 and newer ship the migration skill inside the package, so there is nothing to clone and no script to install:

ls node_modules/@takeoff-ui/react-spar/agents/migrate-takeoff-v1/

SKILL.md is the entry point; references/ holds the inventory commands, the v1-to-v2 component map, the prop and event translation, the one-time setup, the recurring patterns, and the known coverage gaps.

This migration is AI-assisted: the assistant takes the inventory, applies the one-time package, provider, and CSS setup, migrates screens, and runs the validation. You review each diff and make the product decisions. The component-specific v2 skills remain the API authority for props, slots, and accessibility.

AI-assisted migration​

1. Point the assistant at the skill​

Open the consumer repository in Chat or Agent mode. Either give the assistant the skill path directly, or copy it next to the guidance it already loads:

mkdir -p .agents/skills
cp -R node_modules/@takeoff-ui/react-spar/agents/migrate-takeoff-v1 \
.agents/skills/migrate-takeoff-v1

2. Inventory and prepare​

Send the request below. The assistant should run the inventory commands from references/inventory.md, read the results, install v2 beside v1, and apply the provider and token CSS setup when it is missing.

Read node_modules/@takeoff-ui/react-spar/agents/migrate-takeoff-v1/SKILL.md and
migrate the React app at ./src from @takeoff-ui/react v1 to
@takeoff-ui/react-spar v2. Start with the inventory in references/inventory.md.
If the v2 packages, provider, or token CSS are missing, apply the one-time setup
before editing a screen. Keep v1 and v2 installed together.

The inventory is a set of rg searches you can also run yourself:

node -p "require('react/package.json').version"
rg -n "@takeoff-ui/(react|core|tailwind)" src
rg -o --no-filename "(^|[^A-Za-z0-9_\$])<Tk[A-Z][A-Za-z0-9]*" src \
| grep -oE "<Tk[A-Za-z0-9]*" | sort | uniq -c | sort -rn
rg -o --no-filename "\bonTk[A-Z][A-Za-z0-9]*" src | sort | uniq -c | sort -rn
rg -n "<tk-[a-z0-9-]+" src

They report, in order: the React version actually installed, every v1 import, the Tk* components ranked by blast radius, the onTk* handlers to translate, and any raw <tk-*> custom elements. rg honours .gitignore, so node_modules and build output stay out of the counts. A React major below 19 is a blocker — @takeoff-ui/react-spar throws at runtime on React 18.

3. Migrate screens and validate​

Continue in the same Agent session with a bounded route or screen:

Migrate the /settings screen from the v1 inventory. Read each target component's
v2 API docs before editing, run focused typecheck/tests, and report changed files
and unresolved gaps.

The order of leaf controls and compound parents is an internal implementation choice for the assistant, not a separate manual setup step.

Keep @takeoff-ui/react, @takeoff-ui/core, and @takeoff-ui/tailwind installed while screens still use them, and do not remove the v1 packages until the remaining usage and gaps have been reviewed.

Decide coverage gaps​

The gap list below describes the current v2 release, not a permanent product boundary. These areas are candidates for future v2 components and will be closed incrementally in later releases as their React API, accessibility behavior, design-token recipes, and documentation are completed. Keep the v1 implementation or an app-local replacement in place for now, then revisit the decision when the corresponding v2 component is shipped.

The following v1 components have no shipped v2 target:

TkAvatar, TkAvatarGroup, TkCarousel, TkChart, TkColorPicker, TkCurrencyInput, TkEditor, TkGanttChart, TkOrgChart, TkPagination, TkPhoneInput, TkRating, TkTimeline, TkTimelineItem, and TkTreeView.

For each usage, choose one of these explicitly:

  • keep the v1 component beside v2;
  • build an app-local replacement;
  • defer migration for that screen.

Table includes pagination for migrated tables, but standalone TkPagination is still a gap. TkDatepicker is no longer a gap, but it is not a rename either: v2 ships no DatePicker component by decision, and a date field is Popover + Calendar composed in your own component, with the useDatePicker hook for a typable field. Core's tk-datepicker prop surface is not reproduced — dateFormat, headerType, allowApplyButton, footerType, inline and the time-picker props have no v2 equivalent — so treat each date field as a rewrite and keep v1 where a screen depends on time selection. For TkTextarea, use the v2 Input compound component with <Input.Field as="textarea" rows={...} />; the Input skill is authoritative for the supported props and accessibility behavior.

When a gap closes, the migration map and the component's own v2 skill become the source of truth. The inventory commands keep identifying any remaining gap usage so teams can migrate without a breaking package-wide switch.

Verify and remove v1​

After each screen, run the consumer's typecheck and focused tests. Exercise keyboard behavior, controlled values, validation, overlays, and light/dark mode. Then rerun the inventory, plus the styling checks:

rg -n "@takeoff-ui/[^\"']*\.css" src
rg -n "containerStyle" src

Remove @takeoff-ui/react, @takeoff-ui/core, and @takeoff-ui/tailwind only when React is 19 or newer and the searches report no remaining v1 imports, Tk* JSX, raw tk-* elements, or v1 styling dependencies outside the gap allowlist. --tk-* custom properties are v2 token names, not v1 leftovers — v1's own tokens are unprefixed, which is why the stylesheet import is the reliable signal. The full criteria live in references/inventory.md inside the skill.