Migrating to 1.0

One naming convention, applied everywhere. This is the list.

Why anything changed at all

1.0 is the last release in which a public prop can be renamed without a major version, so the eight inconsistencies the 0.x line had accumulated were fixed now rather than frozen forever. Each one below is a single-attribute rename. There are no behavioural changes hidden in this list.

Renamed props

// RadioGroup, OTPInput, TagInput - the DOM already owns onChange
- <RadioGroup onChange={setPlan} />
+ <RadioGroup onValueChange={setPlan} />

// Scheduler - verb names for actions
- <Scheduler onEventSelect={open} />
+ <Scheduler onSelect={open} />

// FAQ - every other defaultOpen in the library is a boolean
- <FAQ defaultOpen={0} />
+ <FAQ defaultOpenIndex={0} />

// EditableGrid - tabular row sets are 'data', matching DataTable
- <EditableGrid rows={lines} />
+ <EditableGrid data={lines} />

// PieChart, ProgressRing - 'size' is a sm/md/lg scale everywhere else
- <ProgressRing size={96} />
+ <ProgressRing diameter={96} />

// CTA - it was Section's background vocabulary under another name
- <CTA variant="primary" />
+ <CTA background="primary" />

// Text - one tone vocabulary: neutral | muted | primary | danger
- <Text tone="default" />
+ <Text tone="neutral" />

// Progress - the last widget that could render an unlabelled progressbar
- <Progress value={40} />
+ <Progress value={40} label="Upload" />

A project-wide find-and-replace on the left-hand side of each line is the whole migration. TypeScript reports every remaining site as a compile error, so nothing can be missed silently.

What arrived with it

None of these require a change, but each removes a workaround you may have written.

// asChild, where a router needs to get in
<DropdownMenu.Item asChild><Link href="/settings">Settings</Link></DropdownMenu.Item>
<PopoverTrigger asChild><Button variant="outline">Filters</Button></PopoverTrigger>
<IconButton asChild aria-label="Settings"><Link href="/settings">{gear}</Link></IconButton>

// size="lg" on Badge, Breadcrumb, Checkbox, Code, Field, FileUpload, Kbd, Label,
// RadioGroup, Switch and TypingIndicator - a large form now composes
<Checkbox size="lg" label="Remember me" />

// invalid on Switch and RadioGroup, like every other form control
<Switch invalid label="Notifications" />

// Navbar collapseAt, for a bar with six links and actions
<Navbar collapseAt="lg">...</Navbar>

The component contract

Every component now forwards its ref to its root element, merges an incoming className and style, and spreads the remaining props onto that root. Four data widgets - EditableGrid, FileTree, KanbanBoard and Scheduler - did not, so a test id or an inline style needed a wrapper element. Those wrappers can go. A test suite now keeps the contract true for every component.

Upgrading an existing app

Three commands and one search-and-replace pass. Nothing below is optional-but-nice: a renamed prop is silently ignored by the new version, so the compiler flags it only if you are on TypeScript. Run the typecheck.

npm install @the_viveksingh/vivek-ui@1.0.1
npx tsc --noEmit          # every renamed prop shows up here
npm run build

If the app is JavaScript, grep for the old names instead — the table above is the complete list, and every one of them is a distinctive string.

Give this to your coding agent

The whole upgrade is mechanical, which makes it a good task to hand over. Copy the prompt below into Claude Code, Cursor or whatever you use; it names every rename, so the agent does not have to guess.

Upgrade this project to @the_viveksingh/vivek-ui 1.0.1 from a pre-1.0 version.

1. Bump the dependency to ^1.0.1 and install.
2. Apply these prop renames wherever the component is used:
   - RadioGroup, OTPInput, TagInput: onChange -> onValueChange
   - Scheduler: onEventClick -> onSelect
   - FAQ: defaultOpen -> defaultOpenIndex
   - EditableGrid: rows -> data
   - PieChart, ProgressRing: size -> diameter
   - CTA: variant -> background
   - Text: tone="default" -> tone="neutral"
   - Progress: label is now required (describe what is loading)
3. Remove wrapper elements that existed only to attach a ref, className, style or
   test id to EditableGrid, FileTree, KanbanBoard or Scheduler - all four now
   forward the ref and merge className/style onto their own root.
4. Chart legends are interactive by default now. If a chart is a figure in a
   report rather than a dashboard control, pass interactiveLegend={false}.
5. ChatMessage and ChatThread format timestamps with explicit locale and timeZone
   props (defaults en-US and UTC). If you render them on a server, pass the
   viewer's values or a preformatted string - the old runtime-locale behaviour
   caused React hydration error #418.
6. Run `npx tsc --noEmit` and fix what it reports, then run the test suite.
Do not change anything else.

Optional, and worth doing once the upgrade is green: swap import '@the_viveksingh/vivek-ui/styles.css' for the per-component stylesheets described in Installation. A typical page drops from 34 kB of CSS to about 4.

Back to the introduction