Recommended preparation

Component API Design for Frontend Interviews: Props, Events, and Trade-offs

A practice-first map for designing component contracts under frontend interview time pressure.
22 minuiapi-designreactcompositioninterviews

Use this component API design interview practice map to define React props, events, a decision matrix, interactive API surface trade-offs, TypeScript guardrails, library patterns, accessibility contracts, styling surfaces, and drill-reviewed follow-ups.

Menu
On this page
Last updated: June 2026 | Author: FrontendAtlas Team | Reviewed by FrontendAtlas

Component API design is the contract between your UI component and the engineers who consume it. In frontend interviews, the answer is not just the JSX that renders; it is the React props, events, slots, state ownership, accessibility, styling, and escape hatches you choose not to expose.

Use this as a frontend component API design interview practice map. Start from a familiar component prompt, name the API contract, ship the MVP, then explain the trade-offs that would make the component scale in a team codebase.

Quick answer: how to design a component API

Start by naming the consumer and the state owner. Then define the props/events, composition model, accessibility contract, styling surface, and the escape hatches you are intentionally leaving for follow-up.

  • Consumer: who uses the component, and what behavior must they control?
  • State ownership: controlled, uncontrolled, or both through value/defaultValue callbacks.
  • Props/events: public inputs and domain events with useful payloads.
  • Composition: simple props, children, slots, or compound components.
  • Accessibility and styling: labels, keyboard paths, focus policy, variants, className, and CSS variables.
  • Score signal: clear contract, small MVP, explicit trade-offs, and no unnecessary escape hatches.
500+practice questions
Component APIdrills
Liveeditor + checks
Props/events/a11ycontracts

How this guide was reviewed

This guide is maintained by FrontendAtlas and reviewed against our UI component drill set, live coding editor checks, interview blueprint scoring rubrics, and official component library patterns. Use it as a timed decision checklist, not as a generic React API pattern list.

Component API decision matrix

Move left to right before coding: each step narrows the public API and gives the interviewer a scoreable decision.
  1. 1Consumer needWho calls this component, and what must they control?
  2. 2State ownershipParent-owned, local, or both through value/defaultValue.
  3. 3Composition modelSimple props, children, named slots, or compound components.
  4. 4Event payloadDomain event with value, item, reason, or context.
  5. 5A11y and stylingLabels, keyboard behavior, focus policy, variants, and tokens.
  6. 6Escape hatchRef, asChild, slotProps, or render hook only when needed.

Try the API surface trade-off

Toggle the same button prompt through three API surfaces. The strongest answer is not always the most flexible one; it is the API that matches the consumer and round scope.

<Button>
  <DownloadIcon aria-hidden="true" />
  Export CSV
</Button>

Interviewer signal: The caller owns custom content while the component keeps button semantics and focus behavior.

Risk: Composition needs clear a11y guidance so callers do not pass confusing markup.

Component API design patterns interviewers ask about

These prompts expose different API decisions: controlled state, composition, event payloads, a11y contracts, styling hooks, and when to keep the surface area small.

DialogA11y

Public surface: open, defaultOpen, onOpenChange, title, description, actions.

Trade-off/test focus: controlled vs uncontrolled, focus restore, Escape policy, slots.

TabsState

Tabs

State model: value, defaultValue, onValueChange, item ids, disabled tabs.

Trade-off/test focus: roving tabindex, tabpanel linkage, controlled active value.

DisclosurePolicy

Accordion

State model: type, value, defaultValue, collapsible, onValueChange.

Trade-off/test focus: single vs multiple sections, button semantics, disabled items.

ComboboxAsync

Autocomplete / Combobox

Consumer API: inputValue, selectedValue, onInputChange, onSelect, renderOption.

Trade-off/test focus: async states, stale responses, keyboard selection, option identity.

FormsValidation

Contact Form

Props/events: field schema, validation timing, onSubmit(values), errors, disabled submit.

Trade-off/test focus: controlled fields, accessible errors, submit lifecycle.

