Make the UI font configurable - #6
Merged
Merged
Conversation
Adds a font picker at the bottom of the sidebar, next to the theme toggle, offering Public Sans (the new default), Barlow, General Sans, Inter, Manrope, and the OS UI font. Hosts set the default everyone starts on with `config.ui_font`; each user's own pick is remembered in localStorage and overrides it. The face is a `data-font` stamp on <html>, rendered server-side so the first paint is already correct. Only the `[data-font]` blocks in input.css name a family — every other rule reads --font-ui — so switching is one attribute write, with no reload and no stylesheet swap. Fonts are no longer inlined as base64 data: URIs. `rake assets:build` now copies each vendored woff2 into the manifest under a digest name and emits @font-face rules with relative url()s, which resolve against the stylesheet's own URL and so survive any mount path. A browser downloads only the face it renders in, and the stylesheet drops from 118KB to 31KB despite offering four more families. Inter, Manrope and Public Sans are served by Google as variable fonts, so those ship as a single file declaring the weight range it covers rather than three static instances. General Sans is not on Google Fonts and comes from Fontshare; FONT-LICENSES.md records what each face is licensed under. test/ui_fonts_test.rb fails if a face is missing from the registry, the stylesheet or the vendored files, and the system tests assert via document.fonts.check that every offered face really loads rather than silently falling back to system-ui. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a font picker at the bottom of the sidebar, next to the theme toggle, and stops inlining fonts in the stylesheet.
What you get
Six choices: Public Sans (the new default), Barlow, General Sans, Inter, Manrope, and System (the OS UI font, no webfont downloaded). Hosts set the default everyone starts on:
Anything not offered raises in the initializer rather than falling back silently. Each user's own pick is remembered in
localStorageand overrides the default. The mono face (IBM Plex Mono) stays fixed — the job tables depend on its tabular figures.How it works
The face is a
data-fontstamp on<html>, rendered server-side so the first paint is already correct. Only the[data-font]blocks ininput.cssname a family; every other rule reads--font-ui. Switching is therefore one attribute write — no reload, no stylesheet swap, no font-loading JS.Fonts are no longer base64 data: URIs.
rake assets:buildcopies each vendored woff2 into the manifest under a digest name and emits@font-facerules with relativeurl()s, which resolve against the stylesheet's own URL and so stay correct under any mount path. A browser downloads only the face it renders in, and the stylesheet drops 118KB → 31KB despite offering four more families.AssetsControllerneeded no change — the manifest whitelist still guarantees a request can never name a file that was not built.Inter, Manrope and Public Sans are served by Google as variable fonts, so those ship as a single file declaring the weight range it covers rather than three static instances.
Notes for review
FONT-LICENSES.mdrecords what each face is under. Worth confirming before release — dropping the face is aLABELSentry, a CSS block and a rebuild.opacity: 0. Zero opacity reads as "not displayed" to WebDriver and makes the control undriveable from system tests.<head>.lib/flightdeck/version.rbis owned bybin/release. This is intended to ship as 1.1.0, so release withbin/release 1.1.0after merge.Testing
test/ui_fonts_test.rbfails if a face is missing from the registry, the stylesheet, or the vendored files — the three places that cannot see each other.document.fonts.check()that every offered face really loads, so a corrupt or unroutable woff2 fails loudly instead of falling back to system-ui. Also covers that the mono face is unaffected and that a pick survives navigation.assets:checknow fails if a face is vendored but never built.🤖 Generated with Claude Code