CSS is Awesome

Migrating from Chakra UI

cia migrate chakra reads a Chakra UI (v2) theme object you already have and writes a starting cia theme.scss with the same real values — one CLI command, not a rewrite from scratch.

What this actually does

This is a token migration, not a component migration. It reads plain values off your extendTheme({...}) result — colors, spacing, border radii, fonts, font sizes — and maps them onto cia's own token contract. It never imports @chakra-ui/react and never touches your Chakra components — cia has no React component library to translate them to (see the recipes book for cia's actual framework story: copy-and-own patterns, not a component package). Migrating your component markup is a separate, manual step that happens after the theme is in place. Scoped to Chakra v2's theme shape — v2 is still the dominant version as of this writing; v3 changed the shape significantly and isn't handled here.

Usage

# writes ./cia-themes/migrated.scss
npx cia migrate chakra ./src/theme.ts

# name the output theme
npx cia migrate chakra ./src/theme.ts --name acme

# pipe-safe: dump the mapping + confidence report as JSON instead of writing a file
npx cia migrate chakra ./src/theme.ts --json | jq '.cia.report'

path is any module — .js, .ts, .mjs, .cjs — that exports a Chakra theme: a default export, a named theme export, or the result of extendTheme({...}) assigned directly. TypeScript files are loaded via jiti (no separate build step needed).

What gets mapped

Chakra's theme shape lines up closely with Tailwind's — colors is the same {shade: hex} palette-object shape, so the same color-mapping engine (and its brand/primary-named-primary, red/green/orange/blue-for-status heuristics) applies unmodified:

Chakracia tokenConfidence
colors.brand.500 (or primary/accent/theme)--action-primary-defaultHIGH
colors.red/green/orange/blue.500the matching --<status>-defaultMEDIUM
space.*the closest --space-N per entryvaries
radii.*the closest --radius-*varies
fontSizes.*the closest --font-size-Nvaries
fonts.heading--font-displayHIGH
fonts.body--font-sansHIGH

Not mapped: shadows.*, breakpoints.*, zIndices.*. None have a clean 1:1 cia analog — cia's shadow set is 5 named steps, and its breakpoints and z-layers are a fixed system scale, not themed per project. Each surfaces as one informational note rather than an arbitrary per-field guess.

Example

A Chakra theme with a brand color scale, a spacing customization, and a font:

// src/theme.ts
export const theme = extendTheme({
  colors: {
    brand: { 50: "#EEF1FC", 500: "#3A5FCD", 900: "#1A2C63" },
  },
  fonts: { heading: '"Inter", sans-serif', body: '"Inter", sans-serif' },
});

npx cia migrate chakra ./src/theme.ts writes:

// migrated theme — generated by `cia migrate chakra`
// Mapping confidence — HIGH: 3 · MEDIUM: 0 · LOW: 0 · UNMAPPED: 0

@use 'css-is-awesome/scss/mixins' as m;

@include m.theme('migrated') {
  --action-primary-default: #3A5FCD;
  --font-display: "Inter", sans-serif;
  --font-sans: "Inter", sans-serif;

  @include m.states(action-primary);
}

Next steps

  1. Review the file — MEDIUM/LOW/UNMAPPED entries are flagged inline, and a fresh migration will always be a partial theme: it only has the tokens your Chakra config actually defined. The rest of cia's 127 required tokens need filling in — see Authoring a theme for the full contract and the validator loop.
  2. @use the file from your app's SCSS entry, set <html data-theme="migrated">, and run your build.
  3. Run npm run validate-themes (or node scripts/theme-validator.js <your-file> on its own) to confirm WCAG 2.2 AA contrast once the required tokens are filled in.
  4. Migrate component markup separately, on your own timeline — see the recipes book for the patterns cia documents (dialog, combobox, data-table, forms, and more), each with real framework examples to adapt.

Further reading

Theme