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.
Summary
On web, Valdi's abstract system font names are emitted as literal CSS font-family values. For example,
font: system 18becomesfont-family: system, andfont: system-bold 18becomesfont-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
In Chromium,
getComputedStyle()reportssystemandsystem-boldas the font families. Depending on installed fonts and browser fallback behavior, the rendered face is serif. Thesystem-boldexample also remains weight 400 becauseboldis encoded in the unresolved family name rather than CSS font weight.Cause
web_renderer/src/styles/ValdiWebStyles.tssplits the Valdi font string and assigns the first token directly tofontFamily. Attributed text and text-field paths perform similar literal assignment. The default web label may start withsans-serif, but an explicit Valdisystemfont 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
systemresolves to the browser's platform sans-serif stack.system-boldresolves to the same stack with bold weight.Proposed fix
Add one shared web font resolver used by every renderer path:
Use it in
ValdiWebStyles, attributed-text rendering,WebValdiTextField, andWebValdiTextView. 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
systemandsystem-bold, bringing web behavior in line with native behavior. Explicit custom font families remain unchanged.