budge
Use when making single-property CSS or Tailwind visual changes in Next.js App Router projects. Presents a floating control widget…
Use when interactive elements that have visual spacing between them (chart bars/columns, list rows, nav items, segmented controls, tabs, calendar cells, icon buttons, legend chips) need hover or click to respond across the whole region with no dead zones. Triggers on "dead
Claude Code
$ npx -y skills add millionco/skills --skill interactive-hit-areas --agent claude-code
Codex
$ npx skills add millionco/skills --skill interactive-hit-areas -a codex -y
Cursor
$ npx skills add millionco/skills --skill interactive-hit-areas -a cursor -y
Gemini CLI
$ npx skills add millionco/skills --skill interactive-hit-areas -a gemini-cli -y
GitHub Copilot
$ npx skills add millionco/skills --skill interactive-hit-areas -a github-copilot -y
OpenCode
$ npx skills add millionco/skills --skill interactive-hit-areas -a opencode -y
Windsurf
$ npx skills add millionco/skills --skill interactive-hit-areas -a windsurf -y
name: interactive-hit-areas description: Use when interactive elements that have visual spacing between them (chart bars/columns, list rows, nav items, segmented controls, tabs, calendar cells, icon buttons, legend chips) need hover or click to respond across the whole region with no dead zones. Triggers on "dead space", "deadspace", "gap between bars/items isn't clickable", "hover flickers between items", "have to aim precisely", "hit area too small", "highlight drops out between". Covers separating the hit area from the visual area, why gap/margin/space-between creates dead zones, and the flush-target + inner-spacing fix.
Separate the **hit area** (where pointer events land) from the **visual area** (what the user sees). Bugs happen when spacing is built so that the gap between items has no event handler — the pointer falls into a dead zone and hover/click does nothing or flickers.
**Visual spacing between interactive siblings must live INSIDE each hit target, never BETWEEN them.**
Result: the entire region is a continuous strip of live targets, but it looks identical to the spaced design.
1. Identify the repeating slot (one item's full share of the axis — its *pitch*). 2. Make the interactive container fill that whole slot, flush against its neighbors (remove `gap`/`space-*`/`margin` between siblings; use `flex-1`/equal grid tracks). 3. Put the handler (`onMouseEnter`, `onClick`, `:hover`) on that full-slot container. 4. Recreate the visual spacing *inside*: center a narrower visual element (`max-width`, fixed width + `items-center`), or use `padding` on the container around full-bleed content. Padding is part of the element, so it stays a live target; margin/gap is not.
Spaced bars where hovering anywhere over a bar's column highlights it:
// Container: flush columns, NO gap — the whole width is live.
<div className="absolute inset-0 flex items-stretch">
{bars.map((bar, i) => (
<div
key={bar.id}
// flex-1 = one full slot/pitch; full height = hover above the bar too
className="flex flex-1 flex-col items-center justify-end"
onMouseEnter={() => setHovered(i)}
onMouseLeave={() => setHovered(null)}
style={{ opacity: hovered !== null && hovered !== i ? 0.4 : 1 }}
>
<span>{bar.value}</span>
{/* visual spacing comes from the narrower CENTERED bar, not a gap */}
<div className="w-full" style={{ maxWidth: 37, height: bar.value * UNIT }} />
</div>
))}
</div>Anti-pattern that caused the bug: `flex ... gap-2` with `w-full` bars. The bars touched their slots, so the only spacing was the 8px `gap` between columns — and that gap was dead to the pointer.
Dead zones only matter when you want "anywhere in the region targets the nearest item." If items are meant to be discrete and the space between them is genuinely inert (e.g. cards on a page, unrelated buttons), `gap` is correct — don't force flush layouts everywhere. Apply this skill when the design intends a continuous interactive band with visual separation.
Use when making single-property CSS or Tailwind visual changes in Next.js App Router projects. Presents a floating control widget…
Use when converting Paper canvas or design nodes from absolute positioning to flex or auto-layout. Covers Paper MCP…
Use when implementing Paper MCP, Paper-to-code, design-to-code, Viewfinder, or Paper-exported JSX in React/Next.js apps. Covers…
Use when a built app that was derived from a Paper design looks "slightly off" versus the design, or to verify a Paper-to-code…
Use when consolidating, deduping, or reducing the number of CSS custom properties / Tailwind v4 design tokens in a globals.css…
Migrates React projects and components from Radix UI to Base UI. Use when asked to migrate from radix, move to base-ui, convert…
tasteskill v2, the anti-slop frontend skill. Art direction for websites, distilled from a study of 247 curated gallery sites (One…