Summary
On iOS 26.5 device (not iOS 17 simulator), plain Text(...) + textSetFontSize + textSetColor with an alpha < 1.0 color renders zero glyphs. The widget is sized correctly and the layout reserves space, but no text is painted. Same regression affects Button(...) titles styled via textSetColor on UIButton.
AttributedText(...) + attributedTextAppend(...) is unaffected — text with the same partial-alpha color renders correctly.
Reproducible scenario
import { Text, VStack, textSetFontSize, textSetColor } from \"perry/ui\";
const TEXT_PRIMARY = { r: 0, g: 0, b: 0, a: 0.87 }; // Material 87% black
const slogan = Text(\"Erlebe eine Welt, in der Teilen Freude schenkt\");
textSetFontSize(slogan, 24);
textSetColor(slogan, TEXT_PRIMARY.r, TEXT_PRIMARY.g, TEXT_PRIMARY.b, TEXT_PRIMARY.a);
Build: `perry compile src/main.ts --target ios`, deploy to iOS 26.5 device.
Result: the slogan label has correct intrinsic size (verified by setting a sentinel background color), but no glyphs are visible.
Hardcoding the same RGB with alpha = 1.0 in perry-ui-ios::widgets::text::set_color (or via a custom test) renders correctly. Hardcoding (1, 0, 0, 1.0) renders bright red text as expected. Only alpha < 1.0 triggers the regression.
What I tried (perry-ui-ios runtime)
- Routing
text::set_font_size / set_font_weight / set_color through setAttributedText: with NSColor in the attributes dict — same \"NSFont\" / \"NSColor\" keys as attributed_text.rs, same colorWithRed:green:blue:alpha: UIColor. Still zero-glyph for alpha < 1.
- Setting
numberOfLines: 0 + lineBreakMode: 0 before setAttributedText:. No change.
- Matching
AttributedText's exact path: build an immutable piece via initWithString:attributes:, append to a fresh NSMutableAttributedString buffer, setAttributedText: with the buffer. Still invisible.
- Skipping
setText: in text::create entirely and routing initial text through setAttributedText: (so the label is on the attributed path from the start). Still invisible.
- Clearing via
setText:@\"\" before setAttributedText: to invalidate cached glyph metrics. Still invisible.
- Forcing
alpha = 1.0 in the runtime: works. Text is visible (in pure black instead of designed 87% gray).
So the trigger is consistently a partial-alpha NSColor in the attributes dict applied via setAttributedText: on a plain UILabel. Why AttributedText widget's identical-looking code path is immune, I could not pin down.
Environment
Workarounds
- Use
AttributedText widget for any user-visible styled text targeting iOS 26 device.
- Or pin all text colors to
alpha: 1.0 in theme.ts (loses the Material 87% / 60% gray distinction).
Happy to provide minimal repro project / additional diagnostics. Suspect this is related to the iOS 26 "Liquid Glass" changes to UIKit text rendering.
Summary
On iOS 26.5 device (not iOS 17 simulator), plain
Text(...)+textSetFontSize+textSetColorwith analpha < 1.0color renders zero glyphs. The widget is sized correctly and the layout reserves space, but no text is painted. Same regression affectsButton(...)titles styled viatextSetColoronUIButton.AttributedText(...)+attributedTextAppend(...)is unaffected — text with the same partial-alpha color renders correctly.Reproducible scenario
Build: `perry compile src/main.ts --target ios`, deploy to iOS 26.5 device.
Result: the slogan label has correct intrinsic size (verified by setting a sentinel background color), but no glyphs are visible.
Hardcoding the same RGB with alpha = 1.0 in
perry-ui-ios::widgets::text::set_color(or via a custom test) renders correctly. Hardcoding(1, 0, 0, 1.0)renders bright red text as expected. Onlyalpha < 1.0triggers the regression.What I tried (perry-ui-ios runtime)
text::set_font_size/set_font_weight/set_colorthroughsetAttributedText:with NSColor in the attributes dict — same\"NSFont\"/\"NSColor\"keys asattributed_text.rs, samecolorWithRed:green:blue:alpha:UIColor. Still zero-glyph foralpha < 1.numberOfLines: 0+lineBreakMode: 0beforesetAttributedText:. No change.AttributedText's exact path: build an immutable piece viainitWithString:attributes:, append to a freshNSMutableAttributedStringbuffer,setAttributedText:with the buffer. Still invisible.setText:intext::createentirely and routing initial text throughsetAttributedText:(so the label is on the attributed path from the start). Still invisible.setText:@\"\"beforesetAttributedText:to invalidate cached glyph metrics. Still invisible.alpha = 1.0in the runtime: works. Text is visible (in pure black instead of designed 87% gray).So the trigger is consistently a partial-alpha NSColor in the attributes dict applied via
setAttributedText:on a plain UILabel. WhyAttributedTextwidget's identical-looking code path is immune, I could not pin down.Environment
~/projects/perry/perry/target/release/perry(rebuilt 2026-05-19, includes PR feat(ui): close 5 sharity-port UI gaps #706/#707/#708/#709/#710 #716 widgets)Workarounds
AttributedTextwidget for any user-visible styled text targeting iOS 26 device.alpha: 1.0intheme.ts(loses the Material 87% / 60% gray distinction).Happy to provide minimal repro project / additional diagnostics. Suspect this is related to the iOS 26 "Liquid Glass" changes to UIKit text rendering.