Task #303: DIN Next LT Arabic site default + working font picker

User report: "the dropdown for changing the site font does not work."
Root cause: FontSettingsSection listed Cairo / Tajawal / Noto Naskh
Arabic / Amiri, but only Tajawal had been registered with @font-face.
Picking the others was a no-op. Site default body font was also not
DIN Next LT Arabic as designed.

Changes:
- artifacts/tx-os/src/index.css: --app-font-sans now starts with
  "DIN Next LT Arabic"; dropped IBM Plex Mono.
- artifacts/tx-os/index.html: removed Google Fonts <link> + preconnect.
- artifacts/tx-os/src/pages/executive-meetings.tsx: FontSettingsSection
  dropdown replaced with the 5 actually-bundled families + system.
- artifacts/api-server/src/routes/executive-meetings.ts: FONT_FAMILIES
  Zod allowlist updated to match.
- artifacts/api-server/src/lib/sanitize.ts: FONT_NAME_PART regex now
  allows the new families (kept IBM Plex Sans Arabic for backward
  compat). Fixes a latent bug from #301 where the rich-text sanitizer
  silently stripped attendee font picks on save.
- artifacts/api-server/src/lib/pdf-renderer.ts: FAMILY_MAP and
  ARABIC_FONT_NAMES updated. Sans-style families map to the bundled
  NotoSansArabic; Naskh-style families to NotoNaskhArabic.
- artifacts/api-server/tests/executive-meetings.test.mjs: PDF
  sans-vs-naskh assertion updated from Cairo/Noto Naskh Arabic to
  DIN Next LT Arabic/Majalla, preserving its semantics. Other
  Cairo/Noto Naskh Arabic occurrences swapped to the new names.
- replit.md: documented site default font + lockstep allowlist rule.

Deviations from plan: kept DEFAULT_FONT.fontFamily = "system" on the
frontend (and the backend Zod default) instead of changing it to
"DIN Next LT Arabic". "system" semantically means "no override → use
the CSS default", which is now DIN Next LT Arabic — same end result
without forcing a migration on existing rows. The sanitizer change
was not in the original plan but was required to make the picker
actually persist.

Verification:
- Frontend tsc clean.
- Backend tsc shows the same pre-existing unrelated errors as before
  (isHighlighted boolean/number; Drizzle scope typing).
- E2E browser test verified all 7 assertions: site default font,
  no Google Fonts requests, exactly 6 dropdown options, font picker
  applies + reverts correctly, attendee font picks persist after save.
- Code review verdict: PASS.
This commit is contained in:
riyadhafraa
2026-05-01 19:55:39 +00:00
parent ef65af248f
commit 471c480824
11 changed files with 95 additions and 33 deletions
+1 -1
View File
@@ -43,7 +43,7 @@ The project is structured as a pnpm monorepo.
- **Executive Meetings Module**: A comprehensive module with scheduling, CRUD operations for meetings, change requests, approvals, tasks, notifications, and an audit log. RBAC is enforced via five role sets (READ/MUTATE/APPROVE/REQUEST/ADMIN_AUDIT). All mutations are wrapped in database transactions to ensure data consistency and atomic audit logging.
- **Optimistic Locking**: Implemented for Executive Meeting postponements to prevent concurrent updates from silently overwriting changes, using `expectedUpdatedAt` and returning a 409 conflict on mismatch.
- **Upcoming Meeting Alert**: A global, draggable alert component appears when an Executive Meeting is within five minutes of starting, providing options to postpone, reschedule, or cancel the meeting.
- **Custom Editor Fonts**: The in-place rich-text cell editor (attendee names, meeting titles, etc.) ships a curated set of self-hosted Arabic + Latin font families (DIN Next LT Arabic, Tajawal, Helvetica Neue LT Arabic, Helvetica Neue, Majalla) declared in `artifacts/tx-os/src/custom-fonts.css` with `font-display: swap`. Files live under `artifacts/tx-os/public/fonts/`.
- **Custom Editor Fonts**: The in-place rich-text cell editor (attendee names, meeting titles, etc.) ships a curated set of self-hosted Arabic + Latin font families (DIN Next LT Arabic, Tajawal, Helvetica Neue LT Arabic, Helvetica Neue, Majalla) declared in `artifacts/tx-os/src/custom-fonts.css` with `font-display: swap`. Files live under `artifacts/tx-os/public/fonts/`. The site default body font is **DIN Next LT Arabic** (`--app-font-sans` in `index.css`), and Google Fonts is no longer fetched at page load. The Executive Meetings **Font Settings** page exposes the same five families plus `system` as the user/global picker; the values are kept in lockstep with the backend Zod allowlist (`FONT_FAMILIES` in `routes/executive-meetings.ts`), the rich-text sanitizer's font-family allowlist (`FONT_NAME_PART` in `lib/sanitize.ts`), and the PDF renderer's family map (`FAMILY_MAP` in `lib/pdf-renderer.ts`). When adding or removing a family, update all four locations together.
- **Tab Quick-Add Attendees**: Pressing Tab inside an attendee name cell commits the current value and immediately opens a new pending attendee row right after, so users can keep typing names without using the mouse. Implemented via an `onTabNext` prop on `EditableCell` and a `chainStartAdd` prop on `AttendeeFlow` that bypasses the single-pending UI gate (the parent's state-level guard still prevents truly overlapping pendings).
### Feature Specifications