TablePagination

Data Table / Pagination

Consumer API: rows, columns, page, pageSize, onPageChange, empty state.

Trade-off/test focus: derived rows, page bounds, cell renderers, table semantics.

TableColumns

Dynamic Table

Public surface: column descriptors, accessors, header labels, fallback renderers, stable row keys.

Trade-off/test focus: typed columns, missing values, sort follow-up, prop explosion.

TreeSelection

Nested Checkbox Tree

State model: nodes, selected ids, onCheckedChange(ids), indeterminate state, disabled nodes.

Trade-off/test focus: parent-child sync, controlled selection, reset, traversal cost.

InputRating

Star Rating

A11y contract: value, max, readOnly, onValueChange, labels.

Trade-off/test focus: hover preview vs committed value, keyboard input, a11y names.

StatusFeedback

Progress Bar

A11y contract: value, min, max, threshold colors, label, reduced motion.

Trade-off/test focus: bounded values, ARIA progressbar, theme hooks, animation policy.

Component API decision framework

Controlled vs uncontrolled

Name state ownership first: value/defaultValue/onValueChange for value state and open/defaultOpen/onOpenChange for visibility state.

  • Controlled when parent coordinates validation, URL state, analytics, or reset.
  • Uncontrolled when the widget is isolated and interview time is tight.
  • Decision tree: if another component needs the state, lift it; otherwise keep it local and expose a controlled mode as follow-up.

Composition vs configuration

Prefer children, named slots, or compound components when content shape changes; use simple props when the API is stable.

  • Prop explosion is a smell when every new layout needs another boolean.
  • Compound components work well for Modal, Tabs, Accordion, and Menu prompts.
  • Configuration is fine for small variants like size and variant.

Event naming and payloads

Use domain events instead of raw DOM events: onSelect({ value, item, reason }) is easier to consume and test than leaking click details.

  • Name events by state change: onValueChange, onOpenChange, onPageChange.
  • Include enough payload for analytics, undo, validation, or async follow-up.
  • Keep the raw event optional unless the interviewer asks for it.

Styling surface

Expose variant, size, className, and CSS variables when they map to real design-system needs.

  • Use enums for known visual choices; avoid many boolean styling props.
  • Expose CSS variables for theme values like colors, radius, and spacing.
  • Do not make every internal element individually styleable in the first pass.

Escape hatches

Mention ref, asChild, slotProps, and render hooks as follow-ups, not as the first API surface.

  • Use ref for focus and integration with forms or popovers.
  • Use slotProps only when consumers need targeted internal element control.
  • Avoid over-abstracted state reducers unless the prompt asks for library-grade APIs.

Accessibility as API

Treat labels, ids, ARIA linkage, keyboard expectations, focus restore, and focus trap as part of the public contract.

  • Expose labels and descriptions instead of hardcoding anonymous controls.
  • State keyboard behavior before coding: Escape, Arrow keys, Enter, Tab order.
  • Call out focus restore/trap policy for dialogs, popovers, and menus.

Weak vs strong component API

Interviewers can usually tell whether you are designing from the consumer's point of view. A weak API adds one prop for every request. A stronger API names ownership, gives consumers a composable slot, and keeps events meaningful.

Practice note from FrontendAtlas drills: in timed component API drills, weak answers often add one prop per requested variation. Stronger answers first name state ownership, composition boundaries, and event payloads, then keep the initial API small enough to implement.

PromptWeak API smellStronger API moveInterview signal
Button iconiconName, iconSize, iconColor, onIconHover.Accept icon, renderIcon, or a named slot so the caller owns custom icon behavior.You avoid prop explosion and let composition handle flexible content.
Modal actionsprimaryText, secondaryText, danger, and many footer booleans.Expose header/body/footer slots plus open/defaultOpen/onOpenChange for state ownership.You separate structure from state and keep destructive flows controllable.
Data Table columnsHardcoded field names, hidden sort rules, and one-off formatting props.Use column descriptors with accessors, headers, fallback renderers, and stable row keys.You make the API reusable without turning it into a generic grid library.

