ToggleButton → Button codemod

Migrates the removed ToggleButton component to Button. Button's prop surface is a superset of ToggleButton's — every ToggleButton prop (size, isActive, icon, iconPosition, isIconOnly, onClick, href, unsafe_iconSize, unsafe_iconColor, isDisabled, as, className, …) exists on Button with the same meaning — so this is a straight rename.

// Before
<ToggleButton icon="check" isActive>Bold</ToggleButton>

// After
<Button variant="tertiary" icon="check" isActive>Bold</Button>

The codemod renames the import and tag and adds variant="tertiary" — the closest match to the old ToggleButton look — unless the element already sets a variant. All other props/attributes pass through unchanged.

Running it

Run it through the Pluma CLI from inside your consuming app. Always start with a dry run to review the diff before applying:

# from the root of your consuming app

# Dry run first (no writes; per-file diff printed inline)
pnx @customerio/pluma-cli@latest upgrade --codemod toggle-button-to-button react --dry ./src
pnx @customerio/pluma-cli@latest upgrade --codemod toggle-button-to-button ember --dry ./app

# Then apply for real
pnx @customerio/pluma-cli@latest upgrade --codemod toggle-button-to-button react ./src
pnx @customerio/pluma-cli@latest upgrade --codemod toggle-button-to-button ember ./app ./addon

Both frameworks accept --dry / -d. The React path also forwards standard jscodeshift flags.

What gets matched

React. JSX elements whose tag resolves (via the import in the same file) to ToggleButton from @customerio/pluma-components/react (or the bare @customerio/pluma-components entry). The import specifier is rewritten to Button (deduped if Button is already imported), and aliased imports (import { ToggleButton as X } from …) are handled. A local component named ToggleButton that wasn't imported from Pluma is left alone, and pre-existing Button usages are untouched.

Ember. <PlumaToggleButton …> element nodes in .gts/.gjs/.hbs templates are rewritten to <PlumaButton …>. In strict-mode .gts/.gjs files the named import is renamed too (deduped if PlumaButton is already imported); classic .hbs templates resolve the component globally and need no import change.

Review after running

The rename is mechanically safe, but review two things:

  • variant. The codemod defaults to variant="tertiary". Pick a different variant (secondary, primary, …) where that reads better for the context.
  • Active state. ToggleButton bolded its label text when isActive; Button instead changes color (background/text) and does not bold. This is a small visual shift, not a behavior change.

Working on the codemod itself

The React transform is a bespoke jscodeshift transform; the Ember transform is built on @codemod-utils/ast-template and reuses the shared CLI runner under ../../_shared/. There's a test suite under tests/:

pnpm --filter @customerio/pluma-cli run test:transforms

It uses Node's built-in test runner (node --test).