Skip to content

Getting Started

Figma to code

Design files and code drift apart by default. What stops it is not tooling — it is agreeing on names, and agreeing on which side owns each decision.

Who owns whatPermalink to this section

Most handoff problems are ownership problems in disguise. When two sources both claim to be authoritative, they will disagree, and nobody will know which to trust.

DecisionOwned byWhy
Token valuesCodesrc/tokens is the source. The Figma library mirrors it, never the other way round.
Token namesSharedRenaming requires agreement on both sides — a name that only exists in one place is a future mismatch.
Component variantsSharedThe variant set is a contract. Adding one is a system change, not a file change.
Component statesCodeHover, focus, disabled and loading are behavioural. The implementation defines them.
Layout and compositionDesignHow components are arranged on a page is a design decision every time.
Interaction and motionCodeTiming and easing are tokens, applied by the components themselves.
Accessible namesSharedThe label a screen reader announces is content, and content is written, not styled.

Names match exactlyPermalink to this section

A token called brand-primary in code is called brand-primary in Figma. Not “Brand / Primary”, not “Purple 600” — the same string, so that a design annotation is directly actionable.

Figma variable

  • brand-primary
  • surface-raised
  • border-default
  • space-16
  • radius-lg

CSS custom property

  • --brand-primary
  • --surface-raised
  • --border-default
  • --space-16
  • --radius-lg

The test

Someone should be able to read a token name off a design file and search for it in the codebase. If that search fails, the naming has already drifted.

Reading a specPermalink to this section

A design file communicates intent. Translating it means mapping measurements back onto the nearest token, not reproducing them literally.

Spec says 22px

→ space-24

Dosnap to the nearest token

A 2px difference is invisible; an off-scale value is permanent technical debt that spreads by copy-paste.

Spec says 22px

→ padding: 22px

Don'treproduce measurements literally

One arbitrary value becomes ten as soon as the component is duplicated, and the scale stops meaning anything.

Spec valueNearest tokenUse
3px, 5pxspace-44px
14px, 18pxspace-1616px
22px, 26pxspace-2424px
#e96516brand-primary#c94e0c
11px radiusradius-md12px
200msduration-fast or duration-normal150ms or 240ms

If a spec value is genuinely between two tokens and the difference matters, that is worth a conversation — either the scale has a gap, or the design is making a distinction the system does not support yet. Both are useful things to find out.

What does not transferPermalink to this section

Some things exist only in code, and design files should not attempt to specify them.

  • Focus rings

    Applied globally by :focus-visible. A design file showing a custom focus treatment is describing a bug.

  • Hover and pressed states

    Defined by the component's variants. Redrawing them in Figma creates two sources of truth.

  • Loading states

    The spinner, the aria-busy attribute and the interaction blocking are behavioural.

  • Responsive collapse

    Which parts of the interface disappear at each breakpoint is documented in the layout foundation.

  • Reduced motion

    There is no static representation of an animation that has been removed.

  • Live regions

    Whether a change is announced is not visible in any design file.

Implementing a screenPermalink to this section

The order that produces the fewest surprises.

  1. Identify the componentsWalk the design and name every part using system component names. Anything that has no name is either a composition of existing components or a gap worth raising before any code is written.
  2. Build the structure with real semanticsHeadings in order, lists as lists, buttons as buttons. Getting this right first is far cheaper than retrofitting it after the styling looks correct.
  3. Apply spacing from the scaleMap every measurement to the nearest step. Flag anything that will not snap.
  4. Compose components, do not restyle themIf a component needs to look different, that is a variant request. Overriding a component's internals with className is how a design system stops being one.
  5. Check the states the design did not showEmpty, loading, error, long content, and the narrowest supported width. Design files almost never include all five.
  6. Run the accessibility checklistKeyboard path, focus order, labels, contrast, reduced motion. The list is on the accessibility foundation page.

Annotating a designPermalink to this section

What to write on a design file so that implementing it does not require a meeting.

Design note
Component:  Button
Variant:    destructive
Size:       md
Icon:       Trash2 (leading)
Label:      "Delete workspace"

Behaviour:  Opens the delete confirmation dialog.
            Does not delete directly.

Empty:      n/a
Loading:    While the delete request is in flight,
            loading={true} — label stays visible.
Error:      Failure message appears above the dialog
            footer; the dialog stays open.

A11y:       Dialog title names the workspace.
            Cancel receives initial focus.

Keeping the library in syncPermalink to this section

The Figma library mirrors the code, and the sync runs in one direction only.

  1. A token change lands in src/tokens and ships in a release.
  2. The release notes list every changed token by name.
  3. The Figma variables are updated to match, in the same week, by whoever owns the library.
  4. A component's variant set changes only through the contribution process — never directly in Figma.
  5. Anything present in Figma but absent from code is marked as exploratory, so it is never mistaken for a spec.

One direction, always

When a designer changes a variable in Figma and the code is not updated, the file becomes a proposal rather than a specification — and the next person to implement from it will build the wrong thing. Token changes start in code.