Articles
UI Coding Interview Guide: Components, State, Accessibility, and Testing
Prepare for UI coding interviews with a practical framework for component design, minimal state, accessibility, edge cases, and behavior-focused testing.
You finish a polished autocomplete with two minutes left. Mouse clicks work, the colors look right, and the data filters correctly. Then the interviewer presses ArrowDown, Enter, and Escape. Nothing behaves as expected.
That is the trap in many UI coding interviews: the visible component is only the surface. Interviewers are also evaluating how you model behavior, decide where state belongs, preserve keyboard and focus semantics, test the user contract, and explain what you would improve with more time.
This guide gives you a repeatable workflow for turning those prompts into a small, complete, defensible UI.
A strong UI coding solution connects a clear component model to observable, accessible behavior.
Quick Verdict
Build the smallest complete experience, not the largest feature set. Clarify the behavior, define minimal state, ship the happy path, add the keyboard and focus contract, test the highest-risk interactions, and narrate any deliberate trade-offs.
A strong candidate can answer four questions at any moment: What is the user doing? Which component owns that behavior? What state is the source of truth? How will I prove it works?
Framework fluency matters, but a finished accordion with semantic buttons, correct state, keyboard operation, and two meaningful tests is usually a better interview artifact than an elaborate component with fragile behavior.
What Is a UI Coding Interview?
A UI coding interview is a timed implementation round where you build an interactive component or small product surface in a browser. The prompt might be an autocomplete, tabs, modal, data table, carousel, file explorer, or toast system.
Atlassian's published Frontend Engineering Interview Guide, for example, describes browser coding as building a simple interactive interface in a runnable environment. Its 60-minute coding rounds assess code quality, conceptual thinking, communication, and testing. Formats vary by company, so treat your recruiter instructions as the source of truth.
| Round | Primary deliverable | Main question |
|---|---|---|
| DSA coding | Correct algorithm | Can you reason about data structures and complexity? |
| UI coding | Working interactive component | Can you turn product behavior into usable code? |
| Frontend system design | Architecture and trade-offs | Can you design a larger frontend system? |
| Take-home | Reviewable repository | Can you deliver a polished solution with more time? |
For architecture-only rounds, use the Front-End System Design Interview Guide.
What Interviewers Score
| Signal | Strong evidence | Common miss |
|---|---|---|
| Behavior | Core interactions and edge states work | Optimizes styling before functionality |
| Components | Boundaries follow responsibilities and data flow | One giant component or premature abstraction |
| State | One source of truth with derived values calculated | Duplicated state drifts out of sync |
| Accessibility | Semantic controls, keyboard behavior, visible focus | Mouse-only interaction with decorative ARIA |
| Testing | Tests observable behavior and risky transitions | Tests implementation details or skips verification |
| Communication | Clarifies assumptions and explains trade-offs | Codes silently until time expires |
A 55-Minute UI Coding Interview Plan
| Time | Action | Visible output |
|---|---|---|
| 0-5 min | Clarify behaviors, data, constraints, and priorities | Short acceptance contract |
| 5-10 min | Sketch components, state, and key events | Simple implementation map |
| 10-30 min | Build the semantic happy path | Working mouse and basic keyboard flow |
| 30-40 min | Add focus behavior and loading, empty, and error states | Complete interaction states |
| 40-50 min | Test the highest-risk user journeys | Two or three behavior tests |
| 50-55 min | Run, review, and explain remaining trade-offs | Clean demo and prioritized follow-ups |
This is a practice framework, not a universal company schedule. If the interviewer gives you 40 minutes, compress styling and secondary edge cases before sacrificing the core user contract.
Keep the loop visible: clarify, model, build, make accessible, test, and explain.
Case Study: Build an Accessible Autocomplete
Autocomplete is an excellent practice problem because a small visual surface hides meaningful decisions about component boundaries, state, asynchronous data, keyboard navigation, focus, and testing.
The component contract should describe behavior before it describes implementation.
1. Clarify the Behavior Contract
Before coding, ask whether data is local or remote, whether free-form text is allowed, when suggestions open, whether the first result becomes active automatically, and what selection should do. Then confirm the priority order if time runs short.
| Area | Agreed behavior |
|---|---|
| Input | Typing filters city suggestions |
| Pointer | Clicking an option selects it and closes the popup |
| Keyboard | Arrows move the active option; Enter selects; Escape closes |
| States | Loading, no results, and request failure are distinguishable |
| Accessibility | The input has a visible label and exposes popup state |
| Test | Typing, keyboard selection, and dismissal are verified |
2. Choose Component Boundaries
Start with one owner, such as Autocomplete, that coordinates input, popup state, active option, and selection. Extract OptionsList or Option when a child has a coherent responsibility, repeated markup, or a useful prop contract.
Do not split every div into a component. An interviewer wants readable ownership, not the highest component count. Keep rapidly changing local UI state near the smallest subtree that needs it.
3. Model Minimal State
const [query, setQuery] = useState("");
const [isOpen, setIsOpen] = useState(false);
const [activeIndex, setActiveIndex] = useState(-1);
const [selectedId, setSelectedId] = useState(null);
const visibleOptions = options.filter(option =>
option.label.toLowerCase().includes(query.toLowerCase())
);
query, isOpen, activeIndex, and selectedId represent independent user-visible decisions. visibleOptions is derived from existing inputs and does not need another state setter.
React's state-structure guidance recommends avoiding redundant and duplicated state because synchronized copies create more ways for the UI to become inconsistent. Also reset activeIndex deliberately when the query or result set changes so it never points beyond the list.
4. Build Semantics Before Decorative ARIA
Use native elements for native behaviors: a real label, input, and button. MDN's ARIA guidance says to prefer the correct semantic HTML element when it already supplies the required semantics and behavior.
An autocomplete is a custom composite widget, so its extra relationship still needs to be expressed:
<label htmlFor="city">City</label>
<input
id="city"
role="combobox"
aria-autocomplete="list"
aria-expanded={isOpen}
aria-controls="city-options"
aria-activedescendant={activeOptionId || undefined}
/>
{isOpen && (
<ul id="city-options" role="listbox">
{visibleOptions.map(option => (
<li
id={`city-option-${option.id}`}
role="option"
aria-selected={option.id === activeId}
key={option.id}
>
{option.label}
</li>
))}
</ul>
)}
Names, IDs, and selection logic must match your real implementation. Adding role="combobox" without the expected state and keyboard behavior makes the interface more confusing, not more accessible.
5. Implement the Keyboard and Focus Contract
The W3C combobox pattern defines the essential relationships and interaction model. For an editable list autocomplete, keep DOM focus on the input, expose the active option with aria-activedescendant, and make selection visually distinct.
| Input | Expected result |
|---|---|
| ArrowDown | Open the popup when appropriate and move to the next option |
| ArrowUp | Move to the previous option according to the agreed boundary behavior |
| Enter | Commit the active option and close the popup |
| Escape | Dismiss the popup without accidentally committing a new option |
| Tab | Follow normal page focus order; do not create a keyboard trap |
Do not capture every key. Standard text-editing keys should continue to work inside the input. When an option is selected by pointer, verify that blur and click ordering does not close the popup before selection is processed.
6. Handle Async and Edge States
If suggestions come from an API, show loading, empty, and error states without confusing them. Protect against stale responses: a slow request for sa should not overwrite a newer response for san. Cancellation or a request sequence ID can preserve the latest-query contract.
Also decide what happens when results shrink while an option is active, the user clears the input, an option is disabled, or the selected item disappears. State transitions are part of correctness, not optional polish.
7. Test What the User Can Observe
Testing Library's guiding principle is to make tests resemble real use. Querying by role and accessible name checks the same interface exposed to users, while user-event models complete interactions rather than firing one isolated DOM event.
const user = userEvent.setup();
render(<CityAutocomplete options={cities} />);
const input = screen.getByRole("combobox", { name: /city/i });
await user.type(input, "san");
expect(
screen.getByRole("option", { name: "San Francisco" })
).toBeVisible();
await user.keyboard("{ArrowDown}{Enter}");
expect(input).toHaveValue("San Francisco");
Add one test for Escape or the empty state, then run the component manually with only a keyboard. Automated tests are useful evidence, but they do not replace checking visible focus, zoom, responsive layout, or a real screen-reader flow.
Common UI Coding Interview Prompts
| Component | State challenge | Accessibility or test focus |
|---|---|---|
| Accordion | Single versus multiple open panels | Button semantics, expanded state, Enter and Space |
| Tabs | Active tab and mounted panel state | Arrow navigation, selected tab, panel relationship |
| Modal | Open state and action result | Initial focus, focus containment, Escape, focus return |
| Autocomplete | Query, active option, selection, async status | Combobox roles and keyboard selection |
| Data table | Sort, filters, pagination, selection | Headers, sort state, loading and empty states |
| Carousel | Current slide and autoplay | Named controls, pause behavior, announcement restraint |
| Toast system | Queue, timers, and removal | Announcements, pause, deterministic timer tests |
| File tree | Expansion, selection, and hierarchy | Tree keyboard model and focus movement |
Do not memorize eight full implementations. Practice the same analysis on each: acceptance contract, owner, minimal state, semantics, keyboard path, edge states, and one high-risk test.
Common UI Coding Interview Mistakes
- Coding before agreeing on behavior. A beautiful solution can still implement the wrong product contract.
- Duplicating derived state. Filtered results, counts, and boolean flags often belong in render-time calculations.
- Making accessibility a final ARIA pass. Element choice, focus, and keyboard behavior shape the architecture from the start.
- Testing private implementation details. A refactor should not break a test when user-visible behavior stays the same.
- Spending the last minute adding features. Run the current solution, fix obvious failures, and explain the next priority.
A 5-Day UI Coding Practice Plan
| Day | Component | Practice goal |
|---|---|---|
| 1 | Accordion | Semantic controls, minimal state, keyboard activation |
| 2 | Tabs | Component contract, focus model, selected state |
| 3 | Autocomplete | Async states, active option, role-based tests |
| 4 | Modal | Focus entry, containment, Escape, and return |
| 5 | Timed mock | Complete one unfamiliar prompt in 55 minutes |
Narrate your assumptions, attempt the prompt before reading any solution, and review where your state or test plan became unclear.
If React behavior itself is the weak area, pair this plan with React Interview Questions for Senior Frontend Engineers.
UI Coding Interview FAQ
Can I use React in a UI coding interview?
It depends on the company and prompt. Some browser rounds allow the framework you use most confidently, while others require vanilla JavaScript to evaluate DOM and language fundamentals. Confirm the environment, allowed packages, starter code, and expected testing setup before the interview.
How much accessibility should I implement under time pressure?
Start with native semantic elements, a visible label, logical keyboard access, and visible focus. For a custom composite such as a combobox, implement the role, state, relationship, and key behavior together. If time prevents a complete pattern, explain the exact gap rather than claiming accessibility is finished.
Should I write tests before or after the component?
Either can work if you keep a clear behavior contract. A practical timed approach is to define the highest-risk cases first, build a thin working path, then encode two or three user-visible behaviors as tests. If the company explicitly expects TDD, follow that instruction and begin with the contract test.
What if I cannot finish the UI coding problem?
Keep the current version runnable. Demonstrate the completed path, identify the first failing requirement, and explain the next implementation and test step. A coherent, tested core with honest prioritization gives the interviewer more evidence than several half-connected features or a last-minute rewrite.
Final Takeaway
A UI coding interview is not a race to produce the most JSX. It is a compact product-engineering exercise: clarify behavior, assign ownership, model one source of truth, preserve the keyboard and focus contract, and test what a user can observe.
Repeating the same decision loop across unfamiliar components is what makes your interview execution faster and more reliable.
Sources and Further Reading
- Atlassian Frontend Engineering Interview Guide
- W3C ARIA Authoring Practices: Combobox Pattern
- W3C ARIA Authoring Practices: Developing a Keyboard Interface
- W3C Web Content Accessibility Guidelines 2.2
- MDN: ARIA
- React: Choosing the State Structure
- Testing Library: Guiding Principles
- Testing Library: About Queries
- Testing Library: user-event Introduction