Building UI Components
Prompt UI components that match your framework, design system, and state needs, with the states and props spelled out.
TL;DR
- Specify the framework, the design system, the props, and every state the component must handle.
- Point at an existing component as a pattern so new ones match your conventions.
- Name all the states up front: default, loading, empty, error, disabled, and focus.
Pin The Stack
Framework & VersionState the framework and version so APIs and patterns match.
"React 18 function component,
TypeScript, no class components."Design SystemName your component library and tokens to reuse, not reinvent.
"Use @/ui Button and our Tailwind
tokens. No inline hex colors."Pattern ExamplePoint at a real component to mirror structure and style.
"Match the structure of
Components/Card.tsx: <paste>"Define The API
Props & TypesList exact props, types, and which are optional.
props: { items: Item[]; onSelect:
(id: string) => void; loading?: boolean }EventsName the callbacks and when they fire.
"onSelect fires with the item id
on row click."CompositionSay how it slots into the app so it composes cleanly.
"Renders inside a <Card>; accepts
children for the footer."Name Every State
Data StatesDefault, loading, empty, and error should all be handled.
"Handle: loading skeleton, empty
message, error with retry."Interaction StatesHover, focus, active, disabled, and selected where relevant.
"Disabled and focus-visible styles
from the design system."Edge ContentLong text, many items, missing images, and overflow.
"Truncate long titles; handle 0 and
500 items gracefully."Baseline Quality
Semantic & A11yAsk for semantic HTML, labels, and keyboard support from the start.
"Use a <button>, label the icon,
keyboard operable."No Magic ValuesUse tokens and props, not hard-coded colors or sizes.
"Spacing and color from tokens only."Review RenderedRun it and check the real states, not just that it compiles.
See loading, empty, and error
in the browser.Tips
- Give your tokens or utility classes ('use our Tailwind config, not inline hex') so styling fits.
- List the exact props and their types so the component's API is right the first time.
Warnings
- Models default to inline styles and ad-hoc classes; anchor to your design system or you get drift.
- Generated components often skip loading, empty, and error states and keyboard/focus handling.
In Practice
A component request that pins the stack and design system, defines the exact props, and lists every state, so the first version fits your app instead of a generic sandbox demo.
- The stack and design system are pinned, with a real component to mirror.
- The props are listed with types so the component's API is correct.
- Every data and interaction state is named so none are skipped.
- Accessibility and token-only styling are required from the start.
Build a `UserList` component.
Stack: React 18, TypeScript. Use our design system:
Button and Spinner from @/ui, Tailwind tokens only
(no inline hex). Mirror the structure of @/ui/Card.tsx.
Props:
{ users: User[]; loading?: boolean; error?: string;
onSelect: (id: string) => void }
(User = { id: string; name: string; avatarUrl?: string })
States to handle:
- loading: show the Spinner
- empty (no users): "No users yet" message
- error: show error text + a Retry button that re-emits
- each row: focus-visible + disabled styles from tokens
Accessibility: rows are <button>s, avatar has alt text,
fully keyboard operable. Truncate long names.
Return the component file only.FAQ
Name the system and point at a real component that uses it. Say 'use our Button and Card from @/ui and our Tailwind tokens; match the style of this existing component'. Describing your system in prose is far weaker than showing one real example.
The exact props and their types, which are required vs optional, default values, and the events it emits. A precise prop list means the component composes correctly with the rest of your app instead of needing a rewrite.
Because models build the happy path unless told otherwise. List every state explicitly, default, loading, empty, error, disabled, and the component will handle them. Unstated states become missing states.
Ask for it. Request semantic HTML, labels, keyboard operability, and focus management. Accessibility is covered in depth in its own chapter, but even here, naming it in the prompt prevents div-soup components you have to retrofit.