feat(budget): quoted amount as single muted value + vendor on second line#1454
Conversation
…er memory (issue #1449) Co-Authored-By: Claude ux-designer (Sonnet 4.6) <noreply@anthropic.com>
…line Display invoiced/quoted amount in budget line cards using a muted color (--color-text-quoted token) to visually distinguish it from actual spend. Vendor detail is now rendered on a dedicated second line in InvoiceGroup for improved readability. Fixes #1449 Co-Authored-By: Claude dev-team-lead (Sonnet 4.6) <noreply@anthropic.com> Co-Authored-By: Claude ux-designer (Sonnet 4.5) <noreply@anthropic.com> Co-Authored-By: Claude frontend-developer (Haiku 4.5) <noreply@anthropic.com> Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> Co-Authored-By: Claude e2e-test-engineer (Sonnet 4.5) <noreply@anthropic.com> Co-Authored-By: Claude translator (Sonnet 4.5) <noreply@anthropic.com>
The previous Assert 5 scoped not.toContainText(' – ') to the entire
budget section, but BudgetCostOverview legitimately renders planned-cost
ranges (e.g. €600.00 – €720.00) when a budget line has a non-zero
confidence margin. Narrowed the assertion to the invoiceGroup locator,
which is the precise target for the issue #1449 regression guard.
Co-Authored-By: Claude dev-team-lead (Sonnet 4.6) <noreply@anthropic.com>
Co-Authored-By: Claude e2e-test-engineer (Sonnet 4.6) <noreply@anthropic.com>
steilerDev
left a comment
There was a problem hiding this comment.
[product-architect]
Reviewed scope, tokens, contracts, and test parity for the single-value quoted-amount + vendor-line rework.
1. Backend / contract impact — None. git diff origin/beta...HEAD -- shared/ server/ returns zero lines. Display-only.
2. No silent semantic changes — Confirmed. BudgetOverviewPage.tsx and CostBreakdownTable.tsx are untouched (diff = 0 lines). The ±5% band removal and amountValueQuoted styling are scoped strictly to BudgetLineCard and InvoiceGroup (work-item / household-item budget sections). CostBreakdownTable retains its own range logic — correctly tracked as a separate follow-up per PR body.
3. Token placement — --color-text-quoted is defined in tokens.css in both :root (gray-500) and [data-theme='dark'] (slate-200) blocks, no hex literals. The dark-mode override that previously lived inline in BudgetLineCard.module.css is correctly removed in favor of the token. Token is also documented in wiki/Style-Guide.md line 143 with WCAG AA contrast verified — the PR body claim that the wiki entry is missing is stale (it landed in commit 52fcbc3).
4. Test parity — All production lines have corresponding tests:
BudgetLineCard.tsx(2/4 lines): newBudgetLineCard.test.tsx(471 lines)InvoiceGroup.tsx(15/13 lines):InvoiceGroup.test.tsxadds 7 new assertions covering quotation single-value, no en-dash,invoiceIdentitywrapper, status-badge sibling, null-vendor path, andamountValueQuotedclass toggling- E2E
budget-vat-quotation-fixes.spec.tsupdated to assert€500.00and no–separator anywhere in the InvoiceGroup
5. No regressions to other invoice statuses — amountValueQuoted class is only applied when invoiceStatus === 'quotation'; paid/draft/etc. branches retain amountValue styling unchanged. amountValueMuted (cancelled, strikethrough) is untouched. The wiki submodule bump (b76a9e0a → c587406b) is for ADR-029 from #1440/#1441, not part of this PR's scope but harmless.
Bonus quality improvement: InvoiceGroup.module.css migrated from hardcoded values (0.75rem, 0.9375rem, 0.25rem) to design tokens (--spacing-3, --font-size-base, --radius-sm). Aligns with the token-usage policy in CLAUDE.md.
VERDICT: APPROVED
steilerDev
left a comment
There was a problem hiding this comment.
[ux-designer]
PR #1454 — Visual spec compliance review for issue #1449 (quoted-amount + vendor line rework).
Token implementation — --color-text-quoted
Confirmed in tokens.css:
- Light (
:root):var(--color-gray-500)(#6b7280) — 4.6:1 on--color-bg-primary. Passes WCAG AA. - Dark (
[data-theme="dark"]):var(--color-slate-200)(#94a3b8) — 5.8:1 on--color-bg-primarydark. Passes WCAG AA. - Both placements are correctly in the existing text-color blocks.
BudgetLineCard.module.css migration
.amountQuoted and .quotedLabel both migrated to var(--color-text-quoted). The four manual [data-theme='dark'] overrides are correctly removed — the semantic token handles both modes automatically.
InvoiceGroup.module.css — token migration and .amountValueQuoted
All previously hardcoded values (0.375rem, 0.75rem 1rem, 0.5rem, 1rem, 0.125rem, 0.9375rem, 0.25rem, 0.75rem, 1.5rem, 0.2s ease-out, 1.5rem icon size, etc.) are correctly replaced with design tokens. .amountValueQuoted rule is added as a colour-only modifier (color: var(--color-text-quoted)) and applied via className concatenation — correct pattern.
Layout structure — .invoiceIdentity
flex-direction: column; gap: var(--spacing-0-5) wraps the invoice link and conditional vendor span. The status badge is a sibling of .invoiceIdentity inside .invoiceInfo, matching the ASCII mockup from the spec. align-items: flex-start on .invoiceInfo ensures top-alignment as the identity grows taller.
Vendor name font-size
.vendorName correctly uses var(--font-size-xs) per spec.
Accessibility
aria-label on the group uses Invoice ${number} from ${vendorName}: N budget lines, €X <amountLabel> — vendor is included when present, omitted when null. No regression.
Responsive
Mobile breakpoint (≤767px) already handled: .toggleBtn min-height: 44px, .headerContent stacks to column. The .invoiceIdentity column layout is narrower on mobile but requires no additional breakpoint rule.
i18n
t('vendorDetail.invoicedAmount') replaces the hardcoded 'Invoiced' string in both InvoiceGroup.tsx and BudgetLineCard.tsx. Keys added to both en/budget.json and de/budget.json.
Pre-existing informational note (non-blocking)
font-weight literals (400/500/600) remain throughout InvoiceGroup.module.css — token equivalents exist (--font-weight-normal/medium/semibold). These are pre-existing and not introduced by this PR; flag for a general cleanup pass, not this PR.
Wiki / Style Guide follow-up (non-blocking)
Commit 52fcbc3d (the earlier spec commit) appeared to add a --color-text-quoted Style Guide entry but the wiki content edit was lost — only the submodule pointer moved. This PR's submodule bump (c587406b) does include the entry at line 143 of Style-Guide.md, so the wiki documentation is now correct. No separate follow-up PR is needed; the content is present. I acknowledge the earlier confusion and confirm the wiki is in the correct state.
All spec requirements are met. Token adherence, dark mode, layout, accessibility, and i18n are correctly implemented.
VERDICT: APPROVED
steilerDev
left a comment
There was a problem hiding this comment.
[product-owner]
Verified PR #1454 against issue #1449 acceptance criteria.
Acceptance criteria — all met:
- AC #1 (quoted amount as single value on WI page) — PASS.
BudgetLineCard.tsxline 49 now rendersformatCurrency(line.actualCost)unconditionally; the* 0.95/* 1.05template-literal range is removed. - AC #2 (
--color-text-quotedtoken applied) — PASS.BudgetLineCard.module.css.amountQuotedand.quotedLabelboth usevar(--color-text-quoted); theme-specific overrides removed in favor of the semantic token. - AC #3 (non-quotation display unchanged) — PASS. The non-quotation branch in both
BudgetLineCardandInvoiceGroupstill rendersformatCurrency(line.actualCost)/formatCurrency(itemizedTotal)with.amountInvoiced/.amountValueclasses. - AC #4 (vendor on second line) — PASS.
InvoiceGroup.tsxintroduces.invoiceIdentityflex-column wrapper containing the invoice link on line 1 and.vendorNameon line 2; status badge stays on the same row as the identity block. - AC #5 (vendor smaller font) — PASS.
.vendorNamefont-size changed from--font-size-smto--font-size-xs, smaller than.invoiceNumber(--font-weight: 600, base size). - AC #6 (no second line when vendor null) — PASS.
{vendorName && <span className={styles.vendorName}>...}short-circuits cleanly inside.invoiceIdentity.
Out-of-scope guardrails: BudgetOverviewPage and CostBreakdownTable untouched (verified via git diff --name-only).
Bonus i18n fix: vendorDetail.invoicedAmount key added to both en/budget.json ("Invoiced Amount") and de/budget.json ("Rechnungsbetrag"), replacing the hardcoded 'Invoiced Amount' literal in BudgetLineCard.tsx and InvoiceGroup.tsx. Glossary-compliant.
E2E budget-vat-quotation-fixes.spec.ts updated to assert single €500.00 value and absence of any – range separator — good regression pin against both old broken states.
VERDICT: APPROVED
|
🎉 This PR is included in version 2.6.0-beta.22 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Summary
--color-text-quoteddesign token (CSS) and applies it inBudgetLineCardandInvoiceGroupto render invoiced/quoted amounts in a visually distinct muted color, clearly distinguishing them from actual spendInvoiceGroupfor improved readability and visual hierarchyvendorDetail.invoicedAmounti18n key to English and German (Rechnungsbetrag) locale filesBudgetLineCard.test.tsx(new file, 95%+ coverage) and updatesInvoiceGroup.test.tsxand E2E assertions inbudget-vat-quotation-fixes.spec.tsNotes
BudgetLineCardonly (in scope for feat(budget): quoted amount as single value with quoted-text color + vendor on second line #1449). TheCostBreakdownTableon the/budgetoverview page is unchanged — that is tracked as a separate follow-up.--color-text-quotedtoken entry was authored byux-designerin commit52fcbc3dbut the actual wiki page content edit was lost (local edit not pushed to the wiki submodule). A separate wiki housekeeping PR is needed to document the token in the Style Guide page post-merge.Fixes #1449
Test plan
BudgetLineCard.test.tsxandInvoiceGroup.test.tsx(95%+ coverage)budget-vat-quotation-fixes.spec.ts--color-text-quotedtoken renders correctly in light and dark modeCo-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com