Acronis UIKit
Guides

Legacy → ui-react migration

Migrate from @acronis-platform/shadcn-uikit to @acronis-platform/ui-react with component mapping and codemod recipes.

Legacy → ui-react migration guide

This guide helps you migrate from:

  • @acronis-platform/shadcn-uikit (legacy)

To:

  • @acronis-platform/ui-react (next generation)

ui-react component ladder tracking

Docs coverage follows the ui-react ladder from context/roadmap.md (E2/E6). Use this checklist to keep docs work aligned with component rollout. ui-react currently ships 24 component modules (plus the cn class-merge helper), exported from packages/ui-react/src/index.ts:

  • Buttons & actions: Button, ButtonIcon, ButtonMenu, Link
  • Form inputs: Input, InputText, InputTextArea, InputSearch, InputSelect, InputDatePicker, Select (alias of InputSelect), Checkbox, Radio (+ RadioGroup), Switch
  • Search: Search, SearchGlobal
  • Display & feedback: Avatar, Tag, Tooltip, Breadcrumb
  • Layout & navigation: Resizable, SidebarPrimary, SidebarSecondary, CardFilter
  • Not yet shipped: overlay primitives (Dialog, Popover, Sheet), data display (Card, Table, DataTable, Chart), and the remaining composites/layout families tracked in context/roadmap.md.

When a component is shipped in ui-react, update this ladder section and the corresponding page in /docs/components/* in the same PR.

1) Switch package + styles

pnpm remove @acronis-platform/shadcn-uikit
pnpm add @acronis-platform/ui-react
// before
import '@acronis-platform/shadcn-uikit/styles';

// after
import '@acronis-platform/ui-react/styles';

2) Update imports

Legacy code usually imports components from @acronis-platform/shadcn-uikit/react. Move migrated components to @acronis-platform/ui-react.

// before
import { Button, Input, Switch } from '@acronis-platform/shadcn-uikit/react';

// after
import { Button, Input, Switch } from '@acronis-platform/ui-react';

3) Component mapping

The mapping below is based on current package exports.

Directly available in both packages

These keep the same name — only the import source changes.

Legacy (shadcn-uikit/react)ui-react
AvatarAvatar
BreadcrumbBreadcrumb
ButtonButton
CheckboxCheckbox
LinkLink
ResizableResizable
SelectSelect
SwitchSwitch
TagTag
TooltipTooltip

Renamed / split equivalents

ui-react standardizes form fields under an Input* namespace and splits the legacy sidebar into two components. Map these by name:

Legacyui-react equivalent
InputInputText
TextareaInputTextArea
DatePickerInputDatePicker
RadioGroupRadioGroup (from radio)
RadioGroupItemRadio
ButtonGroupButtonMenu
SidebarSidebarPrimary / SidebarSecondary

The bare Input export still exists in ui-react, but new code should prefer the explicit InputText field. ui-react also adds form fields with no direct legacy equivalent: InputSearch, InputSelect, Search, SearchGlobal, ButtonIcon, and CardFilter.

Not yet available in ui-react (keep legacy for now)

Accordion, Alert, AlertDialog, AppShell, AspectRatio, AuthLayout, Badge, Calendar, Card, Carousel, Chart, Chip, Collapsible, Combobox, Command, DashboardLayout, DataTable, Dialog, Drawer, DropdownMenu, Field, Filter, Form, Grid, Label, NavigationMenu, NumberField, PageContent, PageHeader, Pagination, Popover, Progress, ScrollArea, SecondaryMenu, Section, Separator, Sheet, Skeleton, Slider, Sonner, Spinner, SplitLayout, Stack, Table, Tabs, ToggleGroup, Tree, VisuallyHidden, Widget, WidgetAlert, WidgetPlaceholder, WidgetProgressChunks, WidgetProgressTiers, WidgetProtectionStatus, WidgetProtectionSummary, WidgetTableData, WidgetText.

4) Codemods (where viable)

Codemod A — import source rewrite

Create ./codemods/shadcn-to-ui-react-imports.cjs:

module.exports = function transformer(file, api) {
  const j = api.jscodeshift;
  const root = j(file.source);

  const fromLegacy = new Set([
    '@acronis-platform/shadcn-uikit/react',
    '@acronis-platform/shadcn-uikit',
  ]);

  root.find(j.ImportDeclaration).forEach((path) => {
    if (!fromLegacy.has(path.node.source.value)) return;
    path.node.source = j.stringLiteral('@acronis-platform/ui-react');
  });

  return root.toSource({ quote: 'single' });
};

Run it:

npx jscodeshift -t ./codemods/shadcn-to-ui-react-imports.cjs "src/**/*.{ts,tsx}" --parser=tsx

