skip to content

When a design system component's design-file properties cannot match its coded props one to one, how should the two be mapped?

level: middleimportance: should knowfreq 30%

answer

  1. public vocabulary, not internals
  2. design-only and code-only properties
  3. states: shown versus behaved
  4. slots and swappable nested parts
  5. write the mapping down

basics

~20 s

Match every shared decision: name, variants, sizes, booleans and content slots. Keep design-only properties, like preview toggles, and code-only ones, like event handlers, on one side, show runtime states as design variants, and document the mapping.

solid answer

~50 s

Parity is about the **decisions** a designer and an engineer both make, not about identical property lists. I'd sort properties into three groups. **Shared**: variant, size, tone, whether an icon is shown, the label text, and content slots; these get identical names and values on both sides. **Code-only**: event handlers, accessibility labels passed at runtime, test identifiers, controlled values; they have no meaning in a design file. **Design-only**: toggles that show example content or annotations, and interactive **states** such as hover, pressed and focus, which a design file shows as variants so they can be reviewed, while code produces them from behaviour. Where the shapes differ, such as a design editor's swappable nested component versus a code slot, I'd pick the same name for the slot and document it. The mapping lives on the component's documentation page, so nobody has to guess.

go deeper

for a junior

Recall that some properties exist only in code, such as event handlers, and some only in design files, such as preview toggles, and that shared ones must match.

for a middle

Explain the three groups of properties, how visual states differ from prop-driven states, and how slots and swappable nested parts map to each other.

for a senior

Show how you would write and maintain the mapping for a real component, and spot design-only toggles that are covering for a missing coded state.

for a principal

Decide how far the system should bend each medium to match the other, and when a documented difference is cheaper than forcing structural parity.

## Why one-to-one parity is impossible In a **design system**, a component exists in a **design-file library** and in a **coded library**. **Library parity** asks them to share names, variants and properties. But the two media do different jobs. A design file shows how a component **looks** in each situation; code defines how it **behaves** and how it connects to data. Some properties therefore exist on one side only, and some concepts take a different shape on each side. The goal is a deliberate, documented mapping, not an identical list. ## Three groups of properties | Group | Examples | Where it lives | Parity rule | |---|---|---|---| | **Shared decisions** | Variant, size, tone, show icon, label text, content slots | Both | Same names, same allowed values | | **Code-only** | Event handlers, controlled value, runtime accessible name, test identifier | Code | Documented, absent from design | | **Design-only** | Show example content, show annotation, device frame | Design file | Documented, absent from code | | **Visual states** | Hover, pressed, focus, disabled, loading | Variants in design; behaviour or props in code | Same state names on both sides | **Disabled** and **loading** are worth singling out: in code they are usually props a product sets, while hover, pressed and focus come from user interaction. Both kinds appear as design variants, but only the first kind should become a coded prop. ## Shapes that differ - **Slots versus swappable nested components.** Code often lets a consumer pass arbitrary content into a named region; a design editor typically offers a placeholder that can be swapped for another component. Give the region the same name on both sides, for example 'leading' and 'trailing', and list what the design side allows in it. - **Booleans versus enumerations.** A design file may have 'Has icon: yes/no' while code has 'icon: none | start | end'. Pick the richer model and mirror it: if code supports an end position, the design file needs it too, or designers cannot express it. - **Text content.** Designers edit label text directly; code takes it as a property. The name should match, such as 'label', even though the design side edits it in place. - **Responsive behaviour.** Code adapts to width at runtime; the design file may represent it as size variants or separate frames. Document which design variant corresponds to which breakpoint behaviour. ## An example: a claim document uploader In an insurance claims portal, claimants attach photos and receipts with an uploader component. 1. **Shared**: 'variant' (drop zone, compact button), 'state' of each file (uploading, uploaded, failed), 'label' and 'helper text', 'multiple' (one file or several). 2. **Code-only**: accepted file types, maximum size, the handler that uploads each file, the handler for retry. 3. **Design-only**: a toggle showing three example files in the list, so designers can review the filled state without building it by hand. 4. **States**: the drop zone's drag-over highlight is a design variant for review and an interaction in code; 'failed' is a real prop-driven state on both sides. The mapping is a short table on the uploader's documentation page. A new engineer can read a design, see 'variant: compact, multiple: yes, one file failed', and know exactly which coded props produce it. ## Keeping the mapping honest - Settle the shared property names in the **spec** before either side builds. - Treat a new shared property as a change to **both** libraries in the same piece of work. - Review design-only properties for **leakage**: if designers use a 'show example content' toggle to fake a real product state, the coded component probably lacks that state. - Revisit the mapping when either side's tooling changes what it can express, because a design editor gaining a feature can remove the need for a workaround.

  • Why show hover and focus as variants in the design file if code produces them from interaction?
    A design file cannot interact, so a state has to be drawn to be reviewed. Showing hover, pressed and focus as variants lets designers specify them and reviewers check contrast and clarity. They are documented as visual states, not as props, so engineers do not add a prop for something the component handles itself.
  • A design file uses 'Has icon: yes/no' but code supports icons at the start or end. What do you change?
    Mirror the richer model in the design file: an icon position property with none, start and end. Otherwise designers cannot express an end icon, engineers guess, and the difference between a boolean and an enumeration becomes a silent mismatch.

saying these in an interview costs you the question

  • Every coded prop, including event handlers, must appear in the design file.
  • Hover and focus should become props in code because they are design variants.
  • Design-only preview toggles mean the libraries are out of parity.
  • A boolean in design and an enumeration in code are close enough to leave alone.