Skip to content

fix(ui): bundle Material Symbols icon font locally instead of Google Fonts CDN#336

Merged
lshw54 merged 2 commits into
codefrom
fix/bundle-material-symbols-icons
Jul 10, 2026
Merged

fix(ui): bundle Material Symbols icon font locally instead of Google Fonts CDN#336
lshw54 merged 2 commits into
codefrom
fix/bundle-material-symbols-icons

Conversation

@lshw54

@lshw54 lshw54 commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

What

The login page (and the QR / region-picker pages) render UI icons via
.material-symbols-outlined font ligatures. The Material Symbols font was loaded
from fonts.googleapis.com (a <link> in index.html). On machines that are
offline — or on the TW/HK networks this launcher targets, where Google Fonts is
often slow or blocked — the font never loaded, so the ligatures fell back to raw
text (e.g. the QR / GamePass switch buttons showed qr_code_2 / passkey).

Fix

Bundle the font locally instead of relying on the CDN, subset to just the icons
we use:

  • Add scripts/subset-material-symbols.py, which produces a ~10 KB subset of the
    ~11 icons the app renders (it strips GSUB down to those ligatures, then subsets
    with layout closure — --text closure alone over-includes because the icon
    names collectively span most of the alphabet).
  • Ship the subset at src/assets/fonts/ and load it via a local
    src/styles/material-symbols.css @font-face + .material-symbols-outlined
    class; src/main.ts imports it. Remove the fonts.googleapis.com <link>
    from index.html.
  • material-symbols becomes a devDependency (the full-font source for the subset
    script only — not bundled at runtime).

Icons resolve offline; the in-bundle font is ~10 KB (down from the ~3.8 MB full
face). Verified in a Chromium render that all 11 icons shape to a single glyph
with no text fallback; prettier / eslint / vue-tsc / vitest (629 tests) all pass.

…Fonts CDN

The login/QR/region pages render icons via `.material-symbols-outlined` font
ligatures, but the font was loaded from fonts.googleapis.com. On machines that
are offline — or on the TW/HK networks this launcher targets, where Google Fonts
is often slow/blocked — the font never loaded and the icons fell back to raw
ligature text (qr_code_2, passkey, expand_more, ...).

Bundle the font in-app: add the `material-symbols` package, import its
`outlined.css` (ships the woff2 + the `.material-symbols-outlined` class) from
src/main.ts, and drop the CDN <link> from index.html. Icons now resolve offline.
Adds ~3.8 MB (one outlined woff2) to the bundle.
@lshw54 lshw54 self-assigned this Jul 10, 2026
Follow-up to bundling the icon font: instead of shipping the full ~3.8 MB
Material Symbols Outlined woff2, bundle a subset of only the ~11 icons the app
actually renders (login / QR / region-picker pages), cutting the in-bundle font
to ~10 KB.

- Add scripts/subset-material-symbols.py, which strips GSUB down to the icons'
  ligatures then subsets with layout closure (the `--text` closure alone
  over-includes because the icon names span most of the alphabet).
- Ship the subset at src/assets/fonts/ and load it via a local
  src/styles/material-symbols.css `@font-face` + the `.material-symbols-outlined`
  class (mirrors the upstream CSS; icons render via the font's rlig ligatures).
- main.ts imports the local CSS instead of `material-symbols/outlined.css`.
- Move `material-symbols` to devDependencies (now only the subset source).

Verified in a Chromium render: all 11 icons shape to a single glyph (24px), no
text fallback. Build emits only the ~10 KB woff2; the 3.8 MB font is no longer
bundled.
@lshw54
lshw54 merged commit 8a43223 into code Jul 10, 2026
3 checks passed
@lshw54
lshw54 deleted the fix/bundle-material-symbols-icons branch July 10, 2026 17:35
@lshw54 lshw54 linked an issue Jul 10, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

QR之類的圖標顯示錯誤

1 participant