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 aSizevariant 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 asaurumShadow's alpha mask.leading/trailingresolve 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 ofModifier.aurumFadeEdgein 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, whosedocs/tokens/motion.mdcarries the *Choosing a curve* table both platforms follow.AurumRollingNumber— a number that rolls to its value instead of appearing at it: lands oneasingGlideover a duration set bypace, rolls later changes from the current figure oneasingDeceleratein the direction of the change, withnumericTextsliding each digit, and gives aselecttick with a 1.5 % settle onspringFastSpatialwhen it stops. Apace—.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,landFromFractionlets a figure arrive from just below its value instead of spinning up from zero, andlandEasingtakes anotherAurum.motioncurve for a documented job (defaulteasingGlide).formatis 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 gainsAurumDefaultMotionfor reading the tokens outside composition;Aurum.motionis already a static here, so there is nothing to mirror.)
[0.2.9] - 2026-09-08
Changed
- The radius scale matches Figma again —
xlis 12, not 16. Design inserted a 12 rung asborderRadius/xland shifted every name abovelg: what we calledxl(16) is Figma'sxxl, ourxxl(24) is its3xl. The scale is nowlg8 ·xl12 ·xxl16 ·xxxl24, mirroring aurum-android name-for-name. Call sites that meant 16 —AurumBottomSheet,AurumTransactionListCard,AurumSurface— now sayxxl, so nothing renders differently. AurumShapesgainedxxxl, keeping the shape aliases one-to-one with the radius scale.
Fixed
- The token codegen only knew how to rename
2xl.normalize_size_tokenhardcoded that one case, so the moment the radius scale grew a rung it emitted3xl:as a Swift field name — which cannot compile, since an identifier may not start with a digit. It now handles any<n>xlrung, so4xlwill not break the generator either.TokenIntegrityTestsasserts 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
AurumLinkButtontakes asize. Figma grew aSizeaxis the component had no way to express:.largeistitleSSemiBold(16/24 SemiBold),.smallislabelLMedium(12/16 Medium)..largeis the default, so existing call sites move to the size the design specifies instead of keeping a third one attitleXSBold. Carried through all four initialisers and the Code Connect mapping.
Changed
AurumLinkButtonis 40 pt tall, not 56. Both sizes; only the label's type scale differs.- Plain
AurumPills carry a hard shadow.borderSurfaceHighContrastat y 1 on rectangular and rounded whenever enabled — Figma authors it on default and focus and omits it on disabled.AurumPillShadowModifiertakes a colour now so thewithTagspill'spurple800and 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, soAurumTextFieldkeeps its default and gained an internalaurumFieldMinHeightfor the one caller that departs from it.
Fixed
AurumPillhad 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.testPillTypesAndStatescovers 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
titleSBoldontextDefaultSubtlerather thanbodyLMediumontextDefaultNormal. The group's gap is 10 — betweens3ands4, so a literal here exactly as on Android — and it carriess3of trailing padding because the field box's ownHStackalready 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. AurumSpringcarries both parameterisations. Compose drives springs bydampingRatio+stiffness, SwiftUI byduration+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..animationhands you the readyAnimation.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 SwiftUISensoryFeedback, 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,durationEmphasizedoneasingDecelerate.nilrenders statically. The travel distance is deliberately not a token; a travel scale would collide withAurum.space..aurumPopIn(delay:)— scale 0.6 → 1 onspringFastSpatialwith 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,aurumStatusIconPopandAurumRollingTextare public. They wereinternal, 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'ssettleDelaydefault is now an inline literal, since a public initializer cannot default from a private constant..aurumStatusIconPopnow readsspringFastSpatialinstead of an ad-hocspring(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 readsspringDefaultSpatialinstead ofspring(response: 0.38, dampingFraction: 0.78). Damping is unchanged in practice (0.78 → 0.8); the slide lands about 15% sooner.AurumPilluses the shared.aurumPressScaleinstead of a pill-privateinteractiveSpring(response: 0.3, dampingFraction: 0.7). Same 0.96 sink, now onspringFastSpatial— 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,AurumTabRowandAurumTab(0.15 →durationQuick, 0.25 →durationStandard). No timing changes; the values were already the token's. easingDecelerate/easingAcceleratedoc 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.scrubmaps to.selection, the same feedback asselect. Android grades the two (SegmentFrequentTickunderSegmentTick); 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 msmotion.easingEmphasized. Animating every intermediate value would fight the digits being typed; rolling once after the pause reads as the field answering the user.AurumTextFieldshakes once when it enters the error state (aurumErrorShake). 6 pt horizontal, 360 ms, three oscillations decaying at 0.6, driven by akeyframeAnimatorso 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'sMediumBouncy/StiffnessMediumLow), keyed on the field'sAurumFieldStatusso a glyph pops only when the status changes.
Changed
AurumPillselection and press are now animated. The selected border previously swapped colour in a single frame; it now animates overmotion.durationStandardwithmotion.easingStandard, on both the plain and.withTagsbodies.AurumPillgained a dimensional press cue. It used the sharedAurumBareButtonStyle(no visual feedback); it now uses a pill-scopedAurumPillPressStylethat 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
AurumAmountInputthat exercises the roll, shake, support-text entrance and icon pop together.
Fixed
VERSIONsaid 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.neutral900andvisual.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
- **
AurumTabdropped 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 Boldforrectangular/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
AurumTextFieldgainsprefixandsuffixslots. 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
AurumAmountInputnow 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.linknow 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 withstandard3/4/5and
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(.aurumBottomSheetmodifier): 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 overAurum.type.*roles with the
Android foreground-resolution order (explicit foreground: ShapeStyle →
color: → textDefaultNormal); AttributedString overload for
per-run styling.
AurumIcon+ generatedAurumIconscatalog (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) andrecord.yml
(label-triggered baseline re-record).