fix(web): correct the dashboard's stylesheet delivery - #280
Closed
Menci wants to merge 4 commits into
Closed
Conversation
Every code surface asked for the generic `monospace` family, which macOS resolves to Courier — a face that shares neither metrics nor mood with the rest of the dashboard. Bundle Cascadia Code through Fontsource, publish it as the theme's monospace family, and route UnoCSS's `font-mono` plus the remaining hardcoded declarations through that one token. The Prism themes address the code block through `pre[class*="language-"]`, which outranks a single-class rule, so those two declarations override the theme outright. Drop the base and numeric family overrides at the same time: they pinned the bare `sans-serif`, which resolves to Helvetica on macOS, while Fluent's own stacks lead with Segoe UI and fall back to the platform UI face.
The Vite integration's global mode emits nothing here: it keys its vite:css-post handle by the top-level build.outDir, while React Router sets outDir only per environment and opts into builder.sharedConfigBuild, so the lookup misses and the layer placeholder ships as the entire stylesheet (unocss/unocss#4990). Per-module mode sidestepped that by generating one sheet per module, but concatenating those in module-graph order put breakpoint variants ahead of the base utilities they override. A media query adds no specificity, so the base utility won at every width: 42 responsive rules across 25 files were inert, among them the sidebar collapse and the mobile navigation trigger. Generate through PostCSS instead. One pass over the content set is a single generate() call, which is where the rule ordering guarantee lives -- base utilities, then lt-*, then ascending min-width breakpoints. Pin the plugin's cwd so config discovery and the content globs resolve against this package rather than the build process's working directory; without it a build launched from the workspace root emits an empty sheet. The source-level transformers go with the Vite plugin, which was the only thing applying them. Neither was reachable anyway: no variant groups appear in the source, and there are no CSS files for the directive transformer to process. Checked the emitted sheet against every responsive class in the source (42 overridden, now 0) and confirmed the computed layout at 500, 700, 900, and 1400px in a headless browser.
# Conflicts: # apps/web/vite.config.ts
Owner
Author
|
Codex agent: Consolidating this follow-up into #277 as requested; the branch remains available while its changes are merged and verified there. |
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.
Stacked on #277.
Summary
Two defects in how the dashboard's CSS reaches the browser.
Utility stylesheet generation. UnoCSS ran in
per-modulemode, which generates one sheet per module and leaves the bundler to concatenate them in module-graph order. That forfeits UnoCSS's rule ordering, which is a property of a singlegenerate()call. Breakpoint variants landed ahead of the base utilities they override, and since a media query adds no specificity the base utility won at every width — 42 responsive rules across 25 files were inert, among them the sidebar collapse and the mobile navigation trigger.per-modulewas itself a workaround: the Vite integration's default global mode emits nothing under React Router. It keys itsvite:css-posthandle by the top-levelbuild.outDir, while React Router setsoutDironly per environment (dist/client,dist/server) and opts intobuilder.sharedConfigBuild, which is what would otherwise re-resolve the config per environment. The lookup misses and the layer placeholder ships as the entire stylesheet — unocss/unocss#4990, open, and not specific to Vite 8 or Rolldown.Generating through
@unocss/postcsssidesteps that machinery entirely: one pass over the content set is onegenerate()call, so base utilities,lt-*, and ascendingmin-widthbreakpoints emit in that order. The plugin'scwdis pinned to the package, because it resolves both config discovery and thecontent.filesystemglobs against the build process's working directory — without the pin, a build launched from the workspace root emits an empty sheet. The source-level transformers go with the Vite plugin, which was the only thing applying them; neither was reachable, since the source has no variant groups and no CSS files for the directive transformer.Monospace face. Bundle Cascadia Code through Fontsource and publish it as the theme's
fontFamilyMonospace, so code surfaces stop resolving to Courier on macOS. Route UnoCSS'sfont-monoand every remaining hardcodedmonospacedeclaration through that one token, and override the Prism themes' own font declaration, which addresses the code block throughpre[class*="language-"]and outranks a single-class rule. Drop thefontFamilyBase/fontFamilyNumericoverrides, which pinned the baresans-serif(Helvetica on macOS) in place of Fluent's Segoe UI stack.Verification
pnpm run lintpnpm run typecheckpnpm run test— 420 files, 4,772 tests passedpnpm --filter @floway-dev/web run buildfont-familyand loaded@font-faceagainst the running dashboard