TypeScript API guardrails

TypeScript should make invalid component states harder to express, not make the interview answer feel like a type puzzle. Use types to protect the public surface, then move back to behavior, accessibility, and trade-offs.

GuardrailUse it whenExample shapeInterview caution
Mirror native propsA component wraps a real DOM element like button, input, or anchor.ComponentPropsWithoutRef<'button'> plus your own variants.Omit conflicting props before adding custom names like size or variant.
Controlled/uncontrolled unionThe component supports both parent-owned and local state.{ value; onValueChange } | { defaultValue? }.Explain the contract; do not spend the whole round perfecting utility types.
Mutually exclusive propsTwo props should not be valid together.{ href: string; onClick?: never } | { onClick: () => void; href?: never }.Use this for important invalid states, not for every minor visual option.
Discriminated unionsVariants have different required payloads.{ type: 'link'; href } | { type: 'button'; onClick }.Name the runtime behavior each branch changes.
Ref forwardingConsumers need focus, measurement, forms, popovers, or composition.forwardRef<HTMLButtonElement, ButtonProps>.Mention it as an integration point, then return to the core prompt.

Library patterns interviewers recognize

You do not need to copy a library API in an interview, but referencing familiar patterns shows that your design choices match real component systems.

The official docs below are references for the pattern vocabulary; adapt the pattern to the prompt, consumer, and timebox instead of copying a full library surface.

PatternWhat it solvesRiskInterview takeaway
React controlled/uncontrolled Lets the caller choose parent-owned state or simple local state.Supporting both can double edge cases if naming is inconsistent.Use value/defaultValue/onValueChange and state who owns the source of truth.
Radix asChildComposes primitive behavior onto a caller-provided element.The child must spread props, forward refs, and remain accessible.Great follow-up for design systems, not the first API for a small interview MVP.
MUI slotPropsGives targeted control over internal elements without many top-level props.Can expose too much internal structure too early.Use when consumers need stable subpart customization.
React Aria hooks Encodes accessibility behavior while you own rendering.Still requires correct labels, relationships, and state wiring.Separate behavior contracts from visual composition.
Headless UI render props Exposes state like active, selected, open, or disabled to custom markup.Render props can get noisy when simple children would be enough.Use when visual control matters more than fixed markup.

Worked examples: API contracts interviewers can score

Modal/Dialog API

Contract: open/defaultOpen/onOpenChange, title, description, slots for header/body/footer, focus restore, Escape policy, and an explicit a11y contract.

  • Use controlled open state when parent owns destructive action flow.
  • Use slots when footer actions vary across confirm, alert, and custom dialogs.
  • Practice: Modal / Confirm Dialog.

Tabs API

Contract: controlled active value, item ids, onValueChange, disabled tab policy, roving tabindex, and linked tabpanel ids.

  • Use stable string ids instead of array indexes when panels can reorder.
  • Clarify whether disabled tabs are skipped by Arrow keys.
  • Practice: React Tabs.

Autocomplete API

Contract: inputValue vs selected value, onInputChange, onSelect, async loading/error/empty states, stale response policy, and renderOption for custom rows.

  • Separate typed text from committed selection so clearing and editing are predictable.
  • Ignore stale responses or track request identity before rendering options.
  • Practice: React Autocomplete.

Minimal example: these two types show the difference between state ownership and domain event payloads. In an interview, write only enough shape to make the contract testable before implementing behavior.

type DialogProps = {
  open?: boolean;
  defaultOpen?: boolean;
  onOpenChange?: (open: boolean, reason: 'trigger' | 'escape' | 'confirm' | 'cancel') => void;
  title: string;
  description?: string;
  children: React.ReactNode;
};

type SelectEvent<T> = {
  value: string;
  item: T;
  reason: 'keyboard' | 'pointer' | 'programmatic';
};

