A nested checklist for picking the right component when several feel "close enough." Use this before you reach for shadcn/ui, MUI, Headless UI, React Native Paper, or Tamagui - the wrong primitive locks in friction that no styling can fix later.
2 options that fit on one line? β Segmented control / Toggle Group (mobile-friendly, instant, no hidden state). Web: ToggleGroup. Native: segmented control / SegmentedButtons (Paper).
2β5 options, all important to see at once? β Radio group. Best for forms where the choice itself is informative (shipping speed, plan tier).
6β15 options? β Select / Dropdown. On mobile, prefer the native <select> on web and the native picker (Picker / ActionSheetIOS / BottomSheet) on React Native - they get the OS-level wheel/sheet UI for free.
16+ options or fetched dynamically? β Combobox / Autocomplete with type-to-filter. Required once scrolling becomes painful.
Hierarchical or grouped options (country β state)? β Cascading select or Combobox with grouped sections, not nested radios.
Visual options (colors, avatars, templates)? β Radio cards or chip group, not a text dropdown.
Mobile gotcha: a custom dropdown that worked beautifully on desktop usually feels broken on a phone (small hit target, no momentum scroll, no haptics). Default to native pickers on touch surfaces unless you have a strong reason.
These three are not interchangeable. Pick by when the change takes effect and what kind of value it represents.
Setting that takes effect immediately, no submit needed? β Switch (e.g. "Dark mode," "Notifications"). On native, use the platform Switch - iOS and Android render it differently and users expect that.
One of many options in a form, applied on submit? β Checkbox (e.g. "I agree to terms," "Subscribe to newsletter").
A press that changes view state, like bold/italic in an editor? β Toggle button (icon button with aria-pressed).
A truly transient action that does something now and isn't a state? β Button, not a toggle.
Accessibility: switches need role="switch" (web) and the right accessibilityRole (switch, native). A checkbox styled like a switch fails screen readers.
All four hide content until requested. Differ on how many panels can be open and whether the items are peers.
Many independent peer items, any number can be open at once (FAQ)? β Accordion (multi-open mode).
Many peer items, only one open at a time (specs / shipping / reviews)? β Accordion (single-open mode) or Tabs - pick Tabs if the panels are roughly equal in importance and length, Accordion if they're long-form prose.
A single show/hide region - "Show more," advanced settings? β Collapsible (one disclosure, no group).
Tiny inline expansion, native-feeling, no JS state needed? β <details> / <summary> on web. Browser-native, free a11y, free SEO, free Ctrl+F discoverability.
Mobile context, panels are full-width and content is heavy? β Accordion (Tabs become cramped under ~360px).
Mobile context, content is short and side-by-side comparison helps? β Tabs with horizontal scroll for overflow.
Anti-pattern: tabs with 7+ items on mobile. Either switch to a select / segmented scroll, or rethink the IA.
Pick by focus stealing, dismissibility, and content size.
Blocks the whole task until handled, may have a form? β Modal / Dialog. Trap focus, return focus on close.
Side panel of related content, page underneath stays meaningful? β Drawer / Sheet. On mobile, prefer bottom sheet (thumb-reachable); on desktop, side drawer.
Small contextual menu or info anchored to a trigger? β Popover.
One-line, hover-only, supplementary label? β Tooltip. β οΈ Tooltips don't exist on touch - never put critical info there. Mobile users will miss it.
Confirming a destructive action? β Alert dialog (a more constrained modal with explicit confirm/cancel).
Time-limited feedback after an action ("Saved")? β Toast / Snackbar. Don't put required actions in a toast - it auto-dismisses.
Persistent in-page status that the user must acknowledge? β Alert / Banner (stays until dismissed or fixed).
Mobile rule of thumb: if you'd reach for a popover or tooltip on desktop, reach for a bottom sheet on mobile. Anchored overlays misbehave when the keyboard opens.
Items the user is browsing (products, photos, recommendations)? β Horizontal carousel (pairs with thumb-swipe on mobile, mouse drag on desktop).
Items the user is consuming sequentially (stories, reels, feed)? β Vertical carousel / vertical pager (TikTok / Stories model). Right when each item is full-screen and immersive.
Both axes feel plausible (a gallery)? β Horizontal, except on TV / large landscape screens where vertical reads as a list and horizontal reads as featured.
More than ~10 items? β Don't carousel - switch to a scrollable rail (no auto-advance, no pagination dots), a grid, or pagination.
Hero / promotional carousel? β Strongly consider not building one. Auto-advancing hero carousels have well-documented engagement drops; a static hero or two stacked cards usually outperform.
User needs deep linkability and back-button predictability (search results)? β Pagination.
Mobile feed where engagement matters more than navigation? β Infinite scroll, but with a footer that's still reachable (use a "Load more" button at the end of the practical first batch, or expose a footer in a drawer).
User needs to know how much is left? β Load-more button with a count, not infinite.
Multi-step form / wizard? β Stepper, with a visible progress indicator.
Imprecise value where feel matters (volume, brightness)? β Slider.
Precise value the user knows (age, quantity)? β Number input with inputMode="numeric" on mobile.
Small integer range, Β±1 actions feel natural (cart quantity)? β Stepper / NumberInput with Β± buttons. Touch-friendly hit targets are essential here (44pt minimum).
Range with two endpoints (min priceβmax price)? β Range slider.
3β5 discrete buckets? β Segmented control ("S / M / L / XL"), not a slider.
Date or time? β Native picker on mobile (<input type="date"> web, DatePickerIOS / DatePickerAndroid / community date picker on RN). Custom calendars are right only when range, multi-select, or business rules require it.