Skip to content

1.2.0

Latest

Choose a tag to compare

@omaralbeik omaralbeik released this 30 Jul 20:47
e13b7d4

MarqueeText is now layout-interchangeable with a single-line Text, and meaningfully cheaper per row in long lists.

Layout parity with Text

The view reported a hard-coded 20pt height on its first layout pass, so any font whose line height was not 20pt resized one frame after appearing. In a List or LazyVStack that showed up as row jitter and scroll-offset drift. Sizing now comes from the layout, so it is correct on the first pass and never changes as measurement settles.

Also fixed:

  • A generous height proposal no longer stretches the view. It behaved like Color inside ZStack, overlays and stacks with taller siblings; it now behaves like Text.
  • Glyph overhang is no longer clipped. Arabic diacritics, emoji and tall accents legitimately paint outside the typographic line box, and Text renders them. Clipping is now horizontal only.
  • Overflowing text that cannot scroll — most importantly under Reduce Motion — now truncates with an ellipsis instead of being cut off mid-glyph.
  • Text baselines are forwarded, so HStack(alignment: .firstTextBaseline) lines up correctly.

These guarantees are covered by tests that compare MarqueeText against a real Text in a hosting view, across multiple fonts, both layout directions, and every size proposal.

Performance

The view used to lay its text out twice — once hidden, purely to measure it — and ran a second geometry reader to read the container width. Both values are already known to the layout, so it now reports them by proposing them as the size of a single weightless probe.

Measured over 200 rows:

before after
overflowing row 0.755 ms 0.577 ms
row that fits 0.429 ms 0.264 ms

Text that fits still costs nothing at rest, and in List or LazyVStack per-frame work stays flat whether the collection holds 25 rows or 2,500. Note that a non-lazy VStack inside a ScrollView builds every row, so offscreen marquees keep animating there — use List or LazyVStack for long collections.

watchOS 9 support

watchOS is now declared in Package.swift. It previously worked only by SPM inferring a floor from the APIs used, which meant consumers below watchOS 9 failed with a confusing module-level error instead of a clean resolution failure.

Other

  • LocalizedStringResource content is compared by value instead of through a String(describing:) reflection dump on every body evaluation.
  • The internal measurement preference can no longer silently drop a measurement, and clears correctly when the text becomes empty.
  • Added CI: lint, tests with coverage, and a build matrix across all five declared platforms.

Full Changelog: 1.1.0...1.2.0