Changelog

Release history for the Swift package. Source of truth: CHANGELOG.md.

All notable changes to Aurum-iOS. Follows Keep a Changelog;

versions follow semver (patch = token/bug fix, minor = new component/token,

major = breaking API).

[0.2.14] - 2026-09-25

Removed

  • AurumTabRow's full-width bottom baseline — Figma dropped the strip-wide divider under the tab row; only the selected-tab underline indicator remains. Mirrors aurum-android 0.3.44.

[0.2.13] - 2026-09-24

Added

  • AurumLinkButtonSize.medium — 14/20 SemiBold (titleXSSemiBold), between .large (16/24) and .small (12/16), for a link inside a compact card or row, such as a coupon's "Apply". It is a Size variant in Figma, mapped in Code Connect. Height and padding are unchanged at every size. Mirrors aurum-android 0.3.43.

[0.2.12] - 2026-09-22

Added

  • View.aurumFadeEdge(top:bottom:leading:trailing:) — fades content out towards any of its four edges instead of letting the parent clip it dead. A scrolling container clips to its bounds, so content leaving the viewport is cut on a hard horizontal line; over a dark hero or under a floating tab bar that line reads as a rendering bug rather than as an edge. The ramp multiplies the content's alpha rather than painting a colour over it, so it works on any background without knowing what sits behind — the same reasoning as aurumShadow's alpha mask. leading / trailing resolve against the layout direction, so a row that fades at its trailing edge keeps doing so in RTL, and two ramps on one axis shrink proportionally to fit rather than overlapping into a double-masked band. A mask composites offscreen, so it belongs on the scrolling container, never on each row; the all-zero case skips the mask entirely. Counterpart of Modifier.aurumFadeEdge in aurum-android 0.3.42.

[0.2.11] - 2026-09-15

Added

  • Aurum.motion.easingGlide — (0.16, 1, 0.3, 1), a decelerate with a long tail for a figure gliding to rest; the counter curve. Mirrors aurum-android.
  • Aurum.motion.easingDecelerateEmphasized / easingAccelerateEmphasized — Material 3's emphasized enter and exit pair, (0.05, 0.7, 0.1, 1) and (0.3, 0, 0.8, 0.15), for the one heavyweight thing on screen. Mirrors aurum-android, whose docs/tokens/motion.md carries the *Choosing a curve* table both platforms follow.
  • AurumRollingNumber — a number that rolls to its value instead of appearing at it: lands on easingGlide over a duration set by pace, rolls later changes from the current figure on easingDecelerate in the direction of the change, with numericText sliding each digit, and gives a select tick with a 1.5 % settle on springFastSpatial when it stops. A pace — .quick (0.6 s) / .standard (1 s) / .slow (2 s), each a composition of the duration tokens — sets how long the landing and later rolls take, landFromFraction lets a figure arrive from just below its value instead of spinning up from zero, and landEasing takes another Aurum.motion curve for a documented job (default easingGlide). format is the caller's — Aurum never decides currency, grouping or units. Honours Reduce Motion; VoiceOver reads the figure once. Mirrors aurum-android 0.3.41.

Fixed

  • AurumTransactionListCard — the status wash is laid over the card's own surface before it is painted, as the design does; drawn straight onto a grey list page the 9 % tint came out pinkish-grey. Mirrors aurum-android.

[0.2.10] - 2026-09-09

Added

  • Aurum.motion.durationScreen (0.30 s). Navigating between screens is a different job from moving something inside one, and it had no token: 0.25 makes a screen swap feel clipped, 0.40 makes it drag. Deliberately off the 0.05/0.15/0.25/0.40/0.60 rungs, matching aurum-android's 300 ms. (Android also gains AurumDefaultMotion for reading the tokens outside composition; Aurum.motion is already a static here, so there is nothing to mirror.)

[0.2.9] - 2026-09-08

