← ALL NOTES
METHOD·2026.09·8 MIN READ
From a Figma Design System to a Code Component Stack
figma-apidesign-systems
The Problem

When I first started evaluating a frontend stack for a design-system pilot, I kept seeing the same group of names: Ant Design, Arco Design, Tailwind CSS, shadcn/ui, Radix UI, GSAP, Framer Motion, and Magic UI.

They all appeared in conversations about interface development, but they were not solving the same problem. Without separating their responsibilities first, it was easy to compare tools that were never direct alternatives in the first place.

The useful questions were more basic:

  • Which layer defines visual styling?
  • Which layer provides reusable components?
  • Which layer handles behavior, accessibility, or motion?

Claude Code helped me organize the ecosystem into those layers. I then mapped the structure back to the Figma component workflow I already understood and used that model to make the actual stack decision.

Start with Responsibilities

The ecosystem becomes much easier to understand when each tool is placed by responsibility.

LayerMain responsibilityExamples
Styling foundationAtomic styling utilities used to compose visual rulesTailwind CSS
Complete UI componentsReady-made buttons, inputs, dialogs, tables, and other interface componentsAnt Design, Arco Design, shadcn/ui
Unstyled behavior primitivesKeyboard interaction, focus, accessibility, and component behavior without prescribing appearanceRadix UI, Base UI
MotionTransitions, movement, timelines, and animation behaviorGSAP, Framer Motion
Visual-effect componentsMore presentation-oriented components for marketing and showcase interfacesMagic UI

The Figma analogy helped me keep the layers straight:

  • Tailwind is closer to individual properties such as spacing, radius, color, and typography;
  • a UI component library is closer to a ready-made Button / Primary / Large component;
  • Radix or Base UI provides the behavior behind focus, keyboard control, and open/close state;
  • a motion library defines how the component enters, leaves, or moves.

These layers can be used together. They are not one large category of competing UI tools.

Tailwind and Component Libraries Are Not Alternatives

This was the first distinction I needed to correct.

Tailwind does not give you a finished Button. It gives you atomic classes that can be combined into the color, spacing, radius, typography, and states of a button.

A component library packages those decisions into a reusable unit.

That is very similar to building a component in Figma: start with layout, fill, radius, and spacing, then save the result as a reusable component.

shadcn/ui makes this relationship especially visible. It provides components such as <Button>, but their visual styling is still composed from Tailwind classes.

So the more useful model is: Tailwind provides styling materials; a component library packages those materials into reusable components.

Once that distinction is clear, a question such as "Ant Design or Tailwind?" is no longer a meaningful comparison because the two tools operate at different layers.

Why shadcn/ui Worked as the Foundation

The most important property of shadcn/ui for this project was not its default visual style. It was its ownership model.

Traditional component libraries such as Ant Design or Arco are typically installed as dependencies. Teams customize them mainly through APIs and theme systems.

shadcn/ui takes a different approach: its CLI copies the component source code directly into the project repository. Once generated, those files can be read, modified, removed, or gradually adapted like any other project code.

That matters when the goal is to turn a company-specific Figma design system into a company-specific code component library.

I was not looking for a third-party design language that happened to look close enough. I needed a component foundation with mature interaction structure that could still be visually rebuilt around our own tokens and component rules.

In that sense, shadcn was a starting point rather than the design system itself.

Radix / Base UI Provide Behavior, Not Appearance

Looking inside more complex shadcn components also made another layer clearer: many of them rely on unstyled primitives such as Radix UI.

That layer handles things such as:

  • keyboard behavior;
  • focus management;
  • open and closed states;
  • accessibility;
  • interaction logic for more complex controls.

It does not decide the final radius, color, or typography.

This separation is useful for design-system work. The company can define its own visual system without rebuilding every accessibility and interaction behavior from scratch.

Changing an underlying primitive such as Radix or Base UI may affect implementation details, but it should not determine the final visual language by itself.

Where Ant Design and Arco Fit

Ant Design and Arco Design are strong choices when the main goal is to build dense enterprise interfaces quickly. They already include mature tables, forms, filters, and administration-oriented components.

