Snapchat / Snapchat/Valdi

Web renderer treats system font tokens as literal families, causing serif fallback

Open
#140 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
16.4k
Forks
537
Avg merge
22d 5h
Merged PRs (30d)
1

Description

Summary

On web, Valdi's abstract system font names are emitted as literal CSS font-family values. For example, font: system 18 becomes font-family: system, and font: system-bold 18 becomes font-family: system-bold. Browsers do not recognize either family, so visible text can fall back to a serif face; bold text also reports normal weight.

The same TSX renders with the expected platform sans-serif font on native targets.

Minimal reproduction

import { Style } from 'valdi_core/src/Style';
import { systemBoldFont, systemFont } from 'valdi_core/src/SystemFont';
import { Label } from 'valdi_tsx/src/NativeTemplateElements';

const regular = new Style<Label>({ font: systemFont(18) });
const bold = new Style<Label>({ font: systemBoldFont(18) });

<label style={regular} value="Regular system text" />;
<label style={bold} value="Bold system text" />;

In Chromium, getComputedStyle() reports system and system-bold as the font families. Depending on installed fonts and browser fallback behavior, the rendered face is serif. The system-bold example also remains weight 400 because bold is encoded in the unresolved family name rather than CSS font weight.

Cause

web_renderer/src/styles/ValdiWebStyles.ts splits the Valdi font string and assigns the first token directly to fontFamily. Attributed text and text-field paths perform similar literal assignment. The default web label may start with sans-serif, but an explicit Valdi system font overwrites that safe default.

Polyglot/custom web views are a related boundary: browser controls created inside them do not necessarily inherit the normal Valdi label defaults. They need either inheritance from a resolved container font or an explicit system stack.

Expected behavior

  • system resolves to the browser's platform sans-serif stack.
  • system-bold resolves to the same stack with bold weight.
  • Normal labels, attributed text, text fields, and text views resolve these names consistently.
  • Custom views can inherit the resolved font where practical; framework widgets that create their own text controls should use the same mapping.

Proposed fix

Add one shared web font resolver used by every renderer path:

const WEB_SYSTEM_FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';

function resolveWebFont(name: string): { family: string; weight?: string } {
  if (name === 'system') return { family: WEB_SYSTEM_FONT };
  if (name === 'system-bold') return { family: WEB_SYSTEM_FONT, weight: 'bold' };
  return { family: name };
}

Use it in ValdiWebStyles, attributed-text rendering, WebValdiTextField, and WebValdiTextView. Add browser tests asserting both computed family and weight. This keeps the abstract Valdi font contract intact and avoids application-level global CSS, which would not cover native targets or isolated custom-view internals.

Compatibility impact

This changes web rendering only for the reserved Valdi names system and system-bold, bringing web behavior in line with native behavior. Explicit custom font families remain unchanged.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in web_renderer/src/styles/ValdiWebStyles.ts and trace the attributed-text, WebValdiTextField, and WebValdiTextView paths that assign font families. Add the shared resolution for system and system-bold described in the issue, then add browser tests checking computed family and weight across the listed renderer paths.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend, testing, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.