What Are UI Components and How Do You Choose and Use Them?
UI components are reusable pieces of interface code—a button, an input, a card, a hero section—that you drop into an app instead of rebuilding from scratch each time. You choose them by matching the component's scope (primitive vs. composed block) and source model (headless library, styled kit, copy-paste registry, or prompt-based generator) to your project's needs, then check accessibility, theming, dependencies, and license before adopting. This guide covers the categories, the trade-offs between sourcing options, and how to integrate one into a React + Tailwind project.
Primitives vs. composed blocks
The single most useful distinction when picking components is scope:
- Primitives are single-purpose controls: buttons, inputs, checkboxes, tooltips, dropdowns. They handle one interaction and expose props for state and styling.
- Composed blocks assemble primitives into a larger section: a hero, a pricing table, a sign-in form, an AI chat panel. They solve a layout and content problem, not just an interaction.
A library that's excellent at primitives may not offer blocks, and a block you copy from a gallery may depend on a specific primitive library underneath. Knowing which layer you're shopping at prevents the common mistake of adopting a whole design system just to get one pricing section.
Common categories to expect
Most component sources organize around roughly the same buckets:
| Category | Examples | Typical scope |
|---|---|---|
| Form controls | Buttons, inputs, selects, toggles | Primitive |
| Navigation | Navbars, sidebars, tabs, breadcrumbs | Primitive to composed |
| Cards & grids | Product cards, galleries, 3D grids | Composed |
| Marketing blocks | Animated heroes, shaders, gradients, footers | Composed |
| AI & chat widgets | Chat panels, prompt inputs, streaming message lists | Composed |
| Auth & widgets | Sign-in forms, account menus | Composed |
21st, for instance, describes its catalog as 12,000+ React components, templates, and shadcn themes, split into roughly 2,000+ marketing blocks and 2,100+ UI components, with categories like animated heroes, shaders, cards & grids, navigation, and AI chats. That split mirrors the primitive/block distinction above.
Comparing sourcing options
The four common ways to get components differ mainly in how much styling and ownership you get:
| Source model | What you get | Best when | Trade-off |
|---|---|---|---|
| Headless libraries | Behavior and accessibility, no styles | You have a design system and want full control | You write all the CSS |
| Styled kits | Pre-styled components with a theme API | You want speed and a consistent look | Customizing beyond the theme can fight the library |
| Copy-paste registries | Source code you paste into your repo | You want to own and edit the code | You maintain it; updates aren't automatic |
| Prompt-based generators | A prompt that produces the component in your tool | You want the component adapted to your existing theme | Output quality depends on the model and your prompt |
21st sits in the copy-paste and prompt-based space: every component ships as a prompt you can paste into a tool like Claude Code, Codex, or Lovable, and the result lands as source in your repo—React + Tailwind following shadcn/ui conventions. The site reports 25,431 installs in a week for one component and 3,819,076 builders using the library, which is a signal of activity rather than a quality guarantee.
If you already run shadcn/ui, a registry that follows the same conventions will slot in with less friction than a styled kit with its own theming layer.
Evaluating a component before you adopt it
Run through these checks before committing:
- Accessibility — Does it use semantic elements and manage focus, keyboard navigation, and ARIA states? A visually correct dropdown that traps focus is a liability.
- Theming — Does it read from your design tokens (CSS variables, Tailwind config) or hard-code colors and spacing? Hard-coded values mean manual edits on every theme change.
- Dependencies — What peer dependencies does it pull in? A single button that requires a large animation library may not be worth it.
- License — Confirm the license permits your use, especially for commercial or redistributed products.
- Maintenance — For copy-paste and prompt-based sources, you own the code after adoption, so check whether the source is actively updated.
Integrating a component into React + Tailwind
The general flow, using a prompt-based source as the example:
- Copy the prompt for the component you want.
- Paste it into your tool—a terminal agent, a chat tool, or your editor's AI. The tool generates the component file, typically under something like
components/ui/. - Verify the file landed in your repo and review the diff before accepting it.
- Adapt it to your tokens—swap hard-coded colors and spacing for your CSS variables or Tailwind theme values.
- Render it in a page and check it against your existing layout.
The expected result is a working component file in your project that you can edit like any other source file, since it's plain React + Tailwind rather than an opaque package.
Troubleshooting common issues
- Style conflicts — If the component's classes clash with your global styles, scope them or convert hard-coded values to your tokens. Tailwind's utility model usually makes this a matter of editing class names.
- Missing peer dependencies — Generated or copied components often assume a helper like
cn(a class-merge utility) or a primitive library. If imports fail, install the missing package or replace the import. - SSR / hydration mismatches — Components that read
window, use random values, or animate on mount can mismatch between server and client render. Guard browser-only code behind an effect or a mounted check. - Theme drift — If a component looks right in isolation but wrong in your app, it's usually reading different tokens. Trace its color and spacing values back to your theme.
Making the call
Pick primitives from a headless or styled library when you need consistent behavior across many controls. Pick composed blocks from a copy-paste or prompt-based registry when you need a specific section fast and are willing to own the code. In both cases, evaluate accessibility, theming, dependencies, and license before adopting—and treat usage numbers as a signal of activity, not a substitute for reviewing the source you're about to ship.