Skip to content

feat: pre-dry-run — hover prompt, SVG mapping fix, fixture rebuild#141

Merged
let-sunny merged 3 commits intomainfrom
chore/pre-dryrun-139
Mar 27, 2026
Merged

feat: pre-dry-run — hover prompt, SVG mapping fix, fixture rebuild#141
let-sunny merged 3 commits intomainfrom
chore/pre-dryrun-139

Conversation

@let-sunny
Copy link
Copy Markdown
Owner

@let-sunny let-sunny commented Mar 27, 2026

Summary

Three changes preparing for ablation experiment (#130):

1. PROMPT.md — hover state instructions

  • New ### Hover States section: [hover]: data → :hover CSS
  • Updated Rules: allow hover effects when [hover]: data is provided

2. implement.ts — SVG mapping.json copy fix

  • vectors/mapping.json was not being copied to output directory
  • SVG lookup fell back to legacy ID-based naming → 0 SVGs inlined
  • Fix: include mapping.json in copy filter → 9 SVGs now inline correctly

3. Fixture rebuild — desktop-product-detail

  • Rebuilt with interactionDestinations (5 hover destinations)
  • Single fixture for dry-run verification

Exit criteria (all pass)

Criteria Count
[component:] annotations 91
/* var: */ token refs 129
svg: inline 9 (was 0 before fix)
url(images/) 4
[hover:] blocks 5
PROMPT hover section

Closes #139

Test plan

  • 671 tests pass
  • Type check passes
  • Exit criteria verified on desktop-product-detail fixture
  • Remaining 23 fixtures to be rebuilt before ablation execution (separate task)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Clarified design-to-code rules: hover styles are only generated when explicitly provided in the design; added a “Hover States” section explaining how hover overrides map to CSS selectors (including nested/child propagation) and forbidding invented hover effects.
    • Revised image-asset guidance: introduced distinct handling for content images vs. background images and formalized placeholder fallback behavior.
  • New Features

    • Asset export now also includes associated mapping/metadata files alongside SVG vector assets.

)

Three changes for experiment readiness:

1. PROMPT.md: add [hover] section with :hover CSS generation instructions,
   update rules to allow hover effects when [hover]: data is provided

