Component fixture screenshots render codicons as tofu — harness installs icon content rules but never the codicon @font-face
- Dominant language
- TypeScript
- Stars
- 193k
- Forks
- 42.4k
- PR merge metrics
- PR metrics pending
Description
## Summary
The component fixture harness installs the codicon **content** rules for every fixture but never the codicon **`@font-face`**. The result is that every codicon resolves to a code point with no font behind it and renders as tofu (▯). Since screenshots are captured from these fixtures, the CI screenshot baselines for the large majority of fixtures currently validate a UI with visibly broken icons.
Discovered incidentally while rendering a new fixture — the icons were missing, and adding a fixture-scoped `@font-face` made them appear.
## Mechanism
Two halves of codicon styling live in different places, and the harness only wires up one of them.
1. **Content rules — installed globally, for every fixture.** `ensureGlobalStylesInstalled()` adopts `getIconsStyleSheetCached()`, which produces `.codicon-check:before { content: "\eab2" }` and friends:
https://github.com/microsoft/vscode/blob/main/src/vs/workbench/test/browser/componentFixtures/fixtureUtilsCss.ts#L216-L224
2. **The `@font-face` — never installed by the harness.** It lives in `src/vs/base/browser/ui/codicons/codicon/codicon.css` and is only reachable through `src/vs/base/browser/ui/codicons/codiconStyles.ts`, which nothing in the shared harness imports.
Because the component explorer builds a per-fixture module graph (`ComponentExplorerPlugin({ include: 'src/**/*.fixture.ts' })` in `build/rspack/rspack.serve-out.config.mts`), the font is only present for fixtures that import `codiconStyles.js` themselves.
Today that is **10 of 63 fixtures**:
```
editor/suggestWidget.fixture.ts
editor/findWidget.fixture.ts
editor/codeActionList.fixture.ts
editor/peekReference.fixture.ts
editor/renameWidget.fixture.ts
editor/inlineChatAffordance.fixture.ts
editor/inlineChatZoneWidget.fixture.ts
editor/inlineCompletions/other.fixture.ts
sessions/contrib/agentFeedback/.../agentFeedbackInputWidget.fixture.ts
sessions/contrib/changes/.../agentsDiffEditor.fixture.ts
```
The other **53 fixtures get content code points with no font → tofu**.
## Second, related trap: the `.ttf` is gitignored
`src/vs/base/browser/ui/codicons/codicon/codicon.ttf` is gitignored (`.gitignore:11`) and only materialized by a CI step:
https://github.com/microsoft/vscode/blob/main/.github/workflows/component-fixtures.yml#L71-L72
```yaml
- name: Copy codicons
run: cp node_modules/@vscode/codicons/dist/codicon.ttf src/vs/base/browser/ui/codicons/codicon/codicon.ttf
```
So `codicon.css`'s relative `src: url("./codicon.ttf")` only resolves once that copy has happened. Locally, even the 10 fixtures that *do* import `codiconStyles.js` render tofu unless the file happens to be present — meaning local renders and CI renders can silently disagree.
## Expected vs actual
- **Expected:** fixtures render codicons the way the product does, so screenshot baselines validate the real UI.
- **Actual:** ~53 of 63 fixtures render every codicon as tofu, and their committed baselines encode that.
## Suggested fix
Install the `@font-face` once in the shared harness, right next to the icon content rules it already installs, so no fixture has to remember to do it. Either:
- add `import '../../../../base/browser/ui/codicons/codiconStyles.js';` to `fixtureUtilsCss.ts`, or
- declare the `@font-face` in `fixtures.css` pointing at `node_modules/@vscode/codicons/dist/codicon.ttf`
The second option also sidesteps the gitignored-`.ttf` trap, since it does not depend on the CI copy step and resolves identically locally and in CI. This is the shape that was verified to work:
```css
@font-face {
font-family: "codicon";
font-display: block;
src: url("<...>/node_modules/@vscode/codicons/dist/codicon.ttf") format("truetype");
}
```
Once this lands, the per-fixture `codiconStyles.js` imports in the 10 fixtures above become redundant and can be removed.
## Impact on baselines
Expect a **large one-time screenshot baseline churn** — icons will appear across ~53 fixtures that previously showed tofu. That churn is the confirmation the bug was real, not a regression. Worth landing as an isolated commit so the diff is self-explanatory and reviewable.
Contributor guide
Assessment
This issue has not been assessed yet.