Codemod B — radio rename

Legacy RadioGroupItem maps to Radio in ui-react.

Create ./codemods/radio-group-item-to-radio.cjs:

module.exports = function transformer(file, api) {
  const j = api.jscodeshift;
  const root = j(file.source);

  root
    .find(j.ImportDeclaration, {
      source: { value: '@acronis-platform/ui-react' },
    })
    .forEach((path) => {
      path.node.specifiers?.forEach((specifier) => {
        if (
          specifier.type === 'ImportSpecifier' &&
          specifier.imported.name === 'RadioGroupItem'
        ) {
          specifier.imported.name = 'Radio';
          if (!specifier.local) specifier.local = j.identifier('Radio');
        }
      });
    });

  return root.toSource({ quote: 'single' });
};

Run it:

npx jscodeshift -t ./codemods/radio-group-item-to-radio.cjs "src/**/*.{ts,tsx}" --parser=tsx

⚠️ Keep mixed files on legacy imports if they still use legacy-only components or utilities/icons.

5) Manual follow-up checklist

  • Keep legacy package only for components not yet in ui-react.
  • Split mixed imports when needed:
import { Button, Input } from '@acronis-platform/ui-react';
import { Dialog, Popover } from '@acronis-platform/shadcn-uikit/react';
  • Re-test interactive components after migration (Select, RadioGroup, sidebars).
  • Verify style import points to @acronis-platform/ui-react/styles.

6) Migrating icons

Icons migrate independently of components. Legacy @acronis-platform/shadcn-uikit re-exports icons under Acronis names (EditIcon, CustomerIcon, SearchIcon); @acronis-platform/icons-react uses descriptive names on a different art grid (PencilIcon, BriefcaseIcon, MagnifierIcon), so names must be resolved authoritatively — not guessed.

The authoritative name map

icons-react ships the bridge as data — the @acronis-platform/icons-react/legacy-map export (legacy-icon-map.json), generated from the design-assets legacyNames bridge. It maps every legacy icon name to its icons-react name per pack variant, classifying each as:

  • mapped — safe 1:1 (with the name per variant, e.g. stroke-mono).
  • colored — exists only in a multicolor pack (baked-in status/brand color). No monochrome equivalent: keep it on a *-multi pack, or map to a mono base (CircleTimesIcon, TriangleWarningIcon, …) with a color className. Never silently flatten status color.
  • unresolved — logos/illustrations genuinely absent from the icon packs.

Because the map ships with the package, no monorepo checkout is needed — any app resolves names from its installed icons-react.

The migrate-icons skill

The repo ships a reusable, dependency-free skill at .claude/skills/migrate-icons/. Copy that folder into your app's .claude/skills/ (or run its scripts directly) to drive the migration off the shipped map:

# 1) Resolve — inventory your shadcn-uikit icon imports + build the map
TARGET=stroke-mono node .claude/skills/migrate-icons/scripts/resolve-map.mjs
#    writes .icon-migration/iconmap.json and prints the colored / unresolved triage

# 2) Triage — decide the colored / unresolved icons; add chosen entries to the map by hand

# 3) Apply — rewrite imports + JSX, dedupe collisions, hold the rest on legacy
MAP=.icon-migration/iconmap.json \
FROM=@acronis-platform/shadcn-uikit \
TO=@acronis-platform/icons-react/stroke-mono \
  node .claude/skills/migrate-icons/scripts/apply-icons.mjs

# 4) Verify — types + tests, then confirm only intended holds remain
npx tsc -b --noEmit && grep -R "@acronis-platform/shadcn-uikit" src

IconProps supports size/className/style, so size={16} and color overrides keep type-checking. Held and unresolved icons stay on the legacy package until you decide on them — icon migration never blocks on them.

7) Verify migration progress

# remaining legacy imports
grep -R "@acronis-platform/shadcn-uikit" src

# ui-react usage
grep -R "@acronis-platform/ui-react" src

A practical rollout is per feature/module: migrate files that use mapped components first, then keep the rest on legacy until their ui-react equivalents are available.

Edit on GitHub

On this page