feat(demo): correct stat badge tones via recorded fill overrides

Apply success/accent/danger tones to the stat badges after layout with the
label fill recorded as an override, so component sync preserves them.
Badges now read +14% green, +8% blue, -3% red.
This commit is contained in:
Danila Poyarkov 2026-07-21 02:13:22 +03:00
parent bc2beeea22
commit 56f99cbc47
2 changed files with 37 additions and 10 deletions

View file

@ -1,5 +1,6 @@
import { computeAllLayouts } from '@open-pencil/core/layout'
import { DEMO_COLORS, solid } from '@/app/demo/colors'
import { createAppPreviewSection } from '@/app/demo/sections/app-preview'
import { createComponentsSection } from '@/app/demo/sections/components'
import { createDemoVariables } from '@/app/demo/sections/variables'
@ -19,6 +20,25 @@ export function createDemoShapes(store: EditorStore) {
graph.bindVariable(app.chartTitle, 'fills/0/color', 'var-text-primary')
computeAllLayouts(graph)
// Apply badge tones after layout so component sync doesn't revert them.
const toneColors = {
success: [DEMO_COLORS.successSoft, DEMO_COLORS.success],
accent: [DEMO_COLORS.accentSoft, DEMO_COLORS.accent],
danger: [DEMO_COLORS.dangerSoft, DEMO_COLORS.danger]
} as const
for (const b of app.statBadges) {
const [soft, strong] = toneColors[b.tone]
const badge = graph.getNode(b.id)
if (!badge) continue
// Record the label fill as an override so component sync preserves it.
graph.updateNode(b.labelId, { fills: [solid(strong)] })
graph.updateNode(b.id, {
fills: [solid(soft)],
overrides: { ...badge.overrides, [`${b.labelId}:fills`]: [solid(strong)] }
})
}
store.clearSelection()
void store.loadFontsForNodes(graph.getPages().flatMap((page) => page.childIds)).then(() => {
store.requestRender()

View file

@ -154,6 +154,7 @@ export function createAppPreviewSection(store: EditorStore, comps: DemoComponent
{ title: 'Churn', value: '1.9%', trend: '-3%', tone: 'danger' as const }
]
const statBadges: StatBadge[] = []
stats.forEach((s) => {
const card = store.createShape('FRAME', 0, 0, 148, 96, statRow)
graph.updateNode(card, {
@ -192,13 +193,6 @@ export function createAppPreviewSection(store: EditorStore, comps: DemoComponent
})
const badge = graph.createInstance(comps.badgeComp, card)
if (badge) {
const bLabel = badge.childIds.map((cid) => graph.getNode(cid)).find((n) => n?.type === 'TEXT')
if (bLabel) {
graph.updateNode(bLabel.id, { text: s.trend })
graph.updateNode(badge.id, {
overrides: { ...badge.overrides, [`${bLabel.id}:text`]: s.trend }
})
}
const tone =
s.tone === 'success'
? DEMO_COLORS.success
@ -211,8 +205,15 @@ export function createAppPreviewSection(store: EditorStore, comps: DemoComponent
: s.tone === 'danger'
? DEMO_COLORS.dangerSoft
: DEMO_COLORS.accentSoft
graph.updateNode(badge.id, { fills: [solid(toneSoft)] })
if (bLabel) graph.updateNode(bLabel.id, { fills: [solid(tone)] })
const bLabel = badge.childIds.map((cid) => graph.getNode(cid)).find((n) => n?.type === 'TEXT')
if (bLabel) {
const overrides: Record<string, unknown> = { ...badge.overrides }
graph.updateNode(bLabel.id, { text: s.trend, fills: [solid(tone)] })
overrides[`${bLabel.id}:text`] = s.trend
overrides[`${bLabel.id}:fills`] = [solid(tone)]
graph.updateNode(badge.id, { fills: [solid(toneSoft)], overrides })
statBadges.push({ id: badge.id, labelId: bLabel.id, tone: s.tone })
}
}
})
@ -304,5 +305,11 @@ export function createAppPreviewSection(store: EditorStore, comps: DemoComponent
fills: [solid(DEMO_COLORS.accentText)]
})
return { sectionId, sidebar, main, headerTitle, chartTitle }
return { sectionId, sidebar, main, headerTitle, chartTitle, statBadges }
}
interface StatBadge {
id: string
labelId: string
tone: 'success' | 'accent' | 'danger'
}