From 6d1f25045e6c16e8265ab8f284af616d7fccdca9 Mon Sep 17 00:00:00 2001 From: Barak Korren Date: Thu, 14 May 2026 08:59:44 +0300 Subject: [PATCH] docs(plans): spec for web icon fonts (issue #818) Add headless spec-start artifacts for migrating UI chrome from inline SVG to icon fonts, with exceptions for bespoke/brand graphics. Refs #818 Co-authored-by: Cursor --- .../2026-05-14-web-icon-fonts-for-ui/qna.md | 39 ++++++ .../2026-05-14-web-icon-fonts-for-ui/spec.md | 120 ++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 docs/plans/2026-05-14-web-icon-fonts-for-ui/qna.md create mode 100644 docs/plans/2026-05-14-web-icon-fonts-for-ui/spec.md diff --git a/docs/plans/2026-05-14-web-icon-fonts-for-ui/qna.md b/docs/plans/2026-05-14-web-icon-fonts-for-ui/qna.md new file mode 100644 index 000000000..0bd1ca891 --- /dev/null +++ b/docs/plans/2026-05-14-web-icon-fonts-for-ui/qna.md @@ -0,0 +1,39 @@ +# Q&A — web icon fonts for UI + +## Q-01 — Which icon font family should be canonical? + +- **Kind:** open +- **Detail:** The issue asks for icon fonts but does not pick a vendor. Triage suggested Material Symbols, Font Awesome, Lucide, Heroicons, or other. Lucide/Heroicons are commonly shipped as SVG components; adapting them to a font may be non-standard compared to first-party variable fonts. +- **Suggested resolution:** Product owner picks one primary family (variable font preferred) and one fallback; record license + self-host decision in the implementation ADR or PR description. + +### Answer — example only (template) + +_(This `###` block demonstrates the answer shape for future discussion threads. Replace with a real decision link or permalink when available.)_ + +Optional permalink line: `https://github.com/fullsend-ai/fullsend/issues/818#issuecomment-4428555502` + +## Q-02 — What stays SVG on purpose? + +- **Kind:** assumption +- **Detail:** Graph visualization and other data-bound vector art should remain SVG (or canvas) rather than being forced into a font. +- **Confidence:** high +- **Blast radius if wrong:** Wasted effort trying to encode complex paths as fonts, or broken visuals if graph code is “simplified” incorrectly. + +## Q-03 — How strict is “no inline SVG” for admin/docs chrome? + +- **Kind:** scope +- **Detail:** Strict reading: all static chrome icons move to the font system. Pragmatic reading: brand marks that must follow third-party guidelines may remain inline SVG or `` even when a font glyph exists. +- **Proposed handling:** Adopt the pragmatic boundary; list allowed SVG exceptions in developer docs to avoid drift. + +## Q-04 — Subsetting and build-time manifest ownership + +- **Kind:** open +- **Detail:** Subsetting reduces bytes but needs an owner for the manifest of allowed icon names and CI enforcement. +- **Suggested resolution:** Web platform owner defines manifest location (for example colocated with `UiIcon`) and adds a small unit test or script invoked from `npm test` / `make lint` as appropriate. + +## Q-05 — Fork / sparse web tree vs upstream triage inventory + +- **Kind:** assumption +- **Detail:** This spec references triage’s list of SVG-heavy areas; the local checkout used for spec-start may have fewer Svelte files than upstream at times. Implementation should re-audit `web/**` for actual `` usage at merge time. +- **Confidence:** medium +- **Blast radius if wrong:** Missed migration targets or unnecessary font work on unused components. diff --git a/docs/plans/2026-05-14-web-icon-fonts-for-ui/spec.md b/docs/plans/2026-05-14-web-icon-fonts-for-ui/spec.md new file mode 100644 index 000000000..846ffc361 --- /dev/null +++ b/docs/plans/2026-05-14-web-icon-fonts-for-ui/spec.md @@ -0,0 +1,120 @@ +# Web UIs: adopt icon fonts instead of embedded SVGs + +**Status:** Speculative (spec-start; headless) + +## Context + +- **Issue:** [fullsend-ai/fullsend#818](https://github.com/fullsend-ai/fullsend/issues/818) — *Change "icons" in web UIs to use an icon font rather then embed raw SVGs* +- **Issue body:** Moving to an icon font should improve styling control and reduce bytes on the wire compared to repeating inline SVG markup. +- **Labels / triage:** The issue is marked **needs-info**. Triage notes (GitHub comment, 2026-05-12) describe current inline SVG usage across the docs site (for example close / hamburger controls), tree navigation folder/document glyphs, the GitHub mark in the admin dashboard, and dynamically generated SVG in graph visualization. This spec treats that inventory as the **expected baseline** for the upstream product even if a given checkout has a smaller Svelte surface at the moment. +- **Human comment:** A maintainer signaled openness to Font Awesome but did not pick a standard; library choice remains open. + +## Goals + +- Replace **decorative / UI chrome** icons that today ship as inline SVG in Svelte (or equivalent) with **icon-font–based rendering** so color, size, and weight track typography and CSS with minimal duplicated markup. +- Cut **wire and DOM weight** for repeated icons (one font + short ligature/PUA markup vs many duplicated `` trees), subject to font subsetting and caching strategy. +- Establish a **single house style** for icon usage across `web/docs`, `web/admin`, and any other first-party web surfaces, including accessibility conventions (exposed name, decorative vs informative). + +## Non-goals + +- Rewriting **data-driven** or **bespoke** visuals (for example graph layout edges/nodes, charts, or illustrations) as icon fonts when SVG remains the correct model—those may stay SVG or move to a different abstraction, but are not required to become font glyphs. +- Choosing **npm package names and exact import paths** in this spec (implementation PR picks versions and pins licenses). +- Internationalizing **third-party** brand marks beyond what license and trademark policy already require. + +## Architectural approach (options) + +### Option A — Variable icon font (Material Symbols–style) + +**Idea:** Load one variable font (WOFF2), map icons via ligatures or codepoints, style with `font-variation-settings` / axes (weight, fill, optical size). + +**Pros:** Large catalog; strong alignment with “icon font” wording; one network artifact after first load; very flexible styling. + +**Cons:** Heavier than a tight subset until subsetting is configured; Google-fonts vs self-host trade-offs; brand icons may still be exceptions. + +### Option B — Classic webfont pack (Font Awesome–style) + +**Idea:** Use a familiar webfont with documented Unicode / class conventions; subset to used glyphs in the build. + +**Pros:** Well-understood ergonomics; predictable licensing tiers; tooling for subsetting. + +**Cons:** Less expressive than variable-font axes unless using newer FA variable builds; bundle/licensing choices need explicit approval. + +### Option C — SVG sprite sheet + currentcolor (not an icon font) + +**Idea:** Centralize SVGs as `` defs or external sprite, reference via ``. + +**Pros:** Crisp at all sizes; easy for one-off brand paths. + +**Cons:** Does **not** satisfy the issue’s request for an **icon font**; keeps more DOM for repeated icons than a font + single codepoint per icon. + +### Recommendation + +**Lead with Option A (variable icon font)** for the majority of UI chrome, paired with a **narrow exception list** for glyphs that are poor font fits (for example the GitHub mark if trademark guidance prefers the official SVG, and graph primitives). Where Option A’s licensing or operational constraints bite, **Option B** is the fallback without changing the overall “font for chrome icons” direction. + +**Explicitly deferred:** swapping every bespoke graph SVG for font glyphs (likely infeasible); any broad redesign of the graph renderer. + +## Components and responsibilities + +| Area | Responsibility | +|------|------------------| +| **Font delivery** | Self-hosted WOFF2 in-repo or via locked CDN URL per security/CSP posture; cache headers and preload hints as appropriate for Vite builds. | +| **Svelte integration** | Thin wrapper component (for example ``) that renders the correct element (`` with text / ligature or PUA) and forwards `class` / `style` / ARIA. | +| **CSS contract** | Document how consumers set size (`font-size`), color (`color` / `currentColor`), and weight/fill axes for variable fonts. | +| **A11y** | Decorative icons: `aria-hidden="true"`; informative icons: `aria-label` or visually hidden text—mirror whatever patterns exist today for SVG titles. | +| **Build / subsetting** | CI or build step lists allowed icon names → shrinks font payload; fail closed when requesting unknown names in dev. | + +## Data flow (runtime) + +1. App shell loads icon stylesheet + font once per navigation session (or per deploy hash). +2. Components request icons by **stable logical name** (not raw codepoint) through the wrapper. +3. CSS maps logical name → glyph (ligature table or `::before { content }` with escaped codepoint). + +```mermaid +flowchart LR + subgraph build [Build] + Names[Icon name manifest] --> Subset[Subset / pick font] + Subset --> Assets[WOFF2 + CSS] + end + subgraph runtime [Runtime] + Assets --> Shell[App shell] + Shell --> Cmp[Svelte UiIcon] + Cmp --> DOM[Span / pseudo-element] + end +``` + +## Error handling and edge cases + +- **Missing glyph:** Dev-time console warning + visible placeholder; production build should fail CI if manifest references unknown name. +- **CSP:** Font and stylesheet hosts must match documented CSP allowlist; avoid inline `@font-face` if policy forbids. +- **Dark mode / themes:** Icons inherit `color`; verify contrast for outline vs filled variants when using variable axes. + +## Security / licensing + +- Confirm **font license** allows redistribution/self-hosting for the chosen pack. +- **Third-party logos** (GitHub): comply with brand guidelines; prefer retaining SVG where required rather than forcing a font glyph. + +## Testing strategy + +- **Visual smoke:** Representative pages in docs and admin with icons at default and large `font-size`. +- **Accessibility:** Quick axe or manual screen-reader pass on nav toggles and inline “icon only” buttons. +- **Bundle:** Compare hashed font + CSS size vs previous inline SVG aggregate for a few hot routes (rough budget, not a hard gate unless maintainers want one). + +## Rollout + +1. Land font + wrapper + CSS behind no flag if risk is low; otherwise a short-lived feature flag only if parallel maintenance is otherwise unavoidable (prefer direct migration for small surfaces). +2. Migrate high-repeat icons first (nav toggles, tree chevrons), then long tail. +3. Document contributor guidance in `web/README.md` or adjacent developer docs: when to use `UiIcon`, when to keep SVG. + +## References + +- Issue: https://github.com/fullsend-ai/fullsend/issues/818 +- Triage comment on the issue (2026-05-12) summarizing SVG call sites. +- `package.json` / Vite workspace for current web build layout. + +## Q&A index + +- [Q-01 — Which icon font family should be canonical?](./qna.md#q-01--which-icon-font-family-should-be-canonical) +- [Q-02 — What stays SVG on purpose?](./qna.md#q-02--what-stays-svg-on-purpose) +- [Q-03 — How strict is “no inline SVG” for admin/docs chrome?](./qna.md#q-03--how-strict-is-no-inline-svg-for-admindocs-chrome) +- [Q-04 — Subsetting and build-time manifest ownership](./qna.md#q-04--subsetting-and-build-time-manifest-ownership) +- [Q-05 — Fork / sparse web tree vs upstream triage inventory](./qna.md#q-05--fork--sparse-web-tree-vs-upstream-triage-inventory)