From d914ff5da3020d0bfbb15818884f6d947834b88e Mon Sep 17 00:00:00 2001 From: pcarter Date: Thu, 23 Apr 2026 13:48:21 -0700 Subject: [PATCH] fix horizontal line rendering --- src/app/globals.css | 4 ++++ src/components/AttachmentList.tsx | 3 +++ src/components/EmailBody.tsx | 3 +++ src/components/SpreadsheetViewer.tsx | 3 +++ src/components/useBodyClass.ts | 29 ++++++++++++++++++++++++++++ 5 files changed, 42 insertions(+) create mode 100644 src/components/useBodyClass.ts diff --git a/src/app/globals.css b/src/app/globals.css index 01b0518..b31216d 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -79,6 +79,10 @@ body::after { ); } +body.rich-content-open::after { + display: none; +} + /* Dark mode: subtle phosphor glow on body text */ @media (prefers-color-scheme: dark) { body { diff --git a/src/components/AttachmentList.tsx b/src/components/AttachmentList.tsx index c977a1b..89efe92 100644 --- a/src/components/AttachmentList.tsx +++ b/src/components/AttachmentList.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from "react"; import SpreadsheetViewer from "@/components/SpreadsheetViewer"; +import useBodyClass from "@/components/useBodyClass"; import { isSpreadsheetAttachment } from "@/lib/spreadsheet"; import { EmailBodyPart } from "@/lib/types"; @@ -39,6 +40,8 @@ interface PdfModalProps { function PdfModal({ attachment, onClose }: PdfModalProps) { const name = attachment.name ?? "document.pdf"; + useBodyClass("rich-content-open"); + useEffect(() => { function onKey(e: KeyboardEvent) { if (e.key === "Escape") onClose(); diff --git a/src/components/EmailBody.tsx b/src/components/EmailBody.tsx index e497ee8..3fad073 100644 --- a/src/components/EmailBody.tsx +++ b/src/components/EmailBody.tsx @@ -1,6 +1,7 @@ "use client"; import { useEffect, useRef } from "react"; +import useBodyClass from "@/components/useBodyClass"; import { prepareHtml, prepareTextBody } from "@/lib/emailHtml"; interface Props { @@ -14,6 +15,8 @@ export default function EmailBody({ body, type, stripQuotes }: Props) { const iframeRef = useRef(null); const lastDimsRef = useRef({ h: 0, w: 0 }); + useBodyClass("rich-content-open"); + useEffect(() => { lastDimsRef.current = { h: 0, w: 0 }; }, [body, type]); diff --git a/src/components/SpreadsheetViewer.tsx b/src/components/SpreadsheetViewer.tsx index 8cfff4f..c04ecd7 100644 --- a/src/components/SpreadsheetViewer.tsx +++ b/src/components/SpreadsheetViewer.tsx @@ -8,6 +8,7 @@ import { columnNumberToName, parseSpreadsheetWorkbook, } from "@/lib/spreadsheet"; +import useBodyClass from "@/components/useBodyClass"; interface Props { attachmentName?: string; @@ -37,6 +38,8 @@ export default function SpreadsheetViewer({ const [activeSheetIndex, setActiveSheetIndex] = useState(0); const [loading, setLoading] = useState(true); + useBodyClass("rich-content-open"); + useEffect(() => { if (!onClose) return; const close = onClose; diff --git a/src/components/useBodyClass.ts b/src/components/useBodyClass.ts new file mode 100644 index 0000000..f182700 --- /dev/null +++ b/src/components/useBodyClass.ts @@ -0,0 +1,29 @@ +"use client"; + +import { useEffect } from "react"; + +const bodyClassCounts = new Map(); + +export default function useBodyClass(className: string) { + useEffect(() => { + const body = document.body; + if (!body) return; + + const nextCount = (bodyClassCounts.get(className) ?? 0) + 1; + bodyClassCounts.set(className, nextCount); + if (nextCount === 1) { + body.classList.add(className); + } + + return () => { + const currentCount = bodyClassCounts.get(className) ?? 0; + if (currentCount <= 1) { + bodyClassCounts.delete(className); + body.classList.remove(className); + return; + } + + bodyClassCounts.set(className, currentCount - 1); + }; + }, [className]); +} -- 2.51.2