Add Ledger and Band template families with decor primitives

Crimson Grid, Tangerine Ledger, Slate Band and Teal Swoosh are rebuilt from
the Canva PDFs with grid and band tables that survive page breaks,
full-bleed fixed bands, pennant tabs, gradient corner swooshes with
keep-outs, Carbon icon circles, and the user's logo in the measured slot
(knockout or white chip on the dark Slate band). Adds static Poppins
500-700 and Inter fonts. Thumbnails regenerated for all eight templates;
the item-count sweeps run in their own test file.
This commit is contained in:
2026-10-04 08:34:18 +05:30
parent 3f7c12b7dd
commit c95514ee8d
62 changed files with 4078 additions and 217 deletions
+19
View File
@@ -126,3 +126,22 @@ Everything can be built with View backgroundColor and borders. Svg is only neede
- Near-duplicate: 11.pdf ('Rimberio'). Same structure and placeholder copy: Invoice Number/Date, vendor and BILL TO columns, 4-column ruled grid with a coloured header row, NOTES/TERMS beside a ruled totals box, PAYMENT METHOD and PREPARED BY. Differences: orange accent, Inter body with a Poppins Bold title, mirrored header (name left, INVOICE right), filled Total row, corner shapes instead of the rule and footer band. Build 7 and 11 as one ruled-grid component with theme props (accent, fontFamily, headerMirror, totalRowFill, decoration set).
- Weaker resemblance: 2.pdf (ruled grid with a yellow header and a ruled total cell).
- None of 7/8/9 resembles the in-app InvoiceDocument.tsx (IBM Plex, hairline rules, title-left/meta-right). The closest in the set is 3.pdf. Not similar to format.pdf (identical to 4.pdf).
## Implementation notes
Built as `src/pdf/templates/ledger/` (one family component, `Layout.tsx`, shared with Tangerine Ledger; tokens in `crimson.tsx`, planning in `plan.ts`) on the decor primitives in `src/pdf/decor/`. Measured against `7.pdf` with `npm run templates:compare` (`/tmp/invoice-c4/compare-crimson-grid.png`, left Canva, right ours).
**Matches the design (measured, A4):** title baseline 100.6 pt at x 59.5, 43.8 pt Poppins Bold; the 1.5 pt #A00000 rule at y 128.85; meta baselines 173.6 / 192.3; party heading to first line 23.9 pt; BILL TO at x 304.3; table text at x 69.7, header row 42 pt (Canva 40.5 plus the 0.75 pt rules) and 40.5 pt single-line rows; header fill #A00000 with white inner verticals and a black outer box; the 63 pt full-bleed band; all colours exact.
**Intentional deviations, and why:**
- **Margins.** Top 53 and sides 59.55 as designed. The bottom margin floor is 26 pt plus a 53 pt footer reserve, so the flow is at least 79 pt (band 63 + 16) above the page bottom on every margin preset and on Letter. The footer text is placed by `chrome.bottom` (14 pt above the edge), inside the band whatever the preset.
- **Header.** Title and brand block are one row without `alignItems: flex-end` (lint bans it): the brand block is placed from the measured slot offsets. 'TAX INVOICE' (about 281 pt) shrinks to at most 60 % of its size before the brand block (at most 40 % of the width) is squeezed. A wordmark logo replaces the whole flame + name lockup; a mark logo sits left of the vendor name in 15.44 pt caps (13.7 pt gap); without a logo only the name shows.
- **Meta** adds 'Due Date:' and 'PO No:' lines (same 18.7 pt pitch); 'Invoice Number:' keeps the design's wording.
- **Parties.** The vendor block's heading is the vendor name in caps, followed by address, phone, e-mail, PAN and the GSTIN (slot). Canva's PREPARED BY (x 322.4, misaligned) is normalised to the BILL TO column (x 304.3) and renamed AUTHORISED SIGNATORY.
- **Table.** The grid is drawn as per-cell borders (`TableRows` `grid`), not lines over the text, so it survives page breaks: the header repeats with its rules and every row owns its bottom rule. An HSN/SAC column (at least 56 pt) appears on tax invoices. Unit Price shows '₹1,200.00/hr' on one line when it fits, else the amount over 'per hour' at 8.5 pt; the money columns are at least 100 / 45 / 100 pt and grow to their widest amount. Rows grow with wrapped descriptions (padY 12.55).
- **Totals box** is widened (about 210 pt: label at least 96, value at least 100) with 28 pt rows instead of 40.5, so Sub-Total, Discount, Taxable value, CGST/SGST (or UTGST, IGST via `Slot.TaxRows`) and Total fit. The Total row is bold 12 pt without a fill, as designed.
- **Notes / Terms** sit left of the totals box when they are at most 110 pt tall; longer notes flow below the table (a long note must never make the unbreakable totals block unplaceable). Amount in words and the reverse-charge line run full width under the box.
- **Closing.** Bank lines are 10.5 / 14.5 pt (not 12 / 16.5) so six lines fit; the signature is the user's image or the computer-generated line with the signatory name.
- **Footer band.** The contact line is 'email | phone' (no website field exists; the GSTIN is printed through its slot only) at 11 pt with 0.05 em tracking instead of 12.44 pt / 0.064 em, and is fitted to one line. The standard footer (supplier name, 'Generated with Voiced', Page n of N) is added inside the band in cream at 7 pt; the continuation band on pages 2+ is grey so it stays readable on white.
- **Letter.** The 49.9 pt deficit comes out of the rule gap (21.5 to 12), meta (31.4 to 20), party (22.3 to 14), table (27.4 to 16), totals (11.3 to 6) and notes (12 to 8) gaps, 50.4 pt in all; type and row padding are not scaled. The band stays 63 pt at the bottom edge.
- **Grid colour.** The Canva artefact (black top/bottom edges on cells 1 and 3 only) is normalised to a black outer box with white inner verticals in the header, as the doc recommends.
+17
View File
@@ -128,3 +128,20 @@ No raster XObjects. Everything is vector shapes plus live text.
- Near-duplicate: 10.pdf ('Liceria & Co.'). The body is identical: Date / Billed to / From, the full-bleed grey SERVICE-QTY-PRICE-TOTAL band, rule-separated rows, TOTAL with an accent dash, inline Payment method / Note. The header differs: teal/grey corner swoosh artwork instead of the slate and blue bands, a dark letter-spaced INVOICE on white, and NO. in the right column. 10 also has a 'Contact:' block instead of the icon footer. Build 9 and 10 as one component with header/decoration variants.
- Shares Montserrat and letter-spaced uppercase INVOICE/headers with format.pdf (identical to 4.pdf), but the structure is different.
- Does not resemble the in-app InvoiceDocument.tsx; the closest in the set is 3.pdf.
## Implementation notes
Built as `src/pdf/templates/band/` (one family component, `Layout.tsx`, shared with Teal Swoosh; tokens in `slate.tsx`, planning in `plan.ts`) on the decor primitives in `src/pdf/decor/`. Measured against `9.pdf` with `npm run templates:compare` (`/tmp/invoice-c4/compare-slate-band.png`, left Canva, right ours; also `-nologo` and the logo variants).
**Matches the design (measured, A4):** dark band 0-103.5, blue band to 157.35 (53.8 tall), INVOICE in Montserrat 800 30 pt with 0.224 em tracking at x 59.5; the name and 'NO.' baseline at 74.7 (Canva 74.4 / 74.8), the number right-aligned to the content edge; Date row baseline 193.4 (label and value share it); party heading to first line 21.3 pt; header band 58.3 tall and full bleed; table text at x 69.4 (the 9.8 pt inset) with 2.25 pt #C1C5CE rules from 69 to 526; TOTAL with the 41.85 x 3 pt dash on its baseline; the footer rule 86.7 pt above the page bottom.
**Intentional deviations, and why:**
- **Bands.** Both are first-page decor inside `FirstPageHeader`, full bleed from the page edges (so they also fill Letter and any margin preset); their heights follow the flow (page top margin + logo row + gap), so they stay glued to the logo row whatever the preset. They overlap by half a point so no viewer shows a seam.
- **Logo (dark surface).** The slot is the measured 25 x 31 mark / 99 x 31 lockup. A logo with alpha uses its white knockout; one without alpha sits on a white rounded chip (4 pt padding) drawn as decor behind it. A wordmark replaces the name; a mark keeps the vendor name beside it in white Medium 12.
- **Number and due date.** 'NO. {number}' in the band; 'Due:' goes in the right column of the Date row (the From column), 'PO No:' under Date.
- **Table.** SERVICE / QTY / PRICE / TOTAL with PRICE right-aligned (centred prices left a ragged edge); the HSN/SAC code is a 10 pt sub-line under the description; the rate unit is '/hr' on the same line or a second 10 pt line when it does not fit. Rows are 44 pt (padY 13.5 + the rule) instead of 52.5, the compact density the doc offers, so a Voiced invoice (longer supplier block, tax rows, words, bank) still fits a page; the header band keeps its 58.3 pt. Money columns are at least 55 / 95 / 105 pt and grow to their widest amount (a 12-digit amount does not overflow from 1 lakh up).
- **Totals.** The design has only TOTAL. A right-anchored stack (SUBTOTAL, DISCOUNT, TAXABLE VALUE, CGST/SGST or IGST via `Slot.TaxRows`, tracked Bold 11 labels over Regular 12 amounts, 20 pt pitch) and a thin rule sit above the TOTAL row; the amount in words runs full width below it.
- **Payment, note, signature.** 'Payment details:' is a label plus bank lines (the inline single value does not scale); the Note sits under it when it is at most 100 pt tall, else flows below the table; the signature (the user's image or the signatory name and the computer-generated line) is the right column.
- **Footer.** Circled Carbon icons (phone, e-mail instead of the globe because Voiced has no website field, location) with 1.2 pt rings, drawn as static Svg decor on every page. Decor is not audited, so each text is fitted to one line (phone, e-mail) or two with an ellipsis (address); the full address is printed in the From block. The standard footer (name, 'Generated with Voiced', Page n of N) is added below the icons in grey 7 pt.
- **Margins.** Top 55.75 (the logo top), sides 59.55, bottom floor 20 plus a 79 pt reserve: the flow ends at least 99 pt above the page bottom (rule 86.7 + 12), on every preset.
- **Letter.** The 49.9 pt deficit comes out of the band's bottom padding (16.5 to 8), the gaps to the date row, parties and table, and the gap above the totals (54 pt of slack); type, rows and the header band are not scaled.
+16
View File
@@ -197,3 +197,19 @@ Near-duplicate of 9.pdf. Both use the same Montserrat type scale, and these elem
- Payment method and Note.
9.pdf swaps the swooshes for a slate top bar (logo plus NO.), a blue full-width 'INVOICE' band and an icon contact footer. 10.pdf has a logo/brand row, swoosh corners and a 'Contact:' block. Build 9 and 10 as one layout component with a header/decor variant. Not related to format.pdf or the current IBM Plex in-app template.
## Implementation notes
Built as `src/pdf/templates/band/` (the family component shared with Slate Band; tokens in `teal.tsx`) on the decor primitives in `src/pdf/decor/` (`CornerSwoosh`, with `LinearGradient` fills and keep-out rectangles). Measured against `10.pdf` with `npm run templates:compare` (`/tmp/invoice-c4/compare-teal-swoosh.png`, left Canva, right ours).
**Matches the design (measured, A4):** logo mark at (59.5, 59.5); INVOICE in Montserrat 800 30 pt with 0.26 em tracking, baseline 144; Date and 'NO.' on one row (x 59.5 and 342), Billed to / From at x 59.5 / 342 (270.5 and 193.7 wide); the full-bleed #EFF1F2 header band 58.3 tall, 2.25 pt #C2C7CF rules; the teal / gunmetal / silver corner art at the design's coordinates (the paths are the spec's, mirrored numerically for the top-right cluster, gradients flipped with them).
**Intentional deviations, and why:**
- **Swooshes.** Static Svg paths with gradients in a single `Defs` (react-pdf resolves `url(#id)` from the first direct `Defs` only), anchored to the page corners (`left 0 / bottom 0`, `right 0 / top 0`, 342 x 188 pt), so they also fit Letter. The bottom-left cluster is fixed on every page. The top-right cluster is **page 1 only** (it sits in `FirstPageHeader`): on pages 2+ the table band starts at the top margin right under where the crescent would be, and the flow may not enter a keep-out. The gradient stops (dark at the teal edge, a highlight about two thirds along, dark again at the page edge) were read off the rendered original; the doc lists only the colours.
- **Keep-outs.** Staircases of 8 pt strips follow the silver crescent's inner edge plus 4 pt, per corner (bottom-left on every page, top-right on page 1); the audit's `keepout` check runs against them for text, images and Svg, fixed chrome included. The bottom padding is 110 pt so the flow stays above the crescent on every page and size; the footer text starts at x 200 (right of the crescent at the footer's height, no supplier name there), and the continuation band keeps its normal place.
- **Header.** The brand block stays left of x 440 (the design's limit): a mark logo has the vendor name beside it at 13 pt Bold (the design's 10.75 pt is a short placeholder), wrapping to more lines when long; a wordmark replaces the name; the tagline slot is dropped.
- **Meta.** Left column: Date, then 'Due:'; right column: 'NO. {number}', then 'PO:'. (The design's second meta line is added; everything below shifts down by one line, 16.5 pt.)
- **Table, totals.** As for Slate Band (docs/templates/09-slate-band.md): PRICE and TOTAL right-aligned, HSN/SAC as a sub-line, 44 pt rows instead of 52.5, a right-anchored stack of SUBTOTAL / DISCOUNT / TAXABLE VALUE / CGST+SGST (or IGST) above TOTAL with the 41.85 x 3 pt teal dash on its baseline, amount in words under it.
- **Bottom block.** The bank details (headed 'Payment details:') take the 'Contact:' column on the right (x 345-526, 181 pt), with the signature below; the Note sits bottom left when it is at most 100 pt tall, else flows below the table. Vendor phone and e-mail are in the From block, so 'Contact:' is not repeated.
- **Margins.** Top 55, sides 59.55, bottom floor 24 plus an 86 pt reserve (110 in all).
- **Letter.** The 49.9 pt deficit comes out of the brand-to-title gap (26.2 to 14), the gaps to the date row, parties, table and totals (58 pt of slack); rows, bands and the art keep their size.
+14
View File
@@ -173,3 +173,17 @@ Near-duplicate of 7.pdf. Both carry the same 'Studio Shodwe' content and the sam
Differences: 7.pdf uses Poppins for body text, a dark-red accent, a flame logo at top-right, a red rule under the header and a full-width red contact footer band. 11.pdf uses Inter body, #FF5F2F, brand text at left and edge tabs.
Build one 'Ledger Grid' component with an accent colour and a decor variant (tabs or footer band). Of 10–13, this is structurally closest to the current in-app template. Unrelated to format.pdf.
## Implementation notes
Built as `src/pdf/templates/ledger/` (the family component shared with Crimson Grid; tokens in `tangerine.tsx`) on the decor primitives in `src/pdf/decor/` (`Pennant`). Measured against `11.pdf` with `npm run templates:compare` (`/tmp/invoice-c4/compare-tangerine-ledger.png`, left Canva, right ours).
**Matches the design (measured, A4):** INVOICE baseline 80.6 pt, right edge on the content edge (536.7), Poppins Bold 33; 'Invoice Number' / 'Invoice Date' baselines 168.6 / 187.3 (Canva 168.7 / 187.4); party headings at x 59.5 and 284.1, 23.9 pt above the first line; table header and row pitch (header 41.5 pt single-line incl. rules, rows 37.5); accent #FF5F2F header, filled Total row with white separators; both pennant tabs at the design's coordinates.
**Intentional deviations, and why:**
- **Margins.** Top 46 pt: Poppins's tall ascent puts the 33 pt title's box top 11.5 pt above the cap top, so the box (not the ink) starts at the margin. Sides 59.55 with a floor of 45 on every preset, so Narrow (36) never puts text under the 35 pt tabs. Bottom 60 + 16 footer reserve.
- **Header.** The brand zone is the measured 220 x 36 allowance at y 62-98. A wordmark logo replaces the 'Rimberio' text; a mark logo sits left of the vendor name in Poppins Bold 18; without a logo the name stands in. The brand block is at most half the content width, the title shrinks to at most 60 % before it would meet it.
- **Tabs.** Two static Svg paths anchored to the page corners (top right 35.1 x 230.5, bottom left 35.3 x 218.6), fixed on every page; the Canva paths are simplified to their visible part with the same curves. They keep their size on Letter.
- **Meta, parties, table, totals, notes, closing, elastic gaps:** as for Crimson Grid (docs/templates/07-crimson-grid.md), with Tangerine's own numbers: meta gap 59 to 32, party 20.8 to 12, table 25.4 to 14, totals 23.3 to 10 (64 pt of slack on Letter), cell padX 9.8, padY 10.8, totals box at least 205 pt. The Total row is filled with the accent (white 12 pt Inter Bold, white separator).
- **Type.** Poppins 700 for brand and title, Inter 400/600/700 for the rest (static TTFs; Inter and Poppins both carry U+20B9, Plex still ends every stack). Inter's strongly kerned pairs ('7,', '7.') make pdf.js report an amount as two text items; the text is unchanged and the harness joins such fragments before checking the rupee sign.
- **Footer.** The standard footer (supplier name, 'Generated with Voiced', Page n of N) at 7 pt in grey; the design has none. The left tab (x 0-35.3) clears the footer at x 59.5 by 24 pt.