Skip to content

feat(templates): add the Workspace SaaS invoice preset - #641

Merged
DemchaAV merged 1 commit into
feature/template-promotionfrom
feat/workspace-invoice-preset
Sep 1, 2026
Merged

DemchaAV merged 1 commit into
feature/template-promotionfrom
feat/workspace-invoice-preset

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Why

slack-invoice is the second bundle whose source carries a real company's identity, and
the second invoice built to paginate. It follows the pattern #638 set: the layout is
ported in full, the identity is not
.

What

invoice.presets.WorkspaceInvoice on the existing StructuredInvoiceData model, on top
of the recipient registration added in #640.

De-branded

Two assets, both dropped:

  • brand-lockup.svg was the real Slack wordmark (logos:slack) and
    item-brand-mark.svg its glyph, which the design draws bare on one service line while
    every other mark sits on a coloured tile. Neither is ported.
  • The bare-mark rule survives without it: a packaged token that the design gives no
    tile colour is drawn bare, so the behaviour is general rather than tied to one mark.
  • The other eight glyphs are stock Material icons; only their token names were
    product-flavoured (item-key-management, item-workflow, item-support), so they are
    renamed to what they draw: search, grid, shield.
  • The legal entity, the product names and the closing words were always data. The
    shipped sample is neutral.

Money, the other way round

PaymentsInvoice carries a currency symbol on every figure. This design does the
opposite: it names the currency once per money column and writes the figures under it
bare, putting the code only on the total (USD 587.50). The preset follows its own
design rather than its sibling, and a quantity is written with what it counts
(50 Users) from the model's quantity and unit.

Two measured type corrections

A cap read off a screenshot includes about half a pixel of antialiasing on each edge and
the whole of it lands in the size, so sizeForCap takes it back off. And the body face
sets uppercase about 6% wider than the design's at the same cap height — measured across
three all-caps runs, while mixed-case runs at the same sizes matched within 2% — so
sizeForCaps carries that as a size correction. There is no letter-spacing API to take
it out with instead.

Tests

  • Pixel parity against the bundle: 8 115 of 2 173 720 differing pixels, and the heat
    map has exactly two bands
    x 45..256, y 46..99 (the lockup box, 7 285 px) and
    x 60..91, y 724..755 (a 31 × 31 square at the first line's mark, 830 px). Both are
    the marks deliberately not shipped. The accent bar, the issuer block, the metadata
    grid and its divider, both parties and their discs, all four table rows including the
    three tiled marks, the payment card, the totals, the accent rule, the due panel, the
    thank-you block and the closing band are pixel-identical; 207 layout nodes, and the
    text layer differs only by the wordmark.
  • The bundle also freezes to 0 against its own published preview on both its pinned
    engine (2.2.2) and 2.2.3-SNAPSHOT, so there is no engine drift to account for.
  • WorkspaceInvoiceSmokeTest — 16 cases: the packaged marks, the unknown-mark data
    error, a line with no mark, the wordmark fallback, the currency named once and not on
    every figure, the quantity with its unit, both parties' registrations and the absent
    one, the closing address as an annotation, a missing ship-to, a payment card with no
    note, an empty document, and a thirty-line invoice that runs on, repeats its column
    names on page two and numbers its pages.
  • WorkspaceInvoiceLayoutSnapshotTest — exact geometry, one page.
  • WorkspaceInvoiceVisualParityTest — pixel baseline; recorded without disturbing any
    other baseline in the suite.
  • Full reactor gate green, and the examples suite (77 tests) run separately because the
    reactor gate does not cover it — the committed preview is rendered from a full
    install of this branch, so the catalogue's drift test passes.
  • The showcase gains invoice-workspace-v2.

A violet-accented sheet: a brand masthead over a short accent bar, a
half-split issuer and metadata header, two addressed parties on filled
discs, a service-line table whose marks sit on coloured tiles, a
settlement row pairing the bank details against the totals, and a closing
band carrying the wordmark.

Ships as invoice.presets.WorkspaceInvoice on the existing
StructuredInvoiceData model. Like PaymentsInvoice it flows: the table's
header repeats, a continuation page reserves a deeper bottom margin, and
every page carries its number. The design's own closing band cannot be
page chrome — a header footer zone takes only strings and the band holds
a wordmark and a link — so it is body content and the number is the only
chrome.

This design states its currency once per money column and writes the
figures under it bare, carrying the code only on the total, which is the
opposite of what PaymentsInvoice does; a quantity is written with what it
counts. Both parties print a registration under their address, and one
with no number prints no label.

Two of the design's type corrections are carried as measured constants:
half a pixel of screenshot antialiasing in every cap, and the 6% the body
face adds to an all-caps run at the same cap height.

Guarded by a 16-case smoke test, an exact layout snapshot and a
pixel-parity gate.
@DemchaAV
DemchaAV merged commit 0300249 into feature/template-promotion Sep 1, 2026
12 checks passed
@DemchaAV
DemchaAV deleted the feat/workspace-invoice-preset branch September 1, 2026 08:53
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.

1 participant