Back

AI Model Picker + Cost/Latency Badge

medium

Streak

0 days

Progress

0%

Submitted

0

AI Model Picker + Cost/Latency Badge

React35 minmediumFreeAI

Prompt

Every serious AI product eventually lets users pick a model. ChatGPT has GPT-4o vs o-series. Claude has Sonnet vs Opus. Cursor has Auto vs a pinned model. The picker looks like a dropdown — but the interview signal is whether you treat model choice as product state that gates UX, not a decorative select.

Build a chat composer with a keyboard-accessible model menu. Each model has latency, cost, and capability tags. Selecting a model must update a cost/latency badge immediately, and actions the model cannot perform (tools, vision) must be disabled with a clear explanation — never a silent no-op.

The senior insight: model selection is a capability contract. Badges communicate tradeoffs; disabled actions + inline reasons communicate limits; persistence across sends proves you modeled it as session state.

Requirements

  • →Provide at least 3 mock models with distinct latency, cost, and capability profiles
  • →Header badge updates immediately on model change (latency + relative cost)
  • →Model menu is keyboard accessible: Arrow keys, Enter to select, Escape to close
  • →Capability gating: tools/vision actions disabled when unsupported, with a visible inline reason
  • →Selected model persists across multiple messages in the same session
  • →Assistant messages show which model produced them
  • →Enter sends; Shift+Enter inserts a newline; empty input cannot send
Example
Loading preview...
For the best coding experience, we recommend using a desktop device.
Preparing Sandbox...
Premium interview report

What interviewers score in this build

Use this before reading the code. It tells you what to say, what to test, and where machine-coding candidates usually lose points.

Interview signals

  • Model as product state: Selection persists and drives badges + message metadata
  • Badge fidelity: Latency and cost update immediately on change
  • Capability gating: Unsupported actions disabled with visible inline reason
  • Keyboard accessibility: Arrows, Enter, Escape work on the menu

Time checkpoints

  1. 1

    0–3 min: Clarify models, badges, capability gates, keyboard needs

  2. 2

    3–8 min: Scaffold catalog + header badges + message list

  3. 3

    8–14 min: Build picker menu with open/close + click select

  4. 4

    14–20 min: Add keyboard navigation and click-outside

Edge-case checklist

Keyboard open/select/escape
Disabled capability with visible reason
Empty or flagged catalog
Click-outside closes menu

Common mistakes

  • Hardcoding badges without a catalog
  • Reason only in onClick on a disabled button
  • Duplicating model fields into state
  • Missing listbox/combobox keyboard pattern
SolutionRead-only · Live Preview

Technical Explanation

How I'd Think About This Problem

This is not a dropdown exercise. Interviewers are checking whether you understand that model choice changes the product surface. Latency badges set expectations. Cost chips educate tradeoffs. Capability tags prevent dead-end clicks. If you only change a label in the select and leave the rest of the UI identical, you've missed the point.

I split the problem into three layers before coding: config (static model catalog), session state (selected modelId that survives sends), and capability gates (actions that consult the selected model's capabilities before running).

Config as Source of Truth

const MODELS = [
  { id: 'flash', name: 'Flash Mini', latencyMs: 280, costPer1k: 0.15, capabilities: ['chat'] },
  { id: 'sonnet', name: 'Sonnet Pro', latencyMs: 520, costPer1k: 3.0, capabilities: ['chat', 'tools'] },
  { id: 'vision', name: 'Vision XL', latencyMs: 900, costPer1k: 8.5, capabilities: ['chat', 'tools', 'vision'] },
];
const model = MODELS.find(m => m.id === modelId);

Never denormalize latency/cost into React state. Derive them. When product adds a model, you edit one array. Same pattern for actions: declare { needs: 'vision', unlock: 'Vision XL' } once and render reasons from that.

Gates Need Visible Reasons

The junior trap: disabled={!ok} and nothing else. Users see a dead button and assume the product is broken. The senior move: keep the button visible, disable it, and put a permanent inline reason beside it — "Flash Mini lacks vision — switch to Vision XL". Also set title for hover/AT. Do not rely on click handlers for the reason; disabled buttons do not fire clicks.

⚠ Common Pitfall: Putting the reason only inside onClick

If the button is disabled, onClick never runs. Your warn banner stays blank forever. Render the reason from capability state, not from a click side-effect.

Keyboard Menu Without a Library

ArrowDown/ArrowUp move activeIdx. Enter commits MODELS[activeIdx]. Escape closes. Focus the menu when it opens (useEffect + ref), not via invalid autoFocus on a non-input. Click-outside closes. That is enough for most frontend loops.

What Changes in Production

  • Model list comes from your BFF (feature flags, regional availability, enterprise allowlists).
  • Cost chips should use live pricing or relative tiers your PM owns — not hardcoded dollars in the client forever.
  • Capability gating should match server-side enforcement. The UI is a courtesy; the gateway still rejects unsupported modalities.
ℹ Interview Tip

Say out loud: "I'd surface cost and TTFT next to the picker because users will pick the expensive model for everything unless you make the tradeoff visible." That sentence alone separates people who've shipped AI UX from people who've only called OpenAI once.

Interview Criteria

Model as product state

Selection persists and drives badges + message metadata

Badge fidelity

Latency and cost update immediately on change

Capability gating

Unsupported actions disabled with visible inline reason

Keyboard accessibility

Arrows, Enter, Escape work on the menu

Composer UX

Enter/Shift+Enter and empty-send guard

Time Checkpoints

0–3 min

0–3 min: Clarify models, badges, capability gates, keyboard needs

3–8 min

3–8 min: Scaffold catalog + header badges + message list

8–14 min

8–14 min: Build picker menu with open/close + click select

14–20 min

14–20 min: Add keyboard navigation and click-outside

20–25 min

20–25 min: Wire capability buttons + always-visible reasons

25–30 min

25–30 min: Persist model across sends; polish meta labels

Streak

0 days

Last active: Sign in to track

Progress

0%

0/0 solved

Submitted

0

Solutions pushed to review history.