Design System Interview Guide — React Ecosystem
A comprehensive guide covering core topics and famous interview questions for Design System interviews in the React ecosystem.
Table of Contents
- Core Topics
- Famous Interview Questions
- Must-Know Concepts
🎨 Core Topics
1. Component Architecture
- Atomic Design methodology — Atoms → Molecules → Organisms → Templates → Pages
- Compound components pattern — components that share implicit state (Tabs, Accordion, Select)
- Controlled vs Uncontrolled components
- Composition over configuration — build complex UIs by combining simple components
- Polymorphic components —
as prop to render any HTML element while keeping styles
Key patterns to know:
// Compound Component Pattern
<Select>
<Select.Trigger />
<Select.Options>
<Select.Option value="a">Option A</Select.Option>
<Select.Option value="b">Option B</Select.Option>
</Select.Options>
</Select>
// Polymorphic Component
<Text as="h1" size="xl">Heading</Text>
<Text as="p" size="md">Paragraph</Text>
<Text as="label" size="sm">Label</Text>
2. Design Tokens
Design tokens are the single source of truth for visual decisions — named variables that store design values.
Token tiers:
Global Tokens → color-blue-500: #3B82F6
↓
Alias Tokens → color-primary: {color-blue-500}
↓
Component Tokens → button-bg-color: {color-primary}
Key concepts:
- Color, spacing, typography, shadow, border-radius, z-index
- Naming conventions:
{category}-{property}-{variant}-{state}
- CSS variables vs JS tokens vs Tailwind config
- Multi-brand / multi-theme token architecture
- Tools: Style Dictionary, Token Studio (Figma plugin)
/* Global tokens */
--color-blue-500: #3B82F6;
/* Alias tokens */
--color-primary: var(--color-blue-500);
/* Component tokens */
--button-bg: var(--color-primary);
--button-bg-hover: var(--color-blue-600);
3. Theming & Styling
Styling approaches comparison:
| Approach |
Pros |
Cons |
Best For |
| CSS-in-JS (Emotion, Styled Components) |
Dynamic styles, colocation |
Runtime cost, larger bundle |
Highly dynamic theming |
| CSS Modules |
Zero runtime, scoped |
No dynamic styles |
Component isolation |
| Tailwind CSS |
Utility-first, small CSS |
Long class strings |
Rapid UI development |
| CSS Variables |
Native, runtime theming |
Limited to CSS values |
Multi-theme support |
Theme context pattern in React:
const ThemeContext = React.createContext('light');
function ThemeProvider({ theme, children }) {
return (
<ThemeContext.Provider value={theme}>
<div data-theme={theme}>{children}</div>
</ThemeContext.Provider>
);
}
// CSS Variables driven by data-theme attribute
[data-theme="dark"] {
--color-bg: #0f172a;
--color-text: #f1f5f9;
}
Dark mode approaches:
prefers-color-scheme media query — respects OS setting
data-theme attribute on <html> — user-controlled
- CSS variables — switch token values without JS re-render
4. Accessibility (a11y)
Every component in a design system must be accessible by default — consumers shouldn't have to think about it.
Key principles:
- Use semantic HTML first, ARIA only when needed
- Every interactive component must be keyboard operable
- All interactive elements need visible focus indicators
- Color alone should never convey meaning (use icons or text too)
- Test with real screen readers (NVDA, VoiceOver, JAWS)
ARIA patterns for common components:
// Modal
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
<h2 id="dialog-title">Confirm Action</h2>
</div>
// Custom Checkbox
<div role="checkbox" aria-checked={checked} tabIndex={0}
onKeyDown={handleKeyDown} onClick={toggle}>
{checked ? '✓' : ''}
</div>
// Live region for notifications
<div aria-live="polite" aria-atomic="true">
{notification}
</div>
Focus management rules:
- Modal opens → focus moves to first focusable element inside
- Modal closes → focus returns to the trigger element
- Tab key cycles only within open modal (focus trap)
- Route change → focus moves to page heading
5. Component API Design
The API is a contract with consumers — design it carefully because breaking changes are costly.
Props naming conventions:
- Use
on prefix for event handlers: onClick, onChange, onClose
- Use
is / has prefix for booleans: isDisabled, isLoading, hasError
- Use
default prefix for uncontrolled defaults: defaultValue, defaultOpen
- Prefer descriptive over clever:
variant="primary" not v="p"
Variants vs boolean props:
// ✅ Preferred — scales well, easy to document
<Button variant="primary" size="lg" />
<Button variant="secondary" size="sm" />
// ❌ Avoid — combinatorial explosion, hard to manage
<Button primary large />
<Button secondary small />
Ref forwarding — always do this in a design system:
const Button = React.forwardRef(({ children, ...props }, ref) => {
return (
<button ref={ref} {...props}>
{children}
</button>
);
});
Button.displayName = 'Button';
Prop spreading safely:
// Allow consumers to pass native HTML attributes
function Input({ label, error, className, ...rest }) {
return (
<div className={clsx('input-wrapper', className)}>
<label>{label}</label>
<input {...rest} aria-invalid={!!error} />
{error && <span role="alert">{error}</span>}
</div>
);
}
6. Documentation & Dev Experience
Good documentation is what separates a design system from just a component library.
Storybook story structure — every component should have:
Default — basic usage
Variants — all visual variants
Sizes — all size options
States — disabled, loading, error, success
Interactive — with Controls to tweak props live
Accessibility — keyboard nav demonstration
// Button.stories.jsx
export default {
title: 'Components/Button',
component: Button,
argTypes: {
variant: { control: 'select', options: ['primary', 'secondary', 'ghost'] },
size: { control: 'radio', options: ['sm', 'md', 'lg'] },
isLoading: { control: 'boolean' },
isDisabled: { control: 'boolean' },
},
};
export const Default = { args: { children: 'Click me', variant: 'primary' } };
export const Loading = { args: { children: 'Saving...', isLoading: true } };
export const AllVariants = () => (
<Stack>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
</Stack>
);
Documentation site essentials:
- Usage guidelines (do's and don'ts)
- Props table with types and defaults
- Code snippets ready to copy
- Figma embed alongside code component
- Changelog and migration guides
7. Versioning & Publishing
Semantic versioning:
MAJOR.MINOR.PATCH
2 . 1 . 3
MAJOR → Breaking change (rename prop, remove component)
MINOR → New feature, backward compatible (new variant, new component)
PATCH → Bug fix, backward compatible
What counts as a breaking change:
- Removing a component or prop
- Renaming a prop
- Changing a prop's type
- Changing default behavior
- Updating a peer dependency major version
Monorepo structure for publishing:
packages/
├── core/ → @myds/core (Button, Input, Modal...)
├── icons/ → @myds/icons
├── charts/ → @myds/charts
├── tokens/ → @myds/tokens
└── utils/ → @myds/utils
Release workflow:
- PR merged → automated
changeset added
- CI runs tests + visual regression
- Changesets bot opens a "Version Packages" PR
- Merge → auto-publishes to npm with correct semver bump
- Changelog auto-generated from changesets
8. Testing Components
Testing pyramid for a design system:
[Visual Regression] ← Chromatic / Percy (screenshot diffs)
[Accessibility Tests] ← axe-core / jest-axe
[Interaction Tests] ← Storybook play() / Testing Library
[Unit Tests] ← Jest + React Testing Library
Unit + interaction testing:
// Button.test.jsx
test('calls onClick when clicked', async () => {
const handleClick = vi.fn();
render(<Button onClick={handleClick}>Click</Button>);
await userEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledOnce();
});
test('does not call onClick when disabled', async () => {
const handleClick = vi.fn();
render(<Button isDisabled onClick={handleClick}>Click</Button>);
await userEvent.click(screen.getByRole('button'));
expect(handleClick).not.toHaveBeenCalled();
});
Accessibility testing:
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
test('Button has no accessibility violations', async () => {
const { container } = render(<Button>Submit</Button>);
expect(await axe(container)).toHaveNoViolations();
});
Visual regression with Chromatic:
- Every story becomes a screenshot test
- On every PR, Chromatic diffs screenshots against baseline
- Reviewers approve or reject visual changes
- Catches unintended CSS regressions automatically
Tree shaking — critical for design systems:
// ✅ Named exports — tree-shakeable
export { Button } from './Button';
export { Input } from './Input';
export { Modal } from './Modal';
// ❌ Barrel with * — can break tree shaking in some bundlers
export * from './components';
Avoiding re-renders in design system components:
- Use
React.memo for pure components
- Avoid creating new objects/functions in render inside context providers
- Keep ThemeContext value stable with
useMemo
// ❌ Creates new object every render → all consumers re-render
<ThemeContext.Provider value={{ theme, tokens }}>
// ✅ Stable reference → only re-renders when theme changes
const contextValue = useMemo(() => ({ theme, tokens }), [theme, tokens]);
<ThemeContext.Provider value={contextValue}>
CSS performance:
- Prefer CSS classes over inline styles
- Avoid deeply nested selectors
- Use CSS variables for runtime theming instead of JS-driven style recalculation
- Keep specificity low — design system styles should be easy to override when necessary
10. Governance & Adoption
Contribution models:
| Model |
How it works |
Best for |
| Centralized |
Core team owns everything |
Small orgs, strict consistency |
| Federated |
Product teams contribute, core team reviews |
Large orgs, many teams |
| Open contribution |
Anyone can PR, core team approves |
Open source design systems |
Driving adoption:
- Make it easier to use the DS than to build custom components
- Provide codemods for migrations
- Embed in starter templates and boilerplates
- Track adoption metrics (% of UI using DS components)
- Maintain a Slack/Discord channel for support
Handling one-off requests:
- Check if an existing component can be extended
- If it's a pattern seen in multiple places → add to DS
- If it's truly one-off → let product team own it locally
- Document the decision and revisit in next design system cycle
❓ Famous Interview Questions
Component Architecture Questions
- How would you build a Button component that supports variants, sizes, loading state, and icons?
- How do you implement the Compound Component pattern? Give an example with
<Select> or <Tabs>
- What is a polymorphic component? Build a
<Text as="h1" /> component in React
- How would you build a Form system with composable fields, labels, and error messages?
- What's the difference between controlled and uncontrolled components in a design system context?
- How do you design a Modal component that handles focus trap, scroll lock, and portal rendering?
- How would you implement a Tooltip that works with both mouse and keyboard users?
- Explain the difference between composition and configuration in component design
Design Tokens & Theming Questions
- What are design tokens and how do they differ from hardcoded values or SCSS variables?
- How would you implement a multi-theme system (light, dark, brand themes) in React?
- What is the difference between global tokens, alias tokens, and component tokens?
- How do you implement dark mode — CSS variables approach vs
data-theme vs Context API?
- How would you handle token scaling across multiple products / brands using one design system?
- How do you keep Figma tokens and code tokens in sync?
- What tool would you use to generate tokens for multiple platforms (web, iOS, Android)?
API Design Questions
- How do you decide when to use a single flexible component vs multiple specialized components?
- How would you design the props API for a
<Button> — what props would it accept and why?
- How do you handle prop forwarding and ref forwarding in design system components?
- What are the pros/cons of variants as strings (
variant="primary") vs boolean props (isPrimary)?
- How do you design a spacing system — what scale would you use and why (4px base, 8px base)?
- How do you handle style overrides — do you allow
className, sx prop, CSS variables, or none?
- How do you support responsive props like
<Box mt={{ sm: 2, md: 4, lg: 6 }}>?
Accessibility Questions
- How do you make a custom Dropdown/Select fully accessible (ARIA, keyboard, screen reader)?
- What ARIA attributes are needed for a Modal dialog component?
- How do you implement focus trapping inside a modal in React?
- How would you make a custom Checkbox accessible without using native
<input type="checkbox">?
- How do you test your component library for accessibility violations in CI/CD?
- How do you handle dynamic content announcements (toast notifications, live regions)?
- What is the roving tabindex pattern and when do you use it?
Styling Questions
- What are the trade-offs between CSS-in-JS vs CSS Modules vs Tailwind in a design system?
- How would you implement CSS variables-based theming in a React component library?
- How do you prevent CSS specificity conflicts when consumers use your components?
- How do you handle responsive styles within components in a design system?
- How do you ensure your components work correctly in SSR environments (Next.js)?
- What is the zero-runtime CSS-in-JS trend (Vanilla Extract, Linaria) and why does it matter?
Storybook & Documentation Questions
- How do you structure stories for a component — what scenarios should every component cover?
- How do you use Storybook Controls to make components interactive in documentation?
- How would you set up visual regression testing with Chromatic in a CI pipeline?
- How do you write usage guidelines (do's and don'ts) for a component?
- How do you keep documentation in sync with the actual component code?
- What is Storybook's play() function and how does it enable interaction testing?
Versioning & Distribution Questions
- How do you decide what is a breaking change in a component library?
- How do you manage multiple major versions of a design system across different consuming apps?
- How would you set up a monorepo to publish multiple packages (core, icons, charts)?
- How do you write a migration guide when introducing breaking changes?
- How would you use Changesets to automate versioning and changelog generation?
- What is peer dependency and how do you handle React as a peer dep in your library?
Real-World / Scenario Questions
- A product team says your Button doesn't support their use case — how do you handle it?
- How do you roll out a new major version without breaking 20 consuming apps overnight?
- How do you measure adoption of your design system across teams and products?
- A designer wants to introduce a new color not in the token system — what do you do?
- How do you convince engineers to use the design system instead of writing custom components?
- Your design system's bundle size is too large — how do you investigate and fix it?
- A team needs a component urgently that doesn't exist in the DS yet — what's your process?
🔥 Must-Know Concepts
| Concept |
Why It Matters |
React.forwardRef |
Pass refs to DOM elements inside DS components |
React.createContext |
Theme and token distribution across the tree |
| Compound components |
Flexible composition (Tabs, Accordion, Select) |
Polymorphic as prop |
Render any HTML element while keeping DS styles |
| CSS custom properties |
Runtime theming without JS re-renders |
| Storybook |
Documentation, visual testing, interaction testing |
| Semantic versioning |
Safe upgrades for all consuming teams |
| Radix UI / Headless UI |
Unstyled accessible primitives to build on top of |
| Style Dictionary |
Transform tokens to any platform (web, iOS, Android) |
| Changesets |
Automate versioning and changelogs in monorepos |
🏆 Top 5 Must-Practice Questions
These come up most frequently at companies like Google, Airbnb, Atlassian, Razorpay, and Swiggy:
- Button component design — variants, sizes, states, ref forwarding, accessibility
- Theming / dark mode — CSS variables, token tiers, React context
- Compound components — implement Tabs or Select with shared implicit state
- Accessibility of custom components — build an accessible Dropdown from scratch
- Breaking change strategy — how to version, communicate, and migrate consumers
📚 Real-World Design Systems to Study
| Company |
Design System |
Tech |
| Google |
Material Design / MUI |
React, Web Components |
| Airbnb |
DLS (Design Language System) |
React |
| Atlassian |
Atlaskit / Forge |
React |
| GitHub |
Primer |
React, CSS |
| Shopify |
Polaris |
React |
| IBM |
Carbon |
React |
| Adobe |
Spectrum |
React, Web Components |
| Razorpay |
Blade |
React |
🧩 Additional Questions — Deep Dive
Component Internals
- How would you implement a Toast / Snackbar system that supports stacking, auto-dismiss, and manual close?
- How do you build a Popover component that handles positioning, flipping, and collision detection?
- How would you implement a virtualized Dropdown that can handle 10,000 options without lag?
- How do you build a Stepper / Wizard component that manages step state and validation between steps?
- How would you implement a Command Palette (like VS Code's Ctrl+K) as a reusable component?
- How do you build an Accordion using the compound component pattern with animation support?
- How would you design a Table component that supports sorting, row selection, pagination, and sticky headers?
- How do you implement a Color Picker component that is fully keyboard accessible?
Tokens & Theming Deep Dive
- How would you design a token system that supports white-labeling for multiple enterprise clients?
- How do you handle component-level token overrides without breaking the global token system?
- How would you implement dynamic theming at runtime — for example, letting users pick an accent color?
- What is the token transformation pipeline and how does Style Dictionary fit into it?
- How do you ensure token parity between Figma and code — what is your sync strategy?
- How do you handle semantic color tokens for states like error, warning, success, info across themes?
- How would you structure tokens to support high contrast mode for accessibility compliance?
Styling Architecture
- What is zero-runtime CSS-in-JS (Vanilla Extract, Linaria, Panda CSS) and why is it gaining popularity?
- How do you handle the specificity war when consumers try to override your component styles?
- How would you design a
sx prop system (like MUI) that maps to CSS properties via tokens?
- How do you ensure your components don't leak global styles that affect consumer apps?
- How would you migrate a design system from Styled Components to CSS Modules with zero downtime?
- How do you handle animation tokens (duration, easing) and apply them consistently across components?
- What strategies do you use to reduce CSS bundle size in a component library?
State & Behavior
- How would you manage shared state between compound components without exposing it to consumers?
- How do you implement uncontrolled behavior with optional controlled mode in the same component?
- How do you handle keyboard shortcuts in a design system component (e.g., Escape to close, Enter to confirm)?
- How would you implement a context menu (right-click menu) that is accessible and positions correctly?
- How do you manage animation state in components like Accordion or Dialog (enter/exit transitions)?
- How would you build a drag-and-drop reorderable list as a design system component?
Testing Deep Dive
- How do you test a compound component where child components rely on parent context?
- How would you write tests for a Modal that checks focus trap and focus restoration?
- How do you test keyboard navigation in a complex component like a ComboBox or Menu?
- What is your strategy for mocking design system tokens in consumer app tests?
- How do you prevent visual regression across 200+ components without making CI too slow?
- How do you test components that use portals (Modal, Tooltip) rendered outside the component tree?
Monorepo & Infrastructure
- How would you set up a Turborepo for a design system with packages for core, icons, tokens, and utils?
- How do you handle peer dependency conflicts when multiple apps use different versions of your DS?
- How would you implement automatic changelog generation using Conventional Commits + Changesets?
- How do you set up Storybook with Module Federation so each team can have their own stories?
- How do you bundle a component library — what is your Rollup or Vite config strategy?
- How do you handle TypeScript declaration files (
.d.ts) when publishing to npm?
Governance & Culture
- How do you run a design system RFC (Request for Comments) process for new components?
- How do you handle a situation where two teams built the same component independently before your DS had it?
- How do you prioritize which components to build first in a new design system?
- How do you structure a design system team — what roles are needed (engineer, designer, PM)?
- How do you communicate deprecations to consuming teams without causing panic?
- How do you build a community of contributors around your design system internally?
- How do you define "done" for a component before it ships in the design system?
- How do you measure the bundle size impact of your design system on a consumer app?
- How would you implement on-demand imports so consumers only pay for what they use?
- How do you prevent context re-render cascades in a deeply nested theme provider?
- How do you optimize a design system component that uses CSS-in-JS for dynamic styles at scale?
- How would you implement font loading strategy as part of the design system setup?
- How do you handle icon performance — inline SVG vs sprite vs icon font vs image?
Quick-Fire Concept Questions
- What is the difference between
aria-label and aria-labelledby?
- When would you use
role="presentation" on an element?
- What is
React.cloneElement and when is it used in design systems?
- What is the render prop pattern and how does it compare to compound components?
- What is CSS containment and how can it help component isolation?
- What is the difference between
visibility: hidden and display: none from an accessibility standpoint?
- What is
inert HTML attribute and how does it help with modal accessibility?
- What is headless UI and how does it differ from a traditional component library?
- What is the difference between
tabIndex="0" and tabIndex="-1"?
- When would you use
React.createPortal in a design system component?
- What is color contrast ratio and what are the WCAG AA requirements?
- What is the
:focus-visible CSS pseudo-class and why is it preferred over :focus for design systems?
Last updated: April 2026