2. implement.ts: copy vectors/mapping.json alongside SVGs — was missing,
   causing all SVG inline to fail (mapping lookup fell back to legacy
   ID-based naming which doesn't match instance-nested IDs)

3. Rebuild desktop-product-detail fixture with interactionDestinations
   (5 hover destinations resolved)

Exit criteria verified:
- [component:] annotations: 91 ✓
- /* var: */ token references: 129 ✓
- svg: inline: 9 ✓ (was 0 before mapping fix)
- url(images/): 4 ✓
- [hover:] blocks: 5 ✓
- PROMPT.md hover section: present ✓

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@let-sunny let-sunny marked this pull request as ready for review March 27, 2026 12:57
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 089046b2-be76-4939-bdd4-21b6d0c20a4b

📥 Commits

Reviewing files that changed from the base of the PR and between 1b50cd1 and 6a1dab6.

⛔ Files ignored due to path filters (74)
  • fixtures/desktop-about/data.json is excluded by !fixtures/**
  • fixtures/desktop-about/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-about/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-ai-chat/data.json is excluded by !fixtures/**
  • fixtures/desktop-ai-chat/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-ai-chat/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-article/data.json is excluded by !fixtures/**
  • fixtures/desktop-article/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-article/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-contact-us/data.json is excluded by !fixtures/**
  • fixtures/desktop-contact-us/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-contact-us/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-home-page/data.json is excluded by !fixtures/**
  • fixtures/desktop-home-page/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-home-page/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-landing-page/data.json is excluded by !fixtures/**
  • fixtures/desktop-landing-page/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-landing-page/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-portfolio/data.json is excluded by !fixtures/**
  • fixtures/desktop-portfolio/images/mapping.json is excluded by !fixtures/**
  • fixtures/desktop-portfolio/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-portfolio/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-portfolio/vectors/mapping.json is excluded by !fixtures/**
  • fixtures/desktop-pricing/data.json is excluded by !fixtures/**
  • fixtures/desktop-pricing/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-pricing/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-product-detail/data.json is excluded by !fixtures/**
  • fixtures/desktop-product-detail/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-product-detail/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-shop/data.json is excluded by !fixtures/**
  • fixtures/desktop-shop/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-shop/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-slot/data.json is excluded by !fixtures/**
  • fixtures/desktop-slot/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-slot/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-waitlist/data.json is excluded by !fixtures/**
  • fixtures/desktop-waitlist/screenshot-1200.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/desktop-waitlist/screenshot-1920.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-about/data.json is excluded by !fixtures/**
  • fixtures/mobile-about/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-about/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-ai-chat/data.json is excluded by !fixtures/**
  • fixtures/mobile-ai-chat/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-ai-chat/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-article/data.json is excluded by !fixtures/**
  • fixtures/mobile-article/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-article/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-contact-us/data.json is excluded by !fixtures/**
  • fixtures/mobile-contact-us/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-contact-us/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-home-page/data.json is excluded by !fixtures/**
  • fixtures/mobile-home-page/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-home-page/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-landing-page/data.json is excluded by !fixtures/**
  • fixtures/mobile-landing-page/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-landing-page/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-portfolio/data.json is excluded by !fixtures/**
  • fixtures/mobile-portfolio/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-portfolio/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-pricing/data.json is excluded by !fixtures/**
  • fixtures/mobile-pricing/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-pricing/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-product-detail/data.json is excluded by !fixtures/**
  • fixtures/mobile-product-detail/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-product-detail/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-shop/data.json is excluded by !fixtures/**
  • fixtures/mobile-shop/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-shop/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-slot/data.json is excluded by !fixtures/**
  • fixtures/mobile-slot/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-slot/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-waitlist/data.json is excluded by !fixtures/**
  • fixtures/mobile-waitlist/screenshot-375.png is excluded by !**/*.png, !fixtures/**, !**/*.png
  • fixtures/mobile-waitlist/screenshot-768.png is excluded by !**/*.png, !fixtures/**, !**/*.png
📒 Files selected for processing (5)
  • .claude/skills/design-to-code/PROMPT.md
  • src/core/engine/design-tree-strip.test.ts
  • src/core/engine/design-tree-strip.ts
  • src/core/engine/design-tree.test.ts
  • src/core/engine/design-tree.ts

📝 Walkthrough

Walkthrough

Updated PROMPT.md to allow generating CSS hover rules only when the design tree includes explicit [hover]: data and to formalize two image-asset types (content-image: vs background-image:). Also extended the implement CLI asset-copy filter for vectors/ to include mapping.json alongside *.svg.

Changes

Cohort / File(s) Summary
Hover & Image Prompt
\.claude/skills/design-to-code/PROMPT.md
Replaced blanket hover prohibition with rule to produce :hover CSS only when [hover]: data exists; added "Hover States" section (including selector propagation like .parent:hover .child); split image handling into content-image: (renders as <img>, may use object-fit) and background-image: (keeps CSS background-*), and formalized [IMAGE] fallback behavior.
CLI Asset Copy
src/cli/commands/implement.ts
Extended vector fixture copy filter to include mapping.json in addition to *.svg so mapping metadata is copied with vector assets.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 I nibble on the prompt tonight,
When designs say "hover", I add the light,
Images choose their proper tag and place,
Mapping walks beside each vector's trace,
A rabbit hops—designs meet code with grace.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the three main changes: hover prompt documentation, SVG mapping fix, and fixture rebuild.
Linked Issues check ✅ Passed The PR addresses all key coding requirements from #139: hover state CSS instructions in PROMPT.md, SVG mapping.json inclusion in implement.ts, and fixture rebuild with interactionDestinations.
Out of Scope Changes check ✅ Passed All changes directly align with #139 objectives: PROMPT.md hover/image documentation, SVG mapping fix, and desktop-product-detail fixture rebuild.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/pre-dryrun-139

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/cli/commands/implement.ts (1)

88-93: 🧹 Nitpick | 🔵 Trivial

Fix is correct; minor log message inconsistency.

The filter change correctly includes mapping.json alongside SVG files, which is necessary for design-tree.ts to resolve node IDs to SVG filenames (as shown in the context snippets).

However, the log message at line 93 now counts mapping.json (if present) but labels the count as "SVGs copied", which could be slightly misleading.

💡 Optional: Adjust log message for accuracy
-          console.log(`  vectors/: ${vecFiles.length} SVGs copied`);
+          const svgCount = vecFiles.filter(f => f.endsWith(".svg")).length;
+          console.log(`  vectors/: ${svgCount} SVGs copied`);

Alternatively, use a more generic message like "${vecFiles.length} files copied" to match the pattern used for images at line 106.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/commands/implement.ts` around lines 88 - 93, The log message after
copying vector assets is now inaccurate because vecFiles can include
mapping.json as well as .svg files; update the console output in implement.ts
(the block that builds vecFiles from vectorDir and copies to vecOutputDir) to
use a generic label like "files copied" or otherwise reflect mixed file types
(e.g., `${vecFiles.length} files copied`) so the count matches the actual files
copied.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/design-to-code/PROMPT.md:
- Around line 78-95: Add a second example showing child-element hover overrides:
extend the existing [hover]: documentation to include a nested example using a
parent component (e.g., Card) with a child element (e.g., Icon) and an explicit
`[hover]: Icon: ...` line, and show the generated descendant selector `:hover`
CSS (e.g., `.card .icon { ... }` and `.card:hover .icon { ... }`) so readers see
how `[hover]: Icon:` maps to the parent `:hover` + child selector pattern; keep
wording consistent with the Button example and explicitly state that only
provided hover data is used.
- Line 94: The wording "via parent selector" is ambiguous; update the sentence
that references child hover styles (the example "[hover]: Icon: fill: `#FFFFFF`")
to explicitly state that the hover state should be applied using a parent hover
selector that targets the child element (i.e., the pattern where the parent is
hovered and the child receives the hovered styles, rather than using a CSS
parent-only construct like :has()). Replace "via parent selector" with a clear
phrase such as "using a parent:hover → child selector (apply the styles on
.parent:hover .child so the child changes when the parent is hovered)" and
ensure the example maps to that pattern.
- Around line 80-91: Update the two fenced code blocks shown — the design-tree
block starting with "Button (INSTANCE, 120x40) [component: Button]" and the
generated CSS block that begins ".button { background: `#2C2C2C`; }" — to include
explicit language identifiers: add a marker (e.g., ```text or ```design-tree) to
the first block and ```css to the second block so both fences specify a language
for proper syntax highlighting and to satisfy MD040.

---

Outside diff comments:
In `@src/cli/commands/implement.ts`:
- Around line 88-93: The log message after copying vector assets is now
inaccurate because vecFiles can include mapping.json as well as .svg files;
update the console output in implement.ts (the block that builds vecFiles from
vectorDir and copies to vecOutputDir) to use a generic label like "files copied"
or otherwise reflect mixed file types (e.g., `${vecFiles.length} files copied`)
so the count matches the actual files copied.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f95daefb-ff06-48d8-a689-6280818254cd

📥 Commits

Reviewing files that changed from the base of the PR and between 38abd49 and aacd754.

⛔ Files ignored due to path filters (1)
  • fixtures/desktop-product-detail/data.json is excluded by !fixtures/**
📒 Files selected for processing (2)
  • .claude/skills/design-to-code/PROMPT.md
  • src/cli/commands/implement.ts

… IDs

- Add child hover example: .button:hover .icon { fill: #FFFFFF }
- Clarify "parent selector" → ".parent:hover .child" pattern
- Add text/css language identifiers to code blocks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@let-sunny let-sunny marked this pull request as draft March 27, 2026 13:42
…tinction

Fixture rebuild:
- All 24 fixtures rebuilt from latest Figma source
- interactionDestinations included (2-6 per fixture)
- Screenshots renamed to viewport convention (375/768/1200/1920)
- Tablet (768) and large desktop (1920) screenshots from Figma API

Design-tree: content-image vs background-image:
- Leaf nodes (no children) → content-image: url(...) + object-fit
- Nodes with children → background-image: url(...) + background-size
- Enables AI to use <img> for content images, CSS background for backgrounds

PROMPT.md: updated image section with two distinct types
Strip functions: content-image protected from color stripping
Tests: updated for content-image/background-image distinction

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@let-sunny let-sunny marked this pull request as ready for review March 27, 2026 13:59
@let-sunny let-sunny merged commit ae45a2e into main Mar 27, 2026
3 checks passed
@let-sunny let-sunny deleted the chore/pre-dryrun-139 branch March 27, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pre-dry-run: rebuild PROMPT.md + fixtures after design-tree changes

1 participant