Adapted this for React Native with NativeWind — token rules carried over directly, the component inventory became our own list. One question: why alwaysApply false rather than attaching to every request?
Index
Feed
Maintained by lena_writes_code · updated Aug 3, 2026
A scoped .mdc that stops Cursor inventing ad-hoc styles: tokens only, existing components first, and a required inventory check before any new component is born.
---
description: Design-system discipline for all UI work
globs: ["src/components/**", "src/features/**/*.tsx", "src/styles/**"]
alwaysApply: false
---- Colors: semantic tokens (`bg-surface`, `text-primary`, `border-subtle`). NEVER raw
Tailwind palette classes (`bg-gray-100`, `text-blue-600`) and never hex/rgb literals.
- Spacing: the 4px scale via existing utilities. No arbitrary values — `p-[13px]` fails review.
- Typography: `text-heading-*`, `text-body-*`, `text-caption` classes only. No raw
`text-sm font-medium` combinations; if a variant seems missing, ask.
- Radii and shadows: `rounded-token-*`, `shadow-token-*`. Same rule.Cursor rules
---
description: Design-system discipline for all UI work
globs: ["src/components/**", "src/features/**/*.tsx", "src/styles/**"]
alwaysApply: false
---
# Design-system rules
You are working in a codebase with an established design system in `src/design-system`.
The system is the source of truth. Your job is to use it, not to extend it casually.
## Tokens only
- Colors: semantic tokens (`bg-surface`, `text-primary`, `border-subtle`). NEVER raw
Tailwind palette classes (`bg-gray-100`, `text-blue-600`) and never hex/rgb literals.
- Spacing: the 4px scale via existing utilities. No arbitrary values — `p-[13px]` fails review.
- Typography: `text-heading-*`, `text-body-*`, `text-caption` classes only. No raw
`text-sm font-medium` combinations; if a variant seems missing, ask.
- Radii and shadows: `rounded-token-*`, `shadow-token-*`. Same rule.
## Components before markup
Before writing ANY new UI, list what `src/design-system/components` already offers:
Button, IconButton, Input, Select, Combobox, Dialog, Sheet, Popover, Tooltip, Card,
Badge, Tag, Table, Tabs, Toast, EmptyState, Spinner, Skeleton.
- Composing existing components > adding props to a component > building new. In that order.
- A new component requires: (1) a one-line justification in the PR, (2) placement in
`design-system/components` with variants via `cva`, (3) a story file. All three or don't.
- Do not fork a component to tweak its look. Extend variants through `cva` in the
component's own file so every consumer gets the option.
## Accessibility floor
- Interactive elements are `button`/`a`, never `div onClick`.
- Every `Input`/`Select` gets a `label` (or `aria-label` when visually hidden by design).
- Focus states come from the tokens; do not remove focus rings, ever.
## When unsure
If a design decision isn't covered by tokens or an existing component, STOP and ask
with a screenshot or description of what you're trying to build. Do not improvise
one-off styles to keep moving.
Listed the component inventory inline. Cursor kept building new dropdowns because it never went looking for Combobox.
Jul 19, 2026Switched from alwaysApply to globs — the rules were burning context on backend-only tasks.
Jul 1, 2026Running this config?
Sign in to add your report — every count here is backed by a named account.
Before writing ANY new UI, list what `src/design-system/components` already offers:
Button, IconButton, Input, Select, Combobox, Dialog, Sheet, Popover, Tooltip, Card,
Badge, Tag, Table, Tabs, Toast, EmptyState, Spinner, Skeleton.
- Composing existing components > adding props to a component > building new. In that order.
- A new component requires: (1) a one-line justification in the PR, (2) placement in
`design-system/components` with variants via `cva`, (3) a story file. All three or don't.
- Do not fork a component to tweak its look. Extend variants through `cva` in the
component's own file so every consumer gets the option.- Interactive elements are `button`/`a`, never `div onClick`.
- Every `Input`/`Select` gets a `label` (or `aria-label` when visually hidden by design).
- Focus states come from the tokens; do not remove focus rings, ever.If a design decision isn't covered by tokens or an existing component, STOP and ask
with a screenshot or description of what you're trying to build. Do not improvise
one-off styles to keep moving.Strong evidence gets promoted into the record above.
Adapted this for React Native with NativeWind — token rules carried over directly, the component inventory became our own list. One question: why alwaysApply false rather than attaching to every request?
Cost and dilution. On non-UI tasks these rules are noise that competes with relevant instructions. Globs mean they load exactly when a matched file is in play — see the 1.1 history note, that change came from watching context fill up on API work.
Sign in to join the discussion, vote, and verify fixes.
Related records
Thank you for making the accessibility section a 'floor' and not a 'guideline'. Framing matters to these models — floors get enforced, guidelines get traded away when the task gets hard.