Changed

  • The radius scale matches Figma again — xl is 12, not 16. Design inserted a 12 rung as borderRadius/xl and shifted every name above lg: what we called xl (16) is Figma's xxl, our xxl (24) is its 3xl. The scale is now lg 8 · xl 12 · xxl 16 · xxxl 24, mirroring aurum-android name-for-name. Call sites that meant 16 — AurumBottomSheet, AurumTransactionListCard, AurumSurface — now say xxl, so nothing renders differently.
  • AurumShapes gained xxxl, keeping the shape aliases one-to-one with the radius scale.

Fixed

  • The token codegen only knew how to rename 2xl. normalize_size_token hardcoded that one case, so the moment the radius scale grew a rung it emitted 3xl: as a Swift field name — which cannot compile, since an identifier may not start with a digit. It now handles any <n>xl rung, so 4xl will not break the generator either. TokenIntegrityTests asserts all three of the upper rungs rather than just the top one.

[0.2.8] - 2026-09-08

The aurum-android mirror of the three Figma moves its weekly spec audit surfaced.

Added

  • AurumLinkButton takes a size. Figma grew a Size axis the component had no way to express: .large is titleSSemiBold (16/24 SemiBold), .small is labelLMedium (12/16 Medium). .large is the default, so existing call sites move to the size the design specifies instead of keeping a third one at titleXSBold. Carried through all four initialisers and the Code Connect mapping.

Changed

  • AurumLinkButton is 40 pt tall, not 56. Both sizes; only the label's type scale differs.
  • Plain AurumPills carry a hard shadow. borderSurfaceHighContrast at y 1 on rectangular and rounded whenever enabled — Figma authors it on default and focus and omits it on disabled. AurumPillShadowModifier takes a colour now so the withTags pill's purple800 and this one share one offset constant; Figma gives both y 1.05.
  • AurumPhoneNumberInput's field is 64 pt. Figma pins it at 64 in all nine variants; the plain field's master is still 56, so AurumTextField keeps its default and gained an internal aurumFieldMinHeight for the one caller that departs from it.

Fixed

  • AurumPill had no snapshot coverage. It shipped in 0.2.5 with none, so nothing verified it visually — the hard shadow above would have landed on iOS untested, and the re-record proved it by touching only the link-button and phone-field tiles. testPillTypesAndStates covers all three types across default / selected / disabled, so the shadow's presence on the first two and its absence on the third are both in the baseline.
  • The leading group now matches Figma and Android. The divider trails the country code instead of separating it from the flag, it is 32 pt rather than 20, and the code renders titleSBold on textDefaultSubtle rather than bodyLMedium on textDefaultNormal. The group's gap is 10 — between s3 and s4, so a literal here exactly as on Android — and it carries s3 of trailing padding because the field box's own HStack already contributes the other half of Figma's 16.

[0.2.7] - 2026-09-07

A motion + haptics token layer, so the numbers behind an animation stop being chosen per call site. Springs, the stagger rule and the haptic vocabulary are shared name-for-name and value-for-value with aurum-android; the motion primitives the app was re-implementing are now public.

Added

  • Six spring tokens on Aurum.motion, split spatial vs effects. springDefaultSpatial (damping 0.8 / stiffness 380), springFastSpatial (0.6 / 800), springSlowSpatial (0.8 / 200), springDefaultEffects (1.0 / 1600), springFastEffects (1.0 / 3800), springSlowEffects (1.0 / 800) — Material 3 Expressive's motion scheme, adopted verbatim because our existing ad-hoc springs already clustered near these numbers. The split is load-bearing: spatial springs move geometry and are under-damped, effects springs move colour and alpha and are pinned to damping 1.0, because an overshooting alpha clips instead of bouncing.
  • AurumSpring carries both parameterisations. Compose drives springs by dampingRatio + stiffness, SwiftUI by duration + bounce; with mass pinned to 1 the conversion is exact (bounce = 1 - dampingRatio, duration = 2π / √stiffness), so a token is provably the same spring on both platforms. .animation hands you the ready Animation.
  • staggerStep (70 ms) + staggerBudget (500 ms) + staggerDelay(index:count:). They ship as a pair on purpose: an interval without a ceiling invites a thirty-item list at 70 ms apiece. The function makes the ceiling mechanical rather than advisory — the interval yields to the budget, so a long run compresses instead of overrunning it.
  • Aurum.haptics — a semantic haptic vocabulary. Eight names (select, commit, reject, toggleOn, toggleOff, press, threshold, scrub) mapped once to SwiftUI SensoryFeedback, with the five policy rules documented next to the tokens. The point is not version safety — SwiftUI already downgrades an unsupported pattern — but that "which haptic means success" is decided once by design instead of once per engineer.
  • .aurumEnter(delay:) — Aurum's standard entrance: fade in while rising 14 pt, durationEmphasized on easingDecelerate. nil renders statically. The travel distance is deliberately not a token; a travel scale would collide with Aurum.space.
  • .aurumPopIn(delay:) — scale 0.6 → 1 on springFastSpatial with a quicker fade, for the one element that has genuinely earned emphasis.
  • .buttonStyle(.aurumPressScale) — a public press cue for tappable surfaces Aurum does not own. Both entrances honour Reduce Motion by rendering their static form.