45/60-minute component API round flow

  • Spend the first minutes clarifying consumers and state ownership.
  • Define the public surface before coding.
  • Use the final minutes to explain trade-offs and skipped escape hatches.
TimeMoveSignal
0-5 minClarify consumers, data shape, ownership, keyboard expectations, and required customization.You design for the caller, not just the demo.
5-12 minDefine contract: props, events, slots, state ownership, accessibility labels, and styling surface.Your API is explainable before implementation.
12-30 minShip MVP behavior with the smallest API that supports the prompt.You can implement without over-designing.
30-45 minAdd a11y/keyboard, event payloads, controlled mode, disabled/error/loading states.You know frontend correctness lives in contracts.
45-60 minExplain trade-offs, name follow-ups, and identify what you intentionally did not expose.You can reason like a component owner.

What interviewers score

  • Clear contract: props, events, slots, and ownership are named before complexity grows.
  • State ownership: controlled/uncontrolled decisions match the caller and prompt constraints.
  • Event payloads: domain payloads carry useful data and reasons without leaking internals.
  • A11y contract: labels, ids, ARIA linkage, keyboard paths, and focus behavior are explicit.
  • Styling surface: variants, size, className, and CSS variables are enough without exposing everything.
  • Trade-off narration: you can name the API you skipped and why it was not needed yet.

What to skip vs prioritize

  • Prioritize the contract, a11y, state ownership, event payloads, and one dry run.
  • Save compound components, render hooks, refs, and slot props for follow-up depth.
  • Skip theme engines, virtualization, global config, and library-grade APIs unless asked.
PriorityDo thisAvoid spending time on
PrioritizeClear contract, state ownership, event payload, a11y, styling surface, and a dry run.Inventing a generic component library before the prompt works.
Know lightlyCompound components, slot props, render hooks, refs, and escape hatches as follow-ups.Over-abstracted state reducers in the first implementation pass.
Skip unless askedTheme engines, polymorphic components, portals, virtualization, and global config systems.Excessive escape hatches that make the API harder to explain.

Choose your next practice format

Component API design FAQ

What is component API design?

Component API design is the way you define how another engineer consumes your component: props, events, slots, state ownership, accessibility labels, styling hooks, and escape hatches.

How do I practice component API design for frontend interviews?

Pick a real prompt like Modal, Tabs, Autocomplete, or Data Table. Name the API contract first, then implement the MVP, keyboard support, a11y contract, styling surface, and trade-offs.

What is the controlled vs uncontrolled component API pattern?

Say who owns the state. Controlled components receive state and callbacks from the parent; uncontrolled components manage local state but can expose defaults and change events.

When should I use compound components or slots?

Use compound components or slots when the content shape varies, such as Modal, Tabs, Accordion, Menu, or Table prompts. Use simple props for stable, small choices.

How should component APIs expose events and accessibility?

Prefer domain payloads like onSelect({ value, item, reason }) instead of raw DOM events. Accessibility is part of the public API too: labels, ids, ARIA relationships, keyboard behavior, visible focus, and focus restore should be named in the contract.

How should TypeScript shape a component API?

TypeScript should make invalid component states harder to express. Use native prop mirroring, controlled/uncontrolled unions, mutually exclusive props, discriminated unions, and ref forwarding only where they clarify the public contract.

Which real library patterns help in component API interviews?

Useful patterns include React controlled/uncontrolled state, Radix asChild composition, MUI slotProps, React Aria hooks, and Headless UI render props. Use them as reference points, not as APIs to copy blindly.

How is this component API design guide reviewed?

FrontendAtlas reviews this guide against UI component drills, live coding editor checks, and interview blueprint scoring rubrics so the advice stays tied to timed interview execution.

How do I choose between prop-heavy, composed, and controlled component APIs?

Use a prop-heavy API only for a small stable surface, use composition when callers need custom content, and use controlled state when a parent must coordinate validation, analytics, reset, loading, or URL state.