fix(studio): reserve a gutter for the promote-to-variable badge#2533
Conversation
PromotableControl absolutely-positions its "◇ var" / "◆ {id}" badge over
the wrapped control without reserving any space, so on rows where the
value renders flush to the right edge (flat Font/Color rows) the badge
sat directly on top of the value text instead of beside it. Add a
right-padding gutter on the wrapper sized to each badge state, and cap
the bound chip to a fixed max-width so it always fits inside its gutter.
… of a padding gutter Shrinking the wrapped control's width to make room for the badge (previous commit) fixed the overlap but pushed the value left unnecessarily. Move the badge to sit above the row instead, clearing the value without touching its layout.
6px between rows left little clearance above a row's value for the promote-to-variable badge (now positioned above the row). Widen the row gap to 10px.
miga-heygen
left a comment
There was a problem hiding this comment.
Review — #2533: reserve gutter for promote-to-variable badge
Pure CSS. top-0 → -top-2 on both bound badge and promote button so they clear flush-right values. space-y-1.5 → space-y-2.5 on text section to accommodate the gutter. No logic changes.
Code: clean.
Review by Miga
james-russo-rames-d-jusso
left a comment
There was a problem hiding this comment.
Reviewed at 14dbfca5. Traced PromotableControl consumers (3 in propertyPanelFlatTextSection.tsx, 3 in classic propertyPanelSections.tsx) and checked the space-y gutter bump scope for correctness.
Blockers
(none)
Concerns
(none)
Nits
🟡 The -top-2 positioning change is global to every PromotableControl consumer — the gutter bump is scoped only to FlatTextSection. PromotableControl.tsx now positions the bound-badge (◆ boundId) and the promotion button (◇ var) 8px above the row's top edge for ALL usages. The gutter bump (space-y-1.5 → space-y-2.5, +4px per gap) landed only in propertyPanelFlatTextSection.tsx:270,298. The classic panel (propertyPanelSections.tsx:332,344,372) is the other consumer, and its rows wrap taller controls (TextAreaField, ColorField, FontFamilyField) with their own internal padding — likely absorbs the 8px protrusion without visual overlap. But this isn't verified visually here, and if a bound-variable indicator now clips into the row above in the classic panel, this PR would be the origin. Would suggest either a quick visual check in the classic-panel path, or a comment on PromotableControl.tsx noting "the classic panel's row heights absorb the -top-2 protrusion; the flat inspector needs the space-y-2.5 gutter" so the coupling is discoverable. Non-blocker — safe assumption for classic panel, just worth documenting.
Questions
(none)
Green notes
🟢 Scope of the space-y-2.5 bump is correct for the flat inspector. PromotableControl is only imported in propertyPanelFlatTextSection.tsx among the flat-family sections (verified via grep of propertyPanelFlat*.tsx). Every other flat section (FlatLayoutSection, FlatMediaSection, FlatColorGradingSection, FlatStyleSections, FlatMotionSection) keeps space-y-1.5 — no wasted gutter, no missed row that could overlap.
🟢 FlatTextLayerList's nested space-y-1 (line 351) is correctly NOT bumped. That inner container holds FlatTextLayerRow entries (the layer-list picker), none of which wrap PromotableControl — no badge to reserve room for. Selective bump only where badges render.
🟢 The -top-2 positioning is symmetric across bound + promote branches. Both the bound && <span> badge (line 84) and the promote && <button> (line 100) get -top-2. If only one had shifted, the "bound → promote toggle" transition would jitter.
🟢 Only the positioning class changed — no semantic behavior change. pointer-events-none, max-w-[60%], truncate, bg-studio-accent/20, etc. all preserved. Same click handler, same stopPropagation(), same title tooltip. Pure CSS reflow.
Verdict framing
Small, targeted CSS fix. Scoped correctly for the flat inspector's compact rows; the classic-panel visual side is a "should be fine given taller controls" assumption worth noting but not blocking. LGTM from my side.

Summary
◇ var/◆ {id}) is absolutely positioned over the wrapped control. On rows where the value renders flush to the right edge (Content, Font, Color in the Text section), the badge sat directly on top of the value instead of beside it.-top-2) instead of on top of it, and widened the Text section's row gap (6px → 10px) so the badge has clear space from the row above it.Test plan
bunx vitest run— full studio suite (231 files / 2643 passed)tsc --noEmit,oxlint,oxfmt --checkclean on touched files