Changed

  • aurumErrorShake, aurumStatusIconPop and AurumRollingText are public. They were internal, so the app could not reach them and was re-implementing all three with different numbers — the exact drift the token layer exists to prevent. AurumRollingText's settleDelay default is now an inline literal, since a public initializer cannot default from a private constant.
  • .aurumStatusIconPop now reads springFastSpatial instead of an ad-hoc spring(response: 0.31, dampingFraction: 0.5). The glyph settles about 28% sooner (0.31 s → 0.222 s) and overshoots slightly less (bounce 0.5 → 0.4); it still reads as a pop.
  • AurumPillTabs' sliding indicator now reads springDefaultSpatial instead of spring(response: 0.38, dampingFraction: 0.78). Damping is unchanged in practice (0.78 → 0.8); the slide lands about 15% sooner.
  • AurumPill uses the shared .aurumPressScale instead of a pill-private interactiveSpring(response: 0.3, dampingFraction: 0.7). Same 0.96 sink, now on springFastSpatial — marginally quicker and marginally springier, and one press cue instead of two.
  • Duration literals that exactly equalled a token now read the token in AurumSwitch, AurumPillTabs, AurumTabRow and AurumTab (0.15 → durationQuick, 0.25 → durationStandard). No timing changes; the values were already the token's.
  • easingDecelerate / easingAccelerate doc labels were swapped. CubicBezier(0,0,0,1) leaves fast and settles — that is the entering curve, not the exiting one. Corrected in both repos; values untouched.

Catalog

  • A Motion & haptics screen: all six springs thrown across a track with their damping/stiffness and duration/bounce shown side by side, a stagger demo whose row count exposes the budget clamping the interval, live aurumEnter / aurumPopIn / aurumPressScale / aurumErrorShake / AurumRollingText, and a tappable row per haptic token.

Platform notes

  • Aurum.haptics.scrub maps to .selection, the same feedback as select. Android grades the two (SegmentFrequentTick under SegmentTick); iOS has no second grade, and .levelChange — the closer name — plays on macOS only, which would leave the token silent.

Mirrors aurum-android 0.3.36.

[0.2.6] - 2026-09-02

Motion for the field family and the pill. No public API changes; every animation is an insertion transition, a keyframe offset or a content transition, so no component's layout or resting state moves.

