šŸ’» Coding

Cursor UI Design Prompt: Mockup to Component and .mdc Rule

Paste a mockup into Cursor and get a token map, contrast checks, an accessible component, a scoped .cursor/rules .mdc file, and an @Browser visual check plan.

0.0
0Reviews
P
October 16, 2026

Prompt

Act as a senior front-end engineer working in Cursor's Agent who turns a pasted UI mockup and the project's design tokens into an accessible component, a scoped project rule, and a visual check plan, and asks instead of guessing any value.

How to run it: open Agent in Cursor, paste the mockup screenshot into the chat (drag and drop or Cmd+V), @-mention the ComponentPath folder and the tokens file, then send this prompt.

Inputs:
- What the mockup shows, section by section: [MockupNotes]
- Design tokens (colors, spacing, radius, type): [DesignTokens]
- Framework and styling: [Stack]
- Folder where the component lives: [ComponentPath]
- States to support: [UIStates]
- Breakpoints: [Breakpoints]
- Accessibility target: [A11yTarget]
- Existing components to reuse: [ReuseList]

Generate:
1. Mockup read-back: every element you see in the screenshot, checked against MockupNotes, and anything unclear as a question.
2. Component tree and props table, reusing ReuseList where it fits.
3. Token map: each visual value in the mockup mapped to a token name; any value with no matching token marked "no token: ask", never a new hex value.
4. Contrast check: the WCAG contrast ratio for each text and background token pair the component uses, pass or fail against A11yTarget (4.5:1 normal text, 3:1 large text and UI component boundaries).
5. Component code in Stack, using only the tokens.
6. States and keyboard behavior for each item in UIStates, including a visible focus style.
7. Responsive layout for each breakpoint.
8. Project rule: a .cursor/rules/*.mdc file with frontmatter and globs scoped to ComponentPath (rule type Apply to Specific Files) that records the token and accessibility conventions. Do not write a .cursorrules file; that single file is the legacy format.
9. Visual check: steps to open the running page in Cursor's built-in browser and an @Browser prompt that compares it with the mockup at each breakpoint, plus a list of what to compare.

Rules:
- Use only DesignTokens and ReuseList; no new colors, fonts, or icon libraries.
- Do not copy logos or brand assets from the mockup unless they already exist in the repo.

Instructions

Run it in Cursor's Agent with the mockup screenshot pasted into the chat and your tokens file @-mentioned. Answer the token questions before merging, and keep project rules as .mdc files in .cursor/rules.

Generated Output

This image was generated using the prompt above.

Cursor UI Design Prompt: Mockup to Component and .mdc Rule - Result

Examples

Example Input

MockupNotes: pricing section with three plan cards side by side (Starter, Team, Business); each card has the plan name, a price per month, the helper line "billed yearly", 3 to 5 feature lines with check marks, and a full-width button; the Team card has a "Most popular" badge on a light blue pill and a 2px primary border
DesignTokens: --color-primary #2563EB; --color-primary-hover #1D4ED8; --color-text #0F172A; --color-muted #64748B; --color-disabled #94A3B8; --color-surface #FFFFFF; --color-border #E2E8F0; radius-lg 12px; space 4, 8, 16, 24, 32; text-sm 14px, text-base 16px, text-2xl 24px; semibold 600
Stack: React 18, TypeScript, Tailwind CSS v3; tokens are CSS variables in src/styles/tokens.css
ComponentPath: src/components/pricing/
UIStates: default, hover, keyboard focus, current plan (button disabled, label "Current plan"), loading
Breakpoints: 1 column under 768px, 3 columns from 768px
A11yTarget: WCAG 2.2 AA
ReuseList: Button from src/components/ui/Button.tsx (variants primary and secondary; props loading and disabled)

Example Output

1. MOCKUP READ-BACK
Matches the notes: 3 cards, Team highlighted with badge and 2px border, full-width buttons.
Questions: the badge's light blue pill has no token. Add one (for example --color-primary-soft) or render the badge as primary text only?

2. TREE AND PROPS
PricingSection > PlanCard x3 > Button (reused)
PlanCard props: name, price, note, features[], highlighted?, current?, loading?, onSelect

3. TOKEN MAP
Card background: --color-surface. Card border: --color-border; Team border: 2px --color-primary.
Plan name: text-base semibold --color-text. Price: text-2xl semibold --color-text.
"billed yearly": text-sm --color-muted. Check marks: --color-primary.
Radius: radius-lg 12px. Card padding: space 24. Gap between cards: space 24.
Badge pill background: no token: ask.

4. CONTRAST (WCAG 2.2 AA)
#0F172A on #FFFFFF: 17.85:1 pass
#64748B on #FFFFFF: 4.76:1 pass (normal text)
#FFFFFF on #2563EB (button): 5.17:1 pass; on #1D4ED8 (hover): 6.70:1 pass
#2563EB border on #FFFFFF: 5.17:1, above 3:1
#94A3B8 on #FFFFFF: 2.56:1. Fine for the disabled button (WCAG exempts inactive controls), but never use it for "billed yearly".

5. CODE (src/components/pricing/PlanCard.tsx)
import { Button } from "@/components/ui/Button";
type Props = { name: string; price: string; note: string; features: string[];
  highlighted?: boolean; current?: boolean; loading?: boolean; onSelect: () => void };
export function PlanCard({ name, price, note, features, highlighted, current, loading, onSelect }: Props) {
  const id = `plan-${name.toLowerCase()}`;
  return (
    <section aria-labelledby={id} className={`rounded-[12px] bg-[var(--color-surface)] p-6 ${highlighted
      ? "border-2 border-[var(--color-primary)]" : "border border-[var(--color-border)]"}`}>
      {highlighted && <p className="mb-2 text-sm font-semibold text-[var(--color-primary)]">Most popular</p>}
      <h3 id={id} className="text-base font-semibold text-[var(--color-text)]">{name}</h3>
      <p className="mt-2 text-2xl font-semibold text-[var(--color-text)]">{price}<span className="text-sm text-[var(--color-muted)]"> per month</span></p>
      <p className="text-sm text-[var(--color-muted)]">{note}</p>
      <ul className="mt-4 space-y-2">{features.map((f) => (
        <li key={f} className="flex gap-2 text-sm text-[var(--color-text)]">
          <span aria-hidden="true" className="text-[var(--color-primary)]">āœ“</span>{f}</li>))}</ul>
      <Button className="mt-6 w-full" variant={highlighted ? "primary" : "secondary"}
        disabled={current} loading={loading} onClick={onSelect}>
        {current ? "Current plan" : `Choose ${name}`}</Button>
    </section>);
}

6. STATES
Hover: Button primary uses --color-primary-hover. Focus: Button keeps a visible 2px --color-primary outline with offset; check it shows on Tab. Current plan: native disabled, label "Current plan". Loading: Button loading prop; keep the label for screen readers.

7. RESPONSIVE
PricingSection grid: grid-cols-1 gap-6 md:grid-cols-3 (Tailwind md is 768px by default).

8. PROJECT RULE (.cursor/rules/pricing-ui.mdc)
---
globs: src/components/pricing/**/*.tsx
alwaysApply: false
---
- Use only CSS variables from src/styles/tokens.css; never hard-code hex values
- Reuse Button from src/components/ui/Button.tsx
- Every interactive element needs a visible focus style
- New text and background pairs must meet WCAG 2.2 AA contrast

9. VISUAL CHECK
Run the dev server, open the pricing page in Cursor's browser, attach the mockup, then send:
"@Browser compare the pricing section at 1280px and 375px wide with the attached mockup and list differences in spacing, color, type size, and border."
Compare: 3 columns at 768px and up, 1 below; badge only on Team; Team border 2px; focus outline visible on every button.

Reviews (0)

Please login to leave a review.
Loading reviews...