For a product that can accept their design language and theme model, that level of completeness is a major advantage.

The trade-off is different when the goal is a highly independent company design system. Their component structures and default design decisions are more opinionated, so making the result feel completely unrelated to the original library can require more overriding.

That is why I did not choose Ant Design for this pilot. It was not a judgment that the library was worse; it was optimized for a different goal.

Arco was still useful as a reference because it maintains both Figma design resources and corresponding code components, which makes it a good example of design-system synchronization across design and development.

Motion Is a Separate Layer

GSAP and Framer Motion often appear in the same frontend discussions, but they do not replace a component or styling system.

They define how interface elements move.

Framer Motion is well suited to common UI transitions and state changes. GSAP is stronger when the interface needs complex sequencing or precise animation timelines.

A project can use shadcn/ui and Framer Motion together, or introduce GSAP only for more complex motion. The choice of component foundation does not remove the need for a motion layer.

From Figma to Code Components

Once the ecosystem was separated into layers, the relationship between a Figma design system and a code component library became clearer as well.

Figma defines things such as:

  • tokens;
  • component structure;
  • visual states;
  • sizing and composition rules.

Code components additionally need to handle:

  • real interaction state;
  • keyboard and focus behavior;
  • accessibility;
  • APIs;
  • integration with application logic.

The goal is therefore not to translate Figma into code one-to-one. It is to let design and code share the same design rules while allowing the implementation layer to use mature engineering primitives.

That is why the pilot ultimately used React + Tailwind CSS + shadcn/ui:

  • React for component structure and state;
  • Tailwind for styling composition;
  • shadcn for editable component foundations;
  • the company design tokens and component specifications for the final visual language.
Connecting Design Tokens to the Components

One practical issue appeared during implementation: shadcn expects its own semantic CSS variables, such as:

--primary
--muted
--accent

The tokens extracted from the Figma design system used company-specific names, for example:

--color-text-brand-primary

Instead of renaming the company tokens or modifying every component, the implementation added a thin mapping layer between the two naming systems.

For example, shadcn's --primary can point to the corresponding company token.

This keeps several responsibilities separate:

  • shadcn components can stay close to their original structure;
  • the company token set remains the single source of truth for visual decisions;
  • changes to the Figma token system can be handled primarily in the mapping layer instead of component by component.

The mapping also avoids treating a third-party component library's semantic names as if they were the company's design-token architecture.

Engineering Notes

Pilot stack: React + Tailwind CSS + shadcn/ui.

shadcn component source is copied into the repository rather than treated only as an opaque third-party package.

Company design tokens keep their own naming system and are mapped to shadcn semantic CSS variables through a thin bridge layer.

Complex component behavior can continue to use unstyled primitives such as Radix UI / Base UI, while the final appearance is defined by company tokens and component styles.

Takeaways
  1. Classify tools by layer before comparing them. Tools that solve different responsibilities should not be evaluated as direct alternatives.
  2. Separate styling, components, and behavior in a design-system architecture. Tokens, reusable components, and accessibility logic belong to different layers.
  3. Choose a component foundation based on how much visual ownership the product needs. Fast adoption of an established design language and building a highly customized company system are different goals.
  4. Figma and code do not need identical implementations. They need shared tokens, states, and component rules, while code can use the right engineering primitives underneath.
  5. Third-party semantic variables are not the same thing as company design tokens. A mapping layer reduces coupling between the component foundation and the design system.
About Learning with AI

The most useful role Claude Code played here was translating an unfamiliar frontend ecosystem into the Figma component model I already understood.

I still did not treat that translation as the final source of truth. After hearing that shadcn components were essentially normal component code styled with Tailwind utilities, I opened the generated Button source myself and verified that the structure was actually readable and editable.

That workflow has been useful for me: use AI to map an unfamiliar domain onto an existing mental model, then validate that model against the real code or product once before making decisions with it. The first step lowers the learning cost; the second makes the understanding reliable enough to use.

CONTINUE READING
Translating Figma Component Properties into Code Props2026.09Engineering a Figma Design System into Production Assets2026.09