Added

  • AurumAmountInput's derived suffix rolls like an odometer (AurumRollingText). It waits 550 ms of quiet after the last keystroke, then rolls only the glyphs that changed via .contentTransition(.numericText(countsDown:)) — upward when the value grew, downward when it shrank — over 320 ms motion.easingEmphasized. Animating every intermediate value would fight the digits being typed; rolling once after the pause reads as the field answering the user.
  • AurumTextField shakes once when it enters the error state (aurumErrorShake). 6 pt horizontal, 360 ms, three oscillations decaying at 0.6, driven by a keyframeAnimator so the field is never re-laid-out. It fires only on the flip *into* error: a field first shown already in error stays still, and holding an invalid value does not keep it jittering.
  • Support text enters with motion. The helper / error / success row is inserted with a fade + slide (motion.durationStandard / easingStandard) and clipped by its container so it reveals downward instead of jumping in. Height is not reserved, so no field's resting layout changes.
  • Validation status icons pop in (aurumStatusIconPop). The trailing error / success glyphs scale in on a spring (response 0.31 s, damping 0.5 — Compose's MediumBouncy / StiffnessMediumLow), keyed on the field's AurumFieldStatus so a glyph pops only when the status changes.

Changed

  • AurumPill selection and press are now animated. The selected border previously swapped colour in a single frame; it now animates over motion.durationStandard with motion.easingStandard, on both the plain and .withTags bodies.
  • AurumPill gained a dimensional press cue. It used the shared AurumBareButtonStyle (no visual feedback); it now uses a pill-scoped AurumPillPressStyle that scales to 0.96 on press with an interactive spring. The shared bare style is untouched, so the other five components that use it are unaffected.

Catalog

  • The fields demo gained a live validating AurumAmountInput that exercises the roll, shake, support-text entrance and icon pop together.

Fixed

  • VERSION said 0.2.4 while the 0.2.5 tag and changelog had shipped. Now 0.2.6, in step with the tag.

Mirrors aurum-android 0.3.35 (AurumRollingText, aurumErrorShake, AurumStatusIconPop, pillPressScale) with the same motion-token values.

[0.2.5] - 2026-08-27

Added

  • AurumPill — the SwiftUI port of aurum-android's pill (5891:802). The

component set had no iOS counterpart at all. Covers all three types

(rectangular / rounded / withTags), the default / selected / disabled

states, and optional leading or trailing 16 pt glyphs. The withTags

composite carries its uppercase ribbon and the master's purple800 hard

shadow at y=1. Mirrors aurum-android 0.3.32, including the corrected

purple tag band in the default state.

  • **AurumPillTabs + AurumPillTab — a new single-select segmented switch

(7741:7306).** A bgSurfaceMidContrast capsule track carrying 2–3 evenly

divided cells, with the active cell lifted as a dark pill

(180°, neutralA400 → neutral900) that slides between cells on a

spring while the labels crossfade. Distinct from AurumTabRow: that is

page-level navigation with an underline indicator, this is an inline filter

or mode switch scoped to one section.

  • Aurum.colors.visual.neutral900 and visual.neutralA400. Figma's Pill

Tabs master binds colors/black/500 and colors/neutral/a400, palette

variables with no codeSyntax and therefore no code counterpart. Surfaced on

the visual group against the existing AurumPalette entries, matching

aurum-android.

Fixed

  • **AurumTab dropped the entire selected treatment from its master

(5531:795).** The active tab specifies a radial wash — bottom-centre,

elliptical at 0.639·w × 1.0·h, purple100 → bgPageBase at 32% — and paints

its label *and* icon with a linear gradient (180°, purple500 from

0.3225 → purple200), not a flat colour. Both now render, and the wash

fades in rather than popping. Consumer impact: selected tabs gain the

wash and a two-tone label — every existing AurumTabRow picks this up.

Notes

  • Three paints on these masters carry unbound stops (no Figma variable):

the tab wash's two stops and the tab label gradient's first stop. They resolve

exactly to purple100, bgPageBase and purple500, so they are token-bound

in code and marked AURUM-DRIFT at the call site in AurumTabDefaults.

  • Figma's Pills set specifies 16 pt Semi Bold for rectangular/rounded

focus labels but 14 pt Bold for withTags focus — a size jump that reflows

a pill on selection. Implemented as 14 pt Bold (Title/XS-Bold) throughout,

matching aurum-android, pending a design decision.

[0.2.4] - 2026-08-11

Added

  • AurumTextField gains prefix and suffix slots. Both render inline

with the value inside the field's content padding — prefix hugs the text

with no slot spacing (unlike leading, which sits a s3 HStack gap away),

and suffix ends flush against the field's 16 pt inset. Use prefix for

tight value prefixes (currency glyphs) and suffix for derived equivalents

(gold grams). Additive; every existing call shape keeps compiling. Mirrors

aurum-android 0.3.30.

Fixed

  • AurumAmountInput now matches its Figma master's anatomy (5080:261).

The ₹ moved from leading to the new prefix slot, closing the 12 pt

gap between the symbol and the amount to the master's 4 pt. The

suffixText equivalent moved from trailing to suffix, dropping its

extra 4 pt inset (now exactly 16 pt from the field edge), and its colour

corrected from textDefaultSubtle to the master's textDefaultNormal.

Loader / validation icons stay in trailing and take precedence over the

suffix. Mirrors aurum-android 0.3.30.

[0.2.3] - 2026-07-30

Fixed

  • **AurumSectionHeaderAction.link now renders neutral-subtle, matching its

Figma master (5442:462).** The link action was styled identically to the

text action — Title/XS-SemiBold in interactive.textPrimaryNormal

(brand purple) with a 20pt iconPrimaryNormal chevron — so "View All /

See More" links shouted as loudly as the section title and were

indistinguishable from a brand text-button. The sheet's action link

layer specifies Body/S-Medium in interactive.textNeutralSubtle with a

12pt interactive.iconNeutralSubtle chevron; the component now follows

it. text is unchanged and remains the brand-emphasis option.

Consumer impact: every existing link action becomes grey and one

step smaller — intended, but visible. Mirrors aurum-android 0.3.29.

  • **surface.textStaticBlackDisabled / surface.iconStaticBlackDisabled

were #121212; Figma and Android say #000000** (same 32% alpha). The

token-codegen carried a deliberate "normalize `_global-colors/neutral/

black/100 to palette black100` for Android parity" mapping whose premise

was false — verified against the live Figma file (alias chain walks to

#000000@0.32) and Android's manifest (ships #000000). The mapping also

silenced the codegen's own alias-integrity check. Removed: aliases into

collections outside the primitives export now inline Figma's resolved

value verbatim (and colors/* misses still hard-fail). Surfaced by

aurum-mcp's cross-platform token-parity check at merge time.

Changed

  • Portal redesigned as a specimen book (tooling/gallery/): the

presentation layer is now the locked Aurum-portal design system

(tooling/gallery/design.md, shared with aurum-android; platform lens

tokens are the only divergence). Newspaper masthead with the version as

the issue line, live type specimens rendered from real tokens on the

landing page, hairline plates instead of cards, tabular spec sheets on

component pages, typographic Do/Don't columns, a build-facts colophon

footer, full OKLCH tokenisation (tooling/gallery/tokens.css), in-place

copy feedback, and a platform-lens colour drawn from the system's own

palette (iOS = visual.blue.600). Verified at 320/375/768/1440 px with no

horizontal scroll; light + dark.

  • Gallery rebuilt as the "Aurum for iOS" designer portal

(tooling/gallery/generate.py): the presentation layer is now a port of

aurum-android's portal — landing page with hero/stats/release card,

light/dark/auto theme, ⌘K live search on components and icons,

copy-to-clipboard token swatches and icon symbol paths, per-component

pages with intended-use/Do/Don't cards and pinned-simulator snapshot

tiles, SPM install section, and bidirectional cross-links with the

Android portal. Data layer, CLI (--validate / --emit-manifest /

--out), and manifest schema unchanged.

Added

  • AurumIcons.Navigation.caretBold{Up,Down,Left,Right} (+ Filled).

Their masters have been sitting in the canonical icon sheet

(5130:35416) without code counterparts on either platform. Single-weight

in Figma, so both weights resolve to the same asset — the same convention

the existing caret family uses. Imported via make icons-import from

aurum-android's normalized Vector Drawables, bringing the iOS set back to

parity at 89 icons × 2 weights. The ICON_MANIFEST in

tooling/icon-import/import_icons.py gained the matching entries; it is a

verbatim port of Android's table, so an entry added on one platform must

land on the other in the same sitting.

  • Catalog app (catalog/AurumCatalog.xcodeproj, XcodeGen-generated

from project.yml — SPM can't declare app targets): an on-device

showcase with 11 family screens covering every component, including

live demos of the stateful surfaces the static gallery can't show —

the toast FIFO queue + timers, the persistent banner host, bottom

sheet presentations, and interactive tabs / nav bar / stepper /

selection controls. make catalog regenerates + builds.

  • Gallery + MCP manifest tooling (tooling/gallery/generate.py, the

iOS twin of aurum-android's generator): --validate enforces the

doc-tag + Figma-url contract in CI (make validate-docs, wired into

check.yml); --out renders the static HTML gallery (components with

doc tags + snapshot strips, tokens, icons, changelog); --emit-manifest

emits the aurum-mcp manifest (schemaVersion: 2,

platforms: ["ios"]), schema-validated against aurum-android's

contract. pages.yml deploys gallery + /data/manifest.json to GitHub

Pages after check passes on main.

[0.2.2] - 2026-07-21

Fixed

  • Code Connect: the checkbox mappings used property names guessed from

the radio set; the Figma checkbox masters actually expose

shownSubtext / shownLabel / shownHelptext / validationState

(and "indeterminate", not "intermediate"). v0.2.1's tag publish

failed validation on these; this release republishes all 197 mappings.

AurumCheckbox's mapping also gained the types label-position axis

(parity with Android's).

[0.2.1] - 2026-07-21

Added

  • AurumNavBar: bottom navigation with standard3/4/5 and

centerQr5 layouts (item-count preconditions), line→filled icon swap,

the purple/500 → pink/50 @ 61% brand ramp on selected glyphs (sRGB

blend helper — Color.mix needs iOS 18), and the raised 56 pt Scan-QR

dome (elliptical radial wash, gradient ring, purple hard shadow, 33 pt

glyph box for Figma's 27 pt drawn size). Labels clip at the cell edge

(Figma's overflow-clip) instead of ellipsising. One Code Connect

mapping (197 total parse clean) + one snapshot tile. **This completes

the aurum-android component-catalogue port** — every Figma-backed

Android component now has a SwiftUI counterpart (AurumScreen /

AurumFragmentBridge are Android platform glue with no iOS

equivalent).

  • Surface, stepper, transaction card: AurumSurface (base container

primitive — token background + shape clip + optional border +

.aurumShadow elevation; codebase-only), AurumStepper (± quantity

control, neutral/brand, "Add" initial state at minValue, bound-aware

disabling), AurumTransactionListCard (status-tinted history row:

feedback.* outer wash, white inner card, status badge, tinted amount,

optional 40 pt leading slot + helper line). Two Code Connect mappings

(196 total parse clean) + three snapshot tiles.

  • Selection family: AurumRadioButton + AurumRadioGroup,

AurumCheckbox (tri-state with check/indeterminate glyph shapes) +

AurumCheckboxGroup, and AurumSwitch (custom-drawn to the Figma/M3

anatomy — 52×32 track, thumb grows 16→24 pt with a check glyph when on,

which the native Toggle can't render). Controls draw Figma's press

state-layer via a press-reporting button style; error tinting, disabled

fade, start/end label positions, 32 pt-indented subtext, and group

label/helper/error lines all mirror Android. Five Code Connect mappings

(194 total parse clean) + four snapshot tiles.

  • Tabs: AurumTab (selected/unselected cell, optional 24 pt leading

icon, Title/XS-Bold label) + AurumTabRow (data-driven items: array —

a documented deviation from Android's slot lambda; fit-or-scroll width

algorithm max(widestNatural, 100 pt) with flex-equal fit and

pinned-width scroll modes, animated 2 pt indicator, hairline divider).

Two Code Connect mappings (189 total parse clean) + one snapshot tile.

  • Headers: AurumGlobalHeader (profile pill with radial sheen +

support / rewards+notifications / live-price right-group variants,

onLight/onDark schemes with dark-glass gradient borders) and

AurumPageHeader (56 pt title-and-actions row covering the 10 Figma

trailing-action types via nilable button/icon/overflow slots, 32×40 pt

icon wrappers, onDark scheme). Both bleed containerColor under the

status bar at the top edge (Android's inset params with no API). Two

Code Connect mappings (187 total parse clean) + two snapshot tiles.

  • Toast + Banner families: AurumToast (6 tones × small/large, per-tone

status glyph, always-dismissible; Code Connect mapping — 185 total parse

clean) with AurumToastHost/AurumToastHostState (FIFO-serialised async

showToast, short/long/indefinite auto-dismiss, slide-up/fade);

AurumBanner (persistent full-bleed top band, same tonal language,

inline action + optional ✕; backgrounds bleed under the status bar at the

top edge — Android's windowInsets for free) with

AurumBannerHost/AurumBannerHostState (single persistent slot,

slide-from-top expand/collapse). Plus AurumIconButton (icon-only

button, 44 pt touch floor, pressed dim) — needed by both close

affordances. Hosts + banner + icon button are codebase-only (no Figma

nodes), mirroring Android. AurumElevationLevel gained a public init

(Android parity) for the toast's master-declared 0/1/1 shadow recipe.

Four snapshot tiles.

  • Progress bars: AurumProgressBar (determinate 8 pt track + primary

fill, optional label/percentage header) and AurumSegmentedProgressBar

(bars/bubbles × 6 intents, numbered checkpoints). Two Code Connect

mappings (184 total parse clean) + two snapshot tiles.

  • AurumBottomSheet (.aurumBottomSheet modifier): native .sheet

presentation with a self-sizing .height detent, token corner radius +

card colour, strict (56 pt header + sticky button slot) and flexible

types. Platform deviations documented: system drag indicator inside the

card, system scrim.

  • AurumOtpInput: underline digit cells (4/6), invisible capture field

with oneTimeCode autofill, none/error/success/timer validation states,

completion-boundary onComplete. AurumTypeStyle gained a public init

(parity with Android's constructible TextStyle) for its Figma-specified

24/32 Bold digit style.

  • Field family: AurumTextField (static-label anatomy, validation-driven

borders and derived status affordances, counter, secure entry, multiline;

shape via a small enum — SwiftUI's InsettableShape can't be type-erased),

AurumSearchField (pill + magnifier + clear), AurumPhoneNumberInput

(country prefix + digits-only filter), AurumAmountInput (Num/XL hero

value + currency symbol + derived suffix). Three more Code Connect

mappings (180 total parse clean) and four snapshot tiles.

  • Second component wave, API-parity ports of aurum-android prioritized

by jar consumer usage: AurumLabel (default/subtle/strong × uppercase),

AurumLinkButton (text-only brand action with pressed dim + slots),

AurumBadge (6 roles × 2 emphases × 2 sizes, cross-axis token pairing,

optional leading icon), AurumChip (action/other × neutral/brand/black/

selected × large/small with pressed states), AurumSectionHeader

(title/subtitle + link/text/icon actions). Each with doc tags, a Code

Connect mapping (177 total now published on release), and snapshot tiles.

Fixed

  • AurumChip's capsule border rasterizes its stroke (drawingGroup) to

side-step an iOS 26.5 shape-layer quirk that paints stray vertical

hairlines at a stroked capsule's horizontal extremes.

[0.2.0] - 2026-07-20

Removed

  • **AurumIcons.Navigation.caretCircleUp/Down/Left/Right (+ Filled) —

removed to restore the 1:1 sheet↔catalog contract** (breaking). Their

Figma masters were deleted from the "Component Icons" sheet and current

product designs use chevron affordances exclusively; keeping ghost icons

breaks the premise that the catalog mirrors the sheet. Mirrors

aurum-android PR #57 (same removal); jar-android's only usage migrates to

a disc + chevronRight composition. 8 imagesets, 8 catalog entries gone

(170 remain); the FIGMA_DELETED workaround in the importer is gone with

them — a deleted Figma node now fails the import loudly, as the 1:1

contract demands.

[0.1.2] - 2026-07-20

Fixed

  • Code Connect: skip the four CaretCircle* icon mappings — their Figma

master components were deleted from the file (verified via the components

API; only the plain Caret set survives), and publish validation fails on

ghost nodes. The icon assets remain in the catalog. Android's

ICON_MANIFEST carries the same stale node ids and needs the same fix.

[0.1.1] - 2026-07-20

Added

  • Figma Code Connect (research §11.4): FigmaConnect/ dev-only nested

SPM package with 180 .figma.swift mappings — AurumButton (variant ×

size × isFullWidth × label), AurumLoader, and one per icon×weight

emitted by the icon importer. All 180 validated with the Swift parser

(make figma-parse). figma-code-connect.yml parse-validates on PR and

publishes to Dev Mode only from v*.*.* tags (Android's release gate,

mirrored).

[0.1.0] - 2026-07-20

Added

  • First components (research §11.3), API-parity ports of aurum-android:
  • AurumText — canonical text primitive over Aurum.type.* roles with the

Android foreground-resolution order (explicit foreground: ShapeStyle →

color: → textDefaultNormal); AttributedString overload for

per-run styling.

  • AurumIcon + generated AurumIcons catalog (89 icons × line/filled) —

template-rendered asset-catalog SVGs with tint resolution explicit →

ambient \.aurumContentColor (the LocalContentColor port) →

iconDefaultNormal; gradient tint overload.

  • Icon importer (tooling/icon-import/import_icons.py): converts

aurum-android's committed, already-normalized Vector Drawables to

imagesets + the Swift catalog, so both platforms share one normalization

pipeline (make icons-import).

  • AurumButton — variants primary/secondary/tertiary × sizes 40/48/56 pt,

full-width, loading, auto-advance progress, leading/trailing slots;

radial primary fill, top-lit rim, and the dimensional purple/800

hard-shadow press (drop + 2 pt sink) via a private ButtonStyle.

  • AurumLoader — track + 90° arc spinner with optional right/bottom label.
  • AurumDivider, AurumSkeleton (t=0-deterministic shimmer).
  • Tests: icon-catalog contract suite, button-defaults unit suite, and 13

component snapshot tiles mirroring the Android @AurumPreview groups.

  • Foundations — the initial package skeleton per the architecture research

(docs/ios-design-system-research.md):

  • Source SPM package with two products: AurumTokens (extension-safe token

layer) and Aurum (components + paint toolkit, re-exports the tokens).

iOS 17 floor.

  • Token codegen (tooling/token-codegen/generate.py): committed Figma

W3C JSON exports → generated Swift token layer (Sources/AurumTokens/Token/),

with a --check determinism gate for CI. Name mapping is a faithful port

of the Token Sync plugin's mapping.ts. 156 palette primitives, 295

semantic + visual colors, 45 typography composites, 4 elevation recipes,

spacing/radius/borderWidth/iconSize scales.

  • Theme layer: static Aurum.* namespace (colors, type, space,

radius, borderWidth, shape, elevation, iconSize, motion,

opacity), theme-shaped structs, AurumRoot / .aurumTheme().

  • Typography: bundled static Inter + Frank Ruhl Libre TTFs registered at

runtime (Aurum.registerFonts(), idempotent); every style carries a

Dynamic Type anchor (relativeTo); .aurumType(_:) reproduces Figma's

exact line height and scales it along the anchor curve.

  • Paint toolkit: AurumLinearGradient (CSS-angle, size-aware),

AurumRadialGradient (circular + rotated-elliptical via Core Graphics),

.aurumShadow() (offset/blur/spread/tint, Figma-blur÷2 conversion,

interior knockout, optional alpha mask), .aurumHardShadow(),

.aurumInnerShadow(), Aurum.shape.smooth() continuous corners.

  • Tests: token integrity + paint math unit suites; snapshot harness on

swift-snapshot-testing with Git LFS baselines (pinned: iPhone 17 Pro,

iOS 26.5) covering gradients, shadows, squircle audit, and the full type

ramp.

  • CI: check.yml (codegen gate + build + test) and record.yml

(label-triggered baseline re-record).