All notable changes to the Aurum design system are documented here.
Format follows Keep a Changelog.
[0.3.44] - 2026-09-25
Removed
AurumTabRow's full-width bottom baseline — Figma dropped the strip-wideinteractive/border/neutral/highlighteddivider under the tab row; only the selected-tab underline indicator remains.HorizontalDivider/AurumTabDefaults.dividerColor()removed from the row.
[0.3.43] - 2026-09-24
Added
AurumLinkButtonSize.Medium— 14/20 SemiBold (titleXSSemiBold), betweenLarge(16/24) andSmall(12/16), for a link that sits inside a compact card or row, such as a coupon's "Apply". Product designs had been reaching for it by overriding theLargeinstance's text style toTitle/XS, an override Code Connect can't see, so the code rendered 16 sp where the design showed 14. It is now aSizevariant in Figma and an enum value on both platforms. Height and padding are unchanged at every size.
[0.3.42] - 2026-09-22
Fixed
- Five of the eight haptic tokens were silent below API 34.
SegmentTick,SegmentFrequentTick,GestureThresholdActivate,ToggleOnandToggleOffare all API 34 constants, and Compose passes aHapticFeedbackTypestraight through toView.performHapticFeedbackwith no compatibility mapping of its own — verified againstPlatformHapticFeedbackTypein compose-ui 1.12.0, which assigns the raw platform ints. The window manager returns no vibration effect for a constant it does not recognise, soselect,scrub,threshold,toggleOnandtoggleOffproduced nothing at all on any device below 34, while reading as correct in code and in review. Each now resolves to a constant theminSdkfloor can actually render. Below 34 the platform has no fine-grained tick, soselectandscrubnecessarily collapse ontoContextClick;thresholdfalls back toConfirmrather than the nearer-soundingGestureEnd, because the older constants differ in amplitude as well as in meaning andGestureEndis a soft tick a mid-tier actuator renders close to imperceptible. The bug was found in jar-android, where the light arm had migrated its call sites onto these tokens while the dark arm still used rawContextClick— so the two arms had silently diverged, and every light-surface haptic on an API 30 handset was dead.
Added
Modifier.aurumFadeEdge— 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 nav bar that line reads as a rendering bug rather than as an edge. The ramp is painted withBlendMode.DstInagainst an offscreen layer — the same masking techniqueaurumShadowuses — so it multiplies the content's alpha rather than painting a colour over it, and works on any background without knowing what sits behind.start/endresolve against the layout direction, so a row that fades at its trailing edge keeps doing so in RTL, and two ramps on one axis are shrunk proportionally to fit rather than overlapping into a double-masked band. Fading two perpendicular edges rounds the corner between them, which is the intended look. Two overloads: aDpone that skips the compositing layer entirely when every edge is zero, and a lambda one whose lengths are read in the draw phase, so a ramp tied to a scroll or drag redraws without recomposing.CompositingStrategy.Offscreenforces a layer, so it belongs on the scrolling container, never on each row.
[0.3.41] - 2026-09-15
Added
Aurum.motion.easingGlide—CubicBezier(0.16, 1, 0.3, 1), a decelerate with a long tail: nearly the whole distance in the first half of the time, then the last few units crawling to rest. It is the counter curve, and what a landing figure wants; the existing decelerate is at 97 % of the way by three-quarters time, so a longer duration only lengthened the blur before the same quick stop.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: a sheet, a hero card, a full-screen layer. Small UI keeps the plaineasingDecelerate/easingAccelerate.docs/tokens/motion.mdgains *Choosing a curve* — one curve per job — and *Considered, not adopted*, the curves we deliberately do not ship (back, overshoot, bounce, M2 sharp, symmetric ease-in-outs) and why, so they are not re-derived at a call site.AurumRollingNumber— a number that rolls to its value instead of appearing at it. It lands oneasingGlideover a duration set bypace, rolls later changes from the current figure oneasingDeceleratein the direction of the change, slides each digit into place while it does —durationQuick, ordurationStandardat theSlowpace so the final turns glide rather than flick — and gives aselecttick with a 1.5 % settle onspringFastSpatialwhen it stops. Digits are keyed from the right, so₹99 → ₹100keeps the glyphs it has and grows one at the front instead of reflowing. Aurum never decides how the figure is written:formatis the caller's, so currency, grouping and units come from wherever the surrounding copy gets them, and only the digits animate. 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.motion.*curve for a documented job (defaulteasingGlide). Reduced motion renders the final value with no roll; TalkBack reads the figure once, not digit by digit. Extracted from jar-android'sLockerRollingAmount, which wasinternalto one module and about to be forked for a third surface.
Fixed
AurumTransactionListCard— the status wash is now composited over the card's own surface before it is painted. It is a 9 % tint, and the design lays it over white; drawn straight onto a grey list page it came out pinkish-grey, which is how a pending row's "Transaction is pending" band looked on the transactions tab.
[0.3.40] - 2026-09-10
Added
AurumBottomSheetSurface— the bottom sheet's anatomy without its mechanism: handle,xxltop corners, page-base surface, navigation-bar inset and the padded primary-button slot.AurumBottomSheetis now this plus aModalBottomSheet, so existing callers are unaffected. It exists because aModalBottomSheetopens its own window, and nesting one inside a host that is already a sheet — Android'sBottomSheetDialogFragment, which is where most of jar-android's sheets live — gives two scrims, two slide-ups and two back handlers, with back dismissing the inner sheet and leaving the outer window swallowing touches. Six light sheets in the consumer had each hand-rolled the radius, handle and insets to avoid that; they can share this instead. It also previews for real, whichAurumBottomSheetcannot — aModalBottomSheetrenders nothing in a static preview, so the sheet's own previews have to stand in for it.
[0.3.39] - 2026-09-09
Added
Aurum.motion.durationScreen(300 ms) andAurumDefaultMotion. Navigating between screens is a different job from moving something inside one, and it had no token: 250 ms makes a screen swap feel clipped, 400 ms makes it drag. 300 is deliberately off the 50/150/250/400/600 rungs, and is what Material specifies for shared-axis screen transitions.AurumDefaultMotionexposes the token set outside composition — motion is never themed, so it resolves to exactly whatAurum.motiondoes, and it exists so code that runs before any composable (fragment transitions, built by a plain injected class) reads the tokens instead of choosing its own millis.
Fixed
- The bottom sheet has no Figma binding, because it cannot have one. 0.3.38 pointed Code Connect at the Type 1 design frame; that parses locally but the server rejects it at publish — Code Connect requires a
COMPONENTorCOMPONENT_SET, and the sheet's master is deliberately a frame. 0.3.38's Code Connect job failed for this reason (the AAR published fine; the two are separate workflows). The mapping is now a TODO marker likeAurumBanner's. That also removes a false green: the previous target6002:939is a real component but an empty one, so the spec audit had been fingerprinting a void and reporting the sheet "in sync" — coverage in appearance only. No snippet in Dev Mode now, and no misleading pass either.
[0.3.38] - 2026-09-08
Changed
- The bottom sheet's Figma binding points at its real design. Code Connect and the spec registry both named
6002:939, an emptyCOMPONENTwith zero children sitting at the Type 1 tile's exact coordinates — its hollowed-out twin from a duplicated page. So Dev Mode rendered the Compose snippet on a blank 360×312 box, and the committed baseline was a fingerprint of nothing (root.children: null), which is whymake component-audithad been reporting this component in sync against a void. Both now point at6346:1706; the target is a frame rather than a component because the master is deliberately not componentised, and a frame still carries the design. The@AurumFigmaKDoc deeplink moved with it. - The radius scale matches Figma again —
xlis 12, not 16. Design inserted a 12 rung asborderRadius/xland shifted every name abovelgup: what we calledxl(16) is Figma'sxxl, and ourxxl(24) is its3xl. Our export never picked the change up, so the same token name meant a different number on each side of the handoff — a designer bindingborderRadius/xlgot 12 whileAurum.radius.xlgave them 16. The scale is nowlg8 ·xl12 ·xxl16 ·xxxl24, withxxxlstanding in for Figma's3xlbecause a Kotlin identifier cannot start with a digit. - Every call site moved with the names, so nothing renders differently.
AurumBottomSheet,AurumTransactionListCardandAurumSurfaceall meant 16 and now sayxxl; the catalog's radius gallery gained the 12 rung. That the Roborazzi baselines are untouched is the proof, not a coincidence — a missed site would have shifted 16 to 12 and failed verify. AurumShapesgainedxxxlso the shape aliases stay one-to-one with the radius scale.
Notes
- Figma also carries an
opacity/*primitive scale (9% … 100%) that our export has never mirrored.Aurum.opacityis a hand-authored semantic layer (disabled/pressed/dragged/backdrop) and is not generated from it, so this is an unconsumed Figma group rather than drift. Left alone deliberately.
[0.3.37] - 2026-09-08
Added
AurumLinkButtontakes asize. Figma grew aSizeaxis (9 → 18 variants) that the component had no way to express:LargeistitleSSemiBold(16/24 SemiBold),SmallislabelLMedium(12/16 Medium).Largeis the default, so existing call sites move from 14/20 Bold to the size Figma actually specifies rather than silently keeping a third one.
Changed
AurumLinkButtonis 40 dp tall, not 56. Both sizes; only the label's type scale differs between them. The 8 dp gap and 16 dp padding already matched.- Plain
AurumPills carry a hard shadow.borderSurfaceHighContrastat y 1, on rectangular and rounded, whenever the pill is enabled — Figma authors it on default and focus and omits it on disabled. ThewithTagspill already had itspurple800shadow and now shares the same offset constant, since Figma gives both y 1.05. - A disabled
AurumPhoneNumberInputdims its country code.+91stayed at fulltextDefaultSubtlewhile the number greyed out. iOS already dimmed it, so this closes the divergence in the direction that was right rather than the one that was shared. Figma's disabled variant doesn't author the code text at all, so the design file settles nothing here. AurumPhoneNumberInput's field is 64 dp. Figma pins it at 64 in all nine variants because its leading flag/code/divider group is 32 tall, where a plain field's content is not — so the plain field's master is still 56 and its default is unchanged.AurumTextFieldLayoutgained an internalfieldMinHeightfor the difference; the field renders through the layout now rather than the public wrapper.
Tooling
- The component spec baselines are back in sync with live Figma. The weekly audit had been failing since July on four drifted components plus one that had never been baselined, so nobody could tell a new design change from the backlog. Re-recorded
AurumLinkButton,AurumPhoneNumberInput,AurumPill,AurumTaband (first time)AurumPillTabs;make component-auditreports 0 drifted, 0 unbaselined.AurumTabturned out to need no code at all — its selected gradient and radial wash have matched Figma token-for-token since 0.3.33 and only the baseline had gone stale. What Figma has genuinely moved on is recorded per component incomponent-specs/RECONCILIATION.md, not silently blessed by the re-record: a newSizeaxis onAurumLinkButton, a 56 → 64 field onAurumPhoneNumberInput, and a hard shadow on plainAurumPills. - A drift line is now readable in the issue it files. Values printed at 80 characters, which cut a gradient off mid-stop, and the 12-path cap was spent by a single edit that had landed on every variant — so the weekly issue could not be triaged without re-recording the baselines locally to see what changed. Values print at 240 and the cap is 24.
[0.3.36] - 2026-09-08
Added
AurumAmountInputcan roll its amount like an odometer (valueRollKey). Opt in by passing a key and bump it when a preset sets the amount: the key arms one roll, and the next change ofvalueturns the digits column by column from the previous amount to the new one, all in the direction of the change, staggered from the left. Columns are right-aligned so the units digit keeps its place while digits appear or disappear, and the value switches to tabular figures so a turning digit never nudges its neighbours. The arm is taken in composition, so it holds when the key and the value change in the same frame — the normal case for a synchronous state update. Typing never rolls. The value is drawn by an overlay while the field's own text stays transparent, so caret, selection and semantics are untouched; consumers that do not pass a key render exactly as before.AurumTextFieldLayout(internal).AurumTextFieldnow delegates to a layout withvalueOverlay/valueTextVisiblehooks; the public API is unchanged.- **Six spring tokens (
Aurum.motion.spring*) andAurumSpring.**springDefaultSpatial/springFastSpatial/springSlowSpatialfor anything that moves, resizes, scales or rotates;springDefaultEffects/springFastEffects/springSlowEffectsfor colour and alpha. The split is load-bearing: the spatial springs are under-damped and overshoot, the effects springs are pinned to damping 1.0 so they cannot — an overshooting alpha clips. Values are Material 3 Expressive's motion scheme adopted verbatim; our existing ad-hoc springs already clustered near them, so this is a refinement rather than a re-feel.AurumSpring.spec()materialises a token as a ComposeSpringSpec. The same six ship on aurum-ios as duration + bounce, converted bybounce = 1 - dampingRatioandduration = 2π / sqrt(stiffness). Aurum.motion.staggerStep(70 ms) andstaggerBudget(500 ms), applied throughstaggerDelay(index, count). 70 ms was already our de-facto interval — 29 call sites against one each for 80/90/100/120 — but an interval on its own invites a 30-item list at 70 ms apiece. The function compresses the step once the run would outlast the budget, so the ceiling is mechanical rather than advisory: past 8 siblings the last one still starts inside 500 ms.Modifier.aurumEnter(delayMillis)andModifier.aurumPopIn(delayMillis)— the two named entrances.aurumEnterfades up over a 14 dp rise ondurationEmphasized/easingDecelerate, for content that arrives with the screen;aurumPopInsprings from 0.6 onspringFastSpatialwhile it fades overdurationQuick, for a badge or glyph that should be noticed. Pass astaggerDelayto run a group in sequence, ornullfor the settled state. Travel distance is deliberately not a token — it would collide with the space scale — so it lives inside the entrances as a constant.Modifier.aurumPressScale(interactionSource). The 0.96 press sinkAurumPillcarried privately, promoted to a public modifier so feature code stops re-deriving it. Colours never shift, so it composes with any surface treatment.aurumReducedMotion(). True when the user has setANIMATOR_DURATION_SCALEto 0, or when the host is a preview / screenshot renderer. Both entrance modifiers consult it and render their settled state, so an animation-off device gets the end state instead of a frozen first frame, and preview tiles show the element at rest.Aurum.haptics— eight semantic haptic events.select·commit·reject·toggleOn·toggleOff·press·threshold·scrub, each bound once to aHapticFeedbackType. Version safety is not the point (Compose dispatches throughViewCompat.performHapticFeedback, which downgrades a newer constant) — this parenthetical was wrong, and is corrected in 0.3.42: Compose does no such downgrade, and five of these eight were silent below API 34 as a result: the point is that "which haptic means success" is decided once by design instead of per call site — jar-android currently reaches for nine constants to express about four conceptual events. The five policy rules ship next to the tokens, including no haptics during camera or microphone capture, and never the rawVibratorAPI.
Changed
Modifier.aurumErrorShakeis public. It wasinternalto the field family; the rejection cue is not field-specific, and feature code had no way to answer "not that" in the same language.AurumPill's press cue is nowaurumPressScale. The pill carried its own private copy onSpring.StiffnessMediumLow; it now runs onspringFastSpatial, so the sink is quicker and carries a slight settle. Same 0.96 depth, same draw-phase application — the pill's measured layout is unchanged.
Fixed
AurumMotion's KDoc labelled the entering and exiting easings backwards. The table calledeasingDecelerate"exits" andeasingAccelerate"enters".CubicBezier(0, 0, 0, 1)starts fast and settles — it is the entering curve.docs/tokens/motion.mdalways had it right; the KDoc now agrees, which matters because the KDoc is what the MCP serves.
Catalog
- A Motion gallery. Durations and easings race the same dot across the same track so they can be compared instead of described, the six springs show their overshoot, the stagger rule is rendered at 4 / 12 / 30 items so the budget compression is visible, the entrance modifiers replay on demand, and every haptic token has a button — the only honest way to review one is on a device.
Tooling
- The MCP manifest now carries
motionandhaptics.tooling/manifest/schema.jsonpinnedtokensto seven Figma-exported categories withadditionalProperties: false, and the generator deliberately skipped motion; an agent asking for a duration or a spring got nothing back. Both groups are now parsed off their Kotlin data classes and emitted as flat, kind-tagged token lists, somotion.durationStandard,motion.springFastSpatialandhaptics.commitresolve throughaurum_list_tokens/aurum_get_token_valueand show up in components'relatedTokens. Spring entries also carry the derived iOSduration/bouncepair. Both categories are optional in the schema so manifests from a generator that predates them stay valid. - The manifest no longer lists
internalcomposables as components.parse_componentsmatched any@Composable fun AurumXwhose name equalled its file's, visibility included, soAurumAmountRoll,AurumRollingTextandAurumStatusIconPop— implementation details of the amount field, the text field and the status icon — were emitted as public components and then failed the MCP-readiness check for lacking a@AurumIntendedUse/@AurumDo/@AurumDontcontract written for callers who cannot reach them. The scan now skips non-public declarations; the manifest describes 40 components instead of 43. - The manifest gate runs on the PR, not after the merge.
generate.py --validatelived only in the Pages deploy, which runs after a push to main — so a schema drift or a missing usage contract turned the gallery deploy red where nobody was looking (it had been failing since 0.3.35) instead of failing the PR that caused it.checknow runs the same validation before the Gradle build; it needs no Gradle and takes seconds.
[0.3.35] - 2026-09-02
Motion for the field family and the pill. No public API changes; every animation runs in the draw phase or as an insertion transition, so no component's measured 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 character positions that changed — up when the digit grew, down when it shrank — over 320 msmotion.easingEmphasizedwith a 25 ms per-index stagger. 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 dp horizontal, 360 ms, three oscillations decaying at 0.6, applied as agraphicsLayertranslation so nothing re-measures. It fires only on the flip *into* error: a field first composed 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 an
AnimatedVisibility(fade overmotion.durationQuick,expandVerticallyovermotion.durationStandard/easingStandard), replacing the single-frame layout jump. 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 aDampingRatioMediumBouncy/StiffnessMediumLowspring, in the draw phase, so the slot's measured size is constant.
Changed
AurumPillselection and press are now animated. Selecting a pill hard-cut its border frominteractive.borderNeutralDefaulttoborderPrimaryDefaultin a single frame; the border colour now animates overmotion.durationStandardwithmotion.easingStandard. Both bodies (plain andWithTags) are covered.AurumPillgained a dimensional press cue. The pill previously fell through to the default ripple with no interaction source of its own. It now sinks to 0.96 on press via a spring, matching the press languageAurumButtonalready uses — colours never shift. Applied through agraphicsLayerso the scale runs in the draw phase without recomposing the pill.
Catalog
- The Text Fields demo gained a live validating
AurumAmountInputthat exercises the roll, shake, support-text entrance and icon pop together.
Mirrored in aurum-ios 0.2.6 (AurumRollingText, aurumErrorShake, aurumStatusIconPop, AurumPillPressStyle) with the same motion-token values.
[0.3.34] - 2026-08-28
No library changes — AurumPillTabs, AurumPill and AurumTab are byte-identical to 0.3.33. This release exists to carry the CI fix into a tag so Code Connect can publish again.
Fixed
- Code Connect CLI pinned to v1. Both the workflow and the Makefile ran
npx @figma/code-connect@latest. Figma shipped CLI v2, which drops framework-specific parsers, so every Code Connect run in both aurum repos has failed since 2026-08-17 — regardless of content, dying while reading the config before any mapping is parsed. Pinned to@1(CLI 1.4.3); 207 mappings parse again, including the newAurumPillandAurumPillTabsentries. Migrating the config to v2 template files is tracked separately — note that v2 templates are.figma.tsstrings, which would give up the compile-time checking our.figma.ktfiles currently get.
Changed
- Dropped the
AURUM-DRIFTcomments added in 0.3.32/0.3.33. The values already resolve to the correct tokens and the magic numbers are named constants, so the markers weren't preventing drift — they were a note to the design team parked in source. The rebinding request lives in the design brief instead.
[0.3.33] - 2026-08-27
Fixed
- 0.3.32 hand-edited two generated token files.
AurumColors.ktandAurumLightColors.ktare emitted fromdesign-tokens/figma-export/by the codegen, and 0.3.32 addedvisual.neutral900/visual.neutralA400to them directly — which left both stale against the JSON and would have been reverted by the nextgenerate-tokensrun (aurum-ios' codegen gate caught this on the mirror PR). Thevisualgroup is the *decorative* palette (purple/yellow/green/red/orange/blue/pink/silver);neutralandblacklive only inprimitives, and Figma deliberately does not publish them as decorative shades. Both files are restored byte-identical to the export and the two tokens are withdrawn. AurumPillTabsnow derives its active fill from a semantic token. Figma bindscolors/neutral/a400andcolors/black/500on that node, neither of which has acodeSyntaxor a semantic background counterpart.interactive.bgStaticBlackDefaultcarries the same base (Black500=#121212), so the solid stop uses it directly and the faded stop derives from it at the design's declared 60% alpha. Rendering is unchanged from 0.3.32.
0.3.32 is functionally correct and renders identically — upgrade for the token hygiene, not for behaviour.
[0.3.32] - 2026-08-27
Added
AurumPillTabs+AurumPillTab— a new single-select segmented switch (7741:7306). A softbgSurfaceMidContrasttrack carrying 2–3 evenly-divided cells, with the active cell lifted as a dark pill (180°,neutralA400 → neutral900). Distinct fromAurumTabRow: that is page-level navigation with an underline indicator, this is an inline filter or mode switch scoped to one section. Labels-only or with a 16 dp leading glyph.- Tab selection now animates.
AurumPillTabsslides its active pill between cells on a spring (dampingRatio 0.78,StiffnessMediumLow) while cell labels crossfade overmotion.durationStandard; the pill is drawn once behind the row and its travel is read insidedrawBehind, so the whole transition stays on the draw phase and never recomposes a cell.AurumTab's selected wash fades in over the same duration instead of popping, alongside the underline slideAurumTabRowalready had. Aurum.colors.visual.neutral900andvisual.neutralA400. Figma's Pill Tabs master bindscolors/black/500andcolors/neutral/a400, both of which are real palette variables with nocodeSyntax— so they had no code counterpart and the component could not be fully token-bound. Surfaced on thevisualgroup, mapped to the existingAurumPalette.Neutral900/NeutralA400.
Fixed
AurumPillWithTagsrendered its tag band grey in the default state. The master (7678:1396) paints the bandinteractive.bgPrimaryDefaultwithtextOnPrimaryNormalin *both* default and focus — onlydisabledfades it. The component was falling back tobgNeutralFaded+textPrimaryDisabledunlessselectedwas set, so an unselected tagged pill lost its purple ribbon entirely. Consumer impact: every unselectedWithTagspill gains its purple band — visible in the daily/weekly/monthly savings amount presets, which is the intended look.AurumPillWithTagswas missing its hard shadow and sat two steps short. The master carries apurple800drop shadow aty=1, blur 0, spread 0, and measures 34 dp of body over a 14 dp band; the component drew no shadow and sized the body fromPillHeight − s2(28 dp). NowaurumHardShadow(purple800, offsetY = 1.dp)on the enabled states, with the two bands pinned to their master heights.AurumTabdropped the entire selected treatment from its master (5531:795). The active tab specifies a radial wash — bottom-centre, elliptical at0.639·w × 1.0·h,purple100 → bgPageBaseat 32% — and paints its label *and* icon with a linear gradient (180°,purple500from0.3225→purple200), not a flat colour. Both are now rendered; the icon uses theAurumIcon(tint: Brush)overload so the gradient fills the glyph rather than a box behind it. Consumer impact: selected tabs gain the wash and a two-tone label — every existingAurumTabRowpicks this up automatically.
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,bgPageBaseandpurple500, so they are token-bound in code and markedAURUM-DRIFTat the call site inAurumTabDefaults. Design should bind the variables so the plugin emits them directly. - Figma's Pills set specifies
16 px Semi Boldforrectangular/roundedfocus labels but14 px BoldforwithTagsfocus — a 2 px jump that reflows a pill on selection, and inconsistent within one component set. Implemented as14 px Bold(Title/XS-Bold) throughout, pending a design decision.
[0.3.31] - 2026-08-17
Fixed
AurumIcons.Status.Warning/WarningFilledshipped with their weights inverted. Both Figma masters share the nameIcons/Warning(weight is encoded only by sheet position), and the icon importer's manifest had the line/fill node ids swapped (5308:802↔5308:805) — soWarningrendered the solid badge andWarningFilledthe outline ring. The manifest now maps the sheet correctly; both drawables and their Code Connect mappings are regenerated. Consumer impact: everyWarningFilledcall site (text-field / amount-input error icons, warning banners and toasts) becomes the solid badge its master shows, andWarningbecomes the outline.AurumTransactionListCard's pending icon references the line weight and therefore turns outline — if its master intends the solid badge there, that call site should move toWarningFilledin a follow-up.
[0.3.30] - 2026-08-11
Added
AurumTextFieldgainsprefixandsuffixslots. Both render inline with the value inside the field's content padding, unlikeleading/trailing, whose M3 icon slots reserve a 48 dp minimum box. Useprefixfor tight value prefixes (currency glyphs) andsuffixfor derived equivalents (gold grams). Additive — existing call sites are unaffected.
Fixed
AurumAmountInputnow matches its Figma master's anatomy (5080:261). The₹moved from theleadingicon slot to the newprefixslot, closing the ~40 dp gap between the symbol and the amount to the master's 4 dp. ThesuffixTextequivalent moved from thetrailingicon slot to thesuffixslot, so it sits 16 dp from the field edge instead of nearly flush, and its colour corrected fromtextDefaultSubtleto the master'stextDefaultNormal. Loader / validation icons stay intrailingand still take precedence over the suffix.
[0.3.29] - 2026-07-30
Added
AurumIcons.Navigation.CaretBold{Up,Down,Left,Right}(+Filled). Their masters have been sitting in the canonical icon sheet (5130:35416) without code counterparts, so the sheet↔catalog contract was one-sided. Single-weight in Figma, so both weights resolve to the same drawable — the same convention the existing Caret family uses. The heavier caret is whatCaretCircleRightis built from, which is where consumers keep needing it.- Catalog gallery now lists the whole Caret family.
CaretUp/Down/Left/Rightshipped in code but were never added toIconGallery, so they were invisible in the catalog; listed now alongside the new bold set.
Fixed
AurumSectionHeaderAction.Linknow renders neutral-subtle, matching its Figma master (5442:462). The link action was styled identically to thetextaction —Title/XS-SemiBoldininteractive.textPrimaryNormal(brand purple) with a 20dpiconPrimaryNormalchevron — so "View All / See More" links shouted as loudly as the section title and were indistinguishable from a brand text-button. The sheet'saction linklayer specifiesBody/S-Mediumininteractive.textNeutralSubtlewith a 12dpinteractive.iconNeutralSubtlechevron; the component now follows it.TextActionis unchanged and remains the brand-emphasis option. Consumer impact: every existingLinkaction becomes grey and one step smaller — intended, but visible. aurum-ios mirrors this in 0.2.3.
[0.3.28] - 2026-07-21
Changed
AurumPhoneNumberInputdisplays the number groupedXXXXX XXXXX. A display-onlyVisualTransformationinserts a single space after the fifth digit (matching the Figma), while the stored value stays raw digits — public API unchanged (value: Stringis still the un-spaced number). Also widened the gap between the country-code divider and the number to 16dp (Figma4904:2076).
[0.3.27] - 2026-07-21
Fixed
AurumPhoneNumberInputtype, colour, and leading-slot order now match the Figma master (4904:2439). The entered number + placeholder render atTitle/M-Bold(20sp) instead of the inheritedbodyLMedium(16sp); the+91country code isTitle/S-BoldintextDefaultSubtle(wasbodyLRegularintextDefaultNormal); and the leading slot is ordered flag →+91→ divider (was flag → divider →+91), so the divider trails the country code and separates the prefix from the number. Consumers should render the India flag at 36×24.AurumTextFieldplaceholder now matches the field's text size and renders in the correct disabled grey. The placeholder hard-codedbodyLMedium, and becauseAurumTextfalls back totextDefaultNormalwhen given no explicit colour, it painted the placeholder near-black regardless of the M3 placeholder-colour config. It now inherits the field'stextStyle(so e.g. the phone field's 20sp placeholder matches its value — no size jump on first keystroke) and is explicitly colouredtextDefaultDisabled. Affects every field that shows a placeholder.
[0.3.26] - 2026-07-20
Removed
AurumIcons.Navigation.CaretCircleUp/Down/Left/Right(+Filled) — removed to restore the 1:1 sheet↔catalog contract. Their master components were deleted from the Figma "Component Icons" sheet (verified via the components API and the sheet subtree — no replacement nodes exist), and the current homefeed designs use Chevron icons exclusively (458 chevron instances, zero carets in the FINAL frames). Ghost entries also crashedmake icons-import(null REST response for deleted nodes) and failed every Code Connect publish with "node not found". Removes the manifest entries, 8 drawables, 8 catalog vals, and 8.figma.ktmappings. Consumer migration: jar-android'sCaretCirclePill(the only production usage) moves to a disc +AurumIcons.Navigation.ChevronRightcomposition in the companion jar-android PR. aurum-ios removes the same icons in the same sitting.
[0.3.25] - 2026-07-20
Fixed
AurumTextFieldhomes the caret at the end of a programmatically-set value. The field used theString-basedBasicTextField, which seeds the text selection at position 0, so any externally-provided value — a pre-filled phone number on the login screen, an autofill / number-hint suggestion — placed the caret *before* the first character, forcing users to move it to the end before editing. Rebuilt on aTextFieldValue-backed buffer that seeds and re-homes the caret to the end whenever the incoming value changes from outside; live typing keeps its own caret.AurumPhoneNumberInput,AurumAmountInput, andAurumSearchFieldinherit the fix; public API is unchanged (value: String/onValueChange: (String) -> Unit).
[0.3.24] - 2026-07-16
Changed
- **Renamed the Silver palette
visual.indigo*→visual.silver*** (and the backing primitiveIndigo*→Silver*), matching the design-system rename in Figma (_primitives+visual_colorsboth usesilvernow). Values are unchanged — a pure rename.visual.indigo*shipped only in 0.3.23 with a single internal consumer, so this corrects the name before it spread. UseAurum.colors.visual.silver50..1000.
[0.3.23] - 2026-07-16
Added
Aurum.colors.visual.indigo50..1000— the Silver brand palette. A new chromatic family, the cool blue-grey Silver analogue to howvisual.yellow*is Gold (from the Figma "Silver Indigo" palette section). Silver surfaces (the Silver locker/tab, silver savings cards) previously had no brand palette and mis-borrowed Blue/Neutral/Purple. Backed by newAurumPalette.Indigo50..1000primitives +IndigoA50..A200alpha tiers, and by realcolors/indigo/*variables added to the Figma_primitives+visual_colorscollections so the token source stays faithful. Purely additive — no existing token changed.
[0.3.22] - 2026-07-15
Fixed
AurumGlobalHeaderrenders a URL avatar full-bleed in the profile pill.profileContentwas placed at its intrinsic size, centered in the 44 dp pill, so a URL-loaded photo showed as a small inset with a wide ring of background around it. The slot now fills the pill's inner circle (inside the 1 dp border, clipped circular), so a full-bleed image reads as the avatar. The defaultprofileIconglyph path is unchanged (still a 20 dp icon). Callers pass afillMaxSizeimage withContentScale.Crop— no manual sizing or clipping.
[0.3.21] - 2026-07-08
Changed
AurumTextFieldmatches the Figma anatomy — no Material floating label. The label was passed into M3OutlinedTextField's label slot, so it rested inside the box and floated up into a notch cut in the top border on focus, and the placeholder stayed hidden until focused. Per the component sheet the label is a *static*Title/S-SemiBoldcaption above the field (greyed when disabled) and the placeholder shows whenever the value is empty. Rebuilt onBasicTextField+OutlinedTextFieldDefaults.DecorationBox: continuous 1.5 dp border (borderWidth.md;lgon focused error/success), default/disabled borderinteractive.borderNeutralHighlighted(was one shade too faint), containerbgSurfaceLowContrast(bound white, was transparent), readonlybgSurfaceMidContrastfill +borderSurfaceMidContrastborder, value/placeholderbodyLMedium, support textbodySMedium.AurumPhoneNumberInput,AurumAmountInput, andAurumSearchFieldinherit the fix; public API unchanged.
Added
AurumTextField(isLoading = …)— trailing loading spinner per the Figmaloadingstate; error / success states now auto-surface their trailing status icon when the caller supplies notrailing.AurumPhoneNumberInputdelegates to the shared affordance.
[0.3.20] - 2026-07-08
Added
AurumBanner(windowInsets = …)— M3 app-bar convention: insets are padded *inside* the tone background, so a top-anchored band paints its colour under the status bar while content stays clear. PassWindowInsets.statusBarsfor window-edge banners; defaults to none.
Changed
AurumBannerHostpushes instead of overlaying. Enter/exit now animatesexpandVertically/shrinkVertically(plus the existing slide + fade), so a host placed in the layout flow (first child of the root Column / a top slot the chrome is constrained below) smoothly pushes the content beneath it down and releases it — the structural-band behaviour used by the app-wide connectivity strip. Overlay placements keep working.AurumChipstate colours match the Figma component set (4446-701) exactly.Selectedfills the 9% brand wash (borderPrimaryMuted— the spec's bound fill) instead of white, withborderPrimaryDefaultborder; the Neutral default border is now type-aware (Other→ hairlineborderNeutralMuted,Action→borderNeutralHighlighted); Neutral pressed fillsborderNeutralDefault(Neutral50) per the spec binding.
Fixed
AurumChipdisabled chips no longer double-dim — the extra 0.40 alpha layer is gone; the disabled tokens (bgNeutralDisabled/textNeutralDisabled/borderNeutralMuted) already encode the muted look and the Figma disabled variants are opacity 1.
[0.3.19] - 2026-07-06
Added
Modifier.aurumInnerShadow(color, blur, offsetX, offsetY, shape)— FigmaINNER_SHADOWfor Compose, which has no inner-shadow primitive. Clips toshapeand draws the shape's *inverse* ring behind asetShadowLayerpaint, so only the shadow bleeding inward is visible — the same construction Figma uses. PositiveoffsetYcasts from the top edge, negative from the bottom. First consumer: the DS-swipe gold hero panel (yellow800@ 24%, blur 16, offsetY −4), Figma10103:18130.
[0.3.18] - 2026-07-06
Added
aurumShadow(alphaMask: Brush?)— Figma derives a drop shadow from the node's *rendered* alpha, so a surface whose fill fades to transparent needs its shadow to fade with it. Pass the fill brush and the shadow is masked through it (saveLayer+BlendMode.DstIn);nullkeeps the plain outline shadow. Built for fade-out cards (e.g. the transactions empty-state CTA card, Figma8498:34146).
Changed
AurumButtonprimary press is dimensional, not tonal. Pressed no longer swaps the radial fill forbgPrimaryHighlighted+ 4 dp muted ring — the fill and top-lit rim stay constant, and on full-width primaries the cue is the purple/800 hard shadow dropping while the button sinks 2 dp onto it (ripple suppressed there; inline primaries keep the ripple as their only cue). Product call (2026-07-06): press feedback should read as 3D depth, never a colour shift — deviates from the Figma pressed variant, pending a design rebind.
Fixed
aurumShadowno longer paints under the node itself (Figma drop shadows areshowShadowBehindNode=false): the blurred silhouette used to bleed a tint wash through translucent/gradient fills. The node's own area is now clipped out of the shadow draw; opaque surfaces render identically.
[0.3.17] - 2026-07-06
Changed
AurumButtonrebuilt as a custom composable — no Material 3. The oldmaterial3.Buttonwrapper drew its border inside theSurface's own shape-clip, shaving the top-lit rim's outer edge and leaving a visible seam ("doubled" upper edge) on the radial primary. Replaced with aRow+clickable(ripple)+ Aurum-painted surface and a 48 dp touch target; public API is unchanged (zero call-site changes). Every state now matches the Figma component exactly — primary: default (radial purple600→400 + white 60→0% rim), pressed (purple800 fill +borderPrimaryMuted4 dp ring), disabled (neutral 9% +textPrimaryDisabled), loading (solid purple500 + white 20→0% rim + spinner), progress (purple100 track + purple500 fill); secondary outline/pressed/disabled; tertiary grey/pressed-ring/disabled. This also unblocks bespoke press interactions (e.g. a 3D press) that M3 constrained.
Fixed
AurumLinkButton— pressed state now shifts the label totextPrimarySubtle(purple300) with no background, per the Figma link-button spec (was a static colour with a ripple).
[0.3.16] - 2026-07-03
Fixed
AurumChip— Black variant filledbgStaticWhite*(white-on-white text); nowbgStaticBlack*. Every variant gains its spec 1 dp stroke (neutralborderNeutralHighlighted; pressed/black/disabledborderNeutralMuted; brandborderPrimaryMuted). Small-chip icons 14 dp.AurumBadge— intense-emphasis content colourtext*Subtle(tints) →text*Inverse(white on solid tone) across all six roles.AurumToast— drop shadow added on every variant viaaurumShadow(nearest tinthighRaised@18% vs spec #000 @16% — no exact token, flagged); brand stroke follows the spec bindingbgPrimarySubtle; label→close gap 4 dp.
[0.3.15] - 2026-07-03
Added
- Token resync to live Figma —
feedback/*/subtlerebound from white to real tints (green/red/orange 400, blue/purple 300, neutral 500;text/neutral/intense600→900),interactive/background/*/faded100→50 shades,interactive/border/{information,primary}/disabled→ 9% alpha neutral. Typography atoms3xl=40/4xl=48/lineHeight 3xl=48/ExtraBold=800and the newAurum.type.num3XL(Inter Bold 40/48). Export JSONs mirrored to live. The borderRadius re-index (xl 16→12) is deliberately HELD pending design confirmation. AurumIcons.Media.PlayCircle(89th glyph) + knockout-aware icon importer:<rect>/<circle>/<ellipse>converted to path data and dark-base + white-overlay glyphs merged into single tintable even-odd paths (CaretCircle* restyle).- Component spec fingerprints —
make component-auditdiffs every component's live Figma master against committed baselines (design-tokens/component-specs/); weeklycomponent-drift.ymlCI files an issue on drift;RECONCILIATION.mdtracks code↔spec status (full 2026-07-03 sweep recorded).
Fixed
AurumButtonprimary matches the restyled Figma master — elliptical radial fill purple600→400 (bottom-centre anchor), 1 dp top-lit white 60→0% rim, and a purple/800 hard shadow (y=2) only whenisFullWidth(inline primaries are flat, per the Figma variants). Pressed is a real state: flat highlighted fill + 4 dpborderPrimaryMutedring; tertiary's ring is now pressed-only.AurumIconCaretCircleRightCode Connect re-pointed to the re-created master7085:15336— un-breaks the Code Connect publish that failed on every release tag.
[0.3.14] - 2026-07-02
Added
AurumSmoothCornerShape+Aurum.shape.smooth(radius, smoothing)— continuous-curvature ("squircle") rounded rectangle, the Compose analogue of Figma'scornerSmoothing. Backed by AndroidXgraphics-shapes(RoundedPolygon.rectangle+CornerRounding): each corner renders as three cubic curves (circular centre + edge-blending flanks).smoothingmaps Figma's 0..1 slider, default 0.6 (Figma's "iOS" preset);0degrades to theOutline.Roundedfast path. Path cached per size, so scroll-feed safe. New dependency:androidx.graphics:graphics-shapes:1.0.1.- Figma plugin 0.7.0 —
cornerSmoothingdecode.analyzeShapenow reads the node'scornerSmoothing: uniform-radius nodes with smoothing > 0.05 emitAurum.shape.smooth(N.dp)(with an explicitsmoothing = …fargument when it deviates from the 0.6 preset); per-corner-radius nodes with smoothing surface a visible// note:drift marker instead of silently dropping it.
Fixed
AurumNavBarCenterQr dome — three drifts from Figma5575:14061: the dome's radial was a circular(0.5, −1) × 2approximation (now the plugin-decoded elliptical recipe: centre(0.5, 0), radii2.96 × 0.91, rotated−26°); the QR glyph rendered ~22 dp of drawn content in a 27 dp box (icon paths cover 19.5/24 of the viewport — the box is now 33 dp so the glyph measures the design's 27 dp); and the selected-icon gradient reached fullpink/50at the glyph bottom while the design's gradient handles extend 1.64× past it (the ramp now ends at the 61%purple/500 → pink/50blend, shared by selected tabs and the QR glyph).
[0.3.13] - 2026-07-01
Added
aurumRadialBrush— elliptical / transform-aware overloadaurumRadialBrush(vararg stops, centerFraction, radiusFractionX, radiusFractionY, rotationDegrees). The circular overload uses a singleradiusFraction = fraction · max(w, h), which collapses a FigmaGRADIENT_RADIALwith unequal/rotated axes to a circle — so on a wide-short surface (e.g. a 308×58 card) the glow washes out flat. The new overload gives the horizontal and vertical extents independent radii (+ rotation) by stretching the shader via alocalMatrix, so the glow fades across the height as designed. The circular overload is unchanged.
Fixed
- Figma plugin
radialGradientParamstook the gradient centre asT⁻¹(0, 0.5)— an axis *endpoint* (e.g.(0.5, −1), a full card-height above the surface) — instead of the true centreT⁻¹(0.5, 0.5), and collapsed the ellipse to one radius. It now emits the true centre plusradiusFractionX/Y+rotationDegrees(principal axes via the 2×2 SVD of the conjugate half-axes), so the plugin's Compose recipe reproduces elliptical Figma radials faithfully instead of a flat circle.
[0.3.12] - 2026-07-01
Fixed
AurumOtpInput— fixes two regressions from the 0.3.11 masking approach. (1) The system's selection/cursor teardrop handle leaked over the cells:cursorBrush = Transparenthides only the cursor *line*, while the handle is drawn fromLocalTextSelectionColors.handleColor(Aurum purple) — so a purple teardrop rendered on cell 1 after a re-tap. (2) The keyboard did not reopen after a back-press dismissed it —requestFocus()is a no-op on a still-focused field andSoftwareKeyboardController.show()can't restart a dismissed session. The field now suppresses selection handles entirely (transparentLocalTextSelectionColors; the active-cell underline is the sole caret cue, correct for a masked input), and the tap-catcher gates onWindowInsets.isImeVisible: keyboard up → just re-focus (no flicker); hidden (first tap / after back) → cycle focus (clear → re-pin caret to end → re-request) to fire a fresh focus-gain that reopens the IME without stranding the caret at offset 0. Device-verified on the catalog OTP demo: no teardrop, keyboard reopens after back, and input always appends. Internal-only; the public API is unchanged. Visually identical — Roborazzi baselines unaffected.
[0.3.11] - 2026-06-30
Fixed
AurumOtpInput— the 0.3.10 caret fix was insufficient (PFPD-99 reopened). Pinning theTextFieldValueselection toTextRange(text.length)only corrects the caret ononValueChange, but a bare tap on a filled cell reaches the hiddenBasicTextField's built-in tap-to-position gesture — which repositions the caret with no text change — so the next digit still overwrote the tapped cell. A transparent tap-catcher overlay now sits above the hidden field and only callsrequestFocus(), so taps can never reach the field's positioning gesture: the caret stays pinned to the end and input always appends. Device-verified on the catalog OTP demo (tap cell 1 → type → digit appends at the end). Internal-only; the public API (value: String/onValueChange: (String) -> Unit) is unchanged. Visually identical — Roborazzi baselines unaffected. (Trade-off: long-press-to-paste on the cells is intercepted; OTP paste continues to work via the keyboard's SMS-autofill chip / auto-read.)
[0.3.10] - 2026-06-29
Fixed
AurumOtpInput— tapping the cell row no longer snaps the caret to the first cell (PFPD-99). The hidden field used theBasicTextField(value: String, …)overload, which carries no selection, so theclickablerow'srequestFocus()could land the caret at offset 0 and the next typed digit overwrote the first cell instead of appending. It now drives the field with aTextFieldValuewhose selection is pinned toTextRange(text.length)on both externalvaluechanges (SMS autofill / resend reset) andonValueChange, so input always continues from the last entered digit. Internal-only — the public API (value: String/onValueChange: (String) -> Unit) is unchanged.
[0.3.9] - 2026-06-22
Fixed
AurumPhoneNumberInput— leading slot now matches the Figma master (fileYvIxqu2oTlM6UnkL0OloHc, node4904-2455): the country flag was pinned to the rounded border (the M3leadingIconslot gives a full-bleed flag image no optical inset, so it visually clipped against the field edge), and the divider sat *after* the country code (flag +91 │ number) instead of between the flag and code. Now: a start inset keeps the flag clear of the border, and the order isflag │ +91 number. The divider is also dropped when noflagis supplied (so the code never leads with a stray rule). Visual-only; the public API is unchanged.
[0.3.8] - 2026-06-18
Fixed
AurumPhoneNumberInput— now renders the trailing validation icon and loading spinner from its Figma component (fileYvIxqu2oTlM6UnkL0OloHc, node4904-2455), reaching parity withAurumAmountInput(which got this in 0.3.7 — the phone input was missed in that pass).isSuccessshowsAurumIcons.Status.SuccessFilled(tintedinteractive.iconPositiveNormal),isErrorshowsWarningFilled(tintedinteractive.iconNegativeNormal), and a newisLoadingparam renders anAurumLoader— matching the FigmastatexvalidationStatevariants. PreviouslyisSuccess/isErroronly recoloured the border (no icon) and there was no loading state at all. Additive, non-breaking. NewPreviewAurumPhoneNumberInputLoading; Code Connect mapsstate=loading -> isLoading.
[0.3.7] - 2026-06-09
Added
- Responsive width-scaling in
AurumTheme(AurumWidthScaling) — every.dp/.spunder the theme now scales byk = (smallestScreenWidthDp / 360).coerceIn(1.0, 1.15), so a layout authored at the 360dp Figma reference keeps its proportions on wider phones instead of looking "airy" (a 411dp phone → ×1.14; verified on-device — a raw-dphome-feed card grew height ×1.14 with width unchanged). Implemented as aLocalDensity.densityoverride at the singleAurumThemechoke point — zero call-site churn, no.sdp/.ssp— that preservesfontScale, so the user's accessibility text-scaling still composes on top. Up-only clamp (never shrinks below the reference → touch targets stay safe; caps growth so tablets/foldables hand off toWindowSizeClassrather than ballooning). NestedAurumThemeis idempotent via the newLocalAurumBaseDensity(re-scales the same base, neverk²). NewwidthScalingparam onAurumTheme(defaultAurumWidthScaling.Default;Disabledrenders pixel-exact to Figma;fixed()pins a factor for previews). Catalog Scaling gallery demonstrates the spectrum on one device. Additive API (optional param + new class), non-breaking — renders identically at 360dp — but default-on, so every Aurum surface scales up on >360dp phones by design. Replaces the temptation to reintroduce.sdp/.ssp; see README → *Sizing*.
Changed
AurumTextField— additivetextStyleparam (defaults tobodyLRegular). Lets specialised inputs set the entered-value typography; existing callers are unaffected (byte-identical default).
Fixed
AurumAmountInput— aligned to the Figma component (fileYvIxqu2oTlM6UnkL0OloHc, node5080-261) after a layer-by-layer audit. The entered amount now renders innumXL(Inter Bold 28) and the ₹ prefix innumL(Inter Bold 24) — previously the value fell back tobodyLRegular(Inter 16 Regular) and the ₹ useddisplayLBold(the serif Frank Ruhl Libre, wrong family). The gold-gramssuffixTextis nowbodyMRegular(14, wasbodyLRegular16) and inset from the field's trailing edge (was flush). The success / error validation states now render the trailing status icon (AurumIcons.Status.SuccessFilledtintedinteractive.iconPositiveNormal/WarningFilledtintedinteractive.iconNegativeNormal), matching the FigmavalidationStatevariants. Verified against the Figma state×validation variants via Roborazzi.AurumBottomSheetcarries the width-scale into the sheet window — aModalBottomSheethosts its content in a new window that re-provides the platformLocalDensityfrom the system config, which droppedAurumTheme's width-scale (the Aurum token locals still inherited; the platform density did not). The sheet now re-applies the enclosing scaled density to its content and drag handle, so sheet content matches the page behind it — verified on-device (a sheet tile's chevron measured 42 px unscaled → 48 px after the fix, matching the page's k=1.14). Rawmaterial3.ModalBottomSheet/Dialogused directly in feature code need the same one-liner — preferAurumBottomSheet.AurumBottomSheetno longer forces consumers to opt in toExperimentalMaterial3Api— itssheetStatedefault wasrememberModalBottomSheetState(...), and for a@Composablethat default is evaluated at the caller's site, so every feature-code caller had to add@OptIn(ExperimentalMaterial3Api::class)— defeating the point of a material-free DS wrapper (it broke the jar-androidLightCriticalActionsBottomSheetmigration). thesheetStateparameter was removed from the public signature — itsandroidx.compose.material3.SheetStatetype leaked the experimental opt-in to consumers of the published AAR (a binary consumer doesn't honour the wrapper's@OptInfor an *exposed experimental type*). The state is created internally now; callers drive the sheet by toggling whether it is composed, plusonDismiss(no caller passedsheetState). Programmatic state control can return later via an Aurum-owned wrapper. Source-compatible for every existing caller.
[0.3.6] - 2026-06-02
Added
AurumPageHeader.colorScheme— newAurumPageHeaderColorScheme { OnLight; OnDark }param (defaultOnLight).OnDarkflips the title, subtitle, and all icon tints to the theme-invariantsurface.iconStaticWhiteNormal/surface.textStaticWhiteNormaltones so a Page Header can sit over a dark hero backdrop (pair withcontainerColor = Color.Transparent). MirrorsAurumGlobalHeaderColorScheme1:1.contentColorbecomes an optional text override (Color.Unspecifieddefault defers to the scheme); icon tints now follow the scheme instead of a hardcodedinteractive.iconNeutralNormal(whichcontentColornever actually reached). Additive, non-breaking —OnLightrenders byte-identically to before. NewPreviewOnDark. Unblocks the jar-android Instant Save hero toolbar (back + title over a dark BE-image hero).
[0.3.5] - 2026-05-31
Added
AurumPill— a compact, label-first status / token element (quieter thanAurumChip). Mirrors the Figma "Pills" set (fileYvIxqu2oTlM6UnkL0OloHc, node5891-802):type= Rounded / Rectangular / WithTags, state = default /selected(Figma focus) / disabled, optional leading/trailing icons, and atagribbon for WithTags. Scratch (sibling toAurumChip), full@AurumFigma+ Code Connect binding, catalogPillsDemo. Closes one of the three Figma-coverage gaps.AurumProgressBar— a determinate linear progress bar (8dp pill track + primary indicator). Mirrors the Figma "Progress Bar - Linear" set (node5934-846):progress(0f..1f), optionallabelheader (FigmashownHeader) and trailing%(FigmashownProgress). Scratch, infeedback/,@AurumFigma+ Code Connect, catalogProgressDemo. Closes the second Figma-coverage gap.AurumSegmentedProgressBar— discrete N-segment progress. Mirrors the Figma "Progress Bar - Segmented" set (node5889-2361):type= Bars / Bubbles (numbered-checkpoint stepper),intent(6: Default + 5 feedback tones),filled/totalcounts, optional header + %. Scratch, infeedback/,@AurumFigma+ Code Connect, catalog demo. Closes the third and final Figma-coverage gap — every ✅ Ready-for-dev Figma component now has code.- 12 feedback
inversetokens —feedback.{icon,text}.{primary,information,positive,negative,notice,neutral}.inverse, all resolving toNeutral0(#FFFFFF). White icon/text content for feedback rendered on a tonal-intense (saturated) surface — the third intensity alongsideintense/subtle, and the exact gap that forced the toast/snackbar white-on-tone workarounds. Added toFeedbackColorson the icon + text axes only (background + border keep 2 intensities, matching Figma). Surfaced by auditing live Figma variables against the committed token layer (plugin-API drift detection) — design had added them since the last export. Additive, non-breaking. - Figma token export artifacts re-synced to live Figma —
design-tokens/figma-export/*.jsonbrought back in line with the live variable set: the 12inverseentries added totheme.onLight; colour primitive leaf-names de-prefixed (colors/blue/blue_500→colors/blue/500— a Figma-side cleanup, values unchanged);typographyfontFamilykeys lowercased (Display→display,Primary→primary) and the orphanedlineHeight/4xsdropped;Booleanprimitive added. Zero residual drift, re-verified by replaying the plugin-API audit against the refreshed files. The cosmetic renames don't touch the generated Kotlin. AurumBanner+AurumBannerHost— a persistent, top-anchored, full-bleed tonal status strip (offline / downtime / account warnings) and its caller-driven host. It is the persistent counterpart of the transientAurumToast— same 6-tone tonal language and per-tone status glyphs (feedback.*subtle fill over opaquesurface.bgPageBase+ matching intense content) — but structural rather than floating: square corners, full-bleedfillMaxWidth, a 1dp bottom hairline, no clip. Supports an optional inline textaction(e.g. "Retry") and an optional trailing dismiss ✕ (onDismiss/dismissible); state banners are non-dismissible and persist until the condition resolves.AurumBannerHostanimates a single banner in from the top (slideInVertically { -it }) with no auto-dismiss timer (vs. the toast host's queue + timer) — the caller owns show/dismiss. No Figma node yet — proposal-grade, to reconcile when design produces the spec. CatalogBannerDemo(all tones, with/without action, dismissible, host). Code Connect stub (AurumBanner.figma.kt,urlpending design) +classification.mdrows added per the add-component ritual.- 11 icons synced from the Figma "Component Icons" frame (node
5130:35416):Navigation.Caret{Up,Down,Left,Right}+Navigation.CaretCircle{Up,Down,Left,Right}(single-weight; distinct from the existing Chevron set),Content.Star,Content.ChartBar, andCommerce.Bank(each line + fill). The catalog is now 88 icons / 176 drawables. Imported viatooling/icons/import_from_figma.py(ICON_MANIFESTextended) + Code Connect bindings regenerated. Also refreshed 6 existing glyphs the design team refined (action_qr_code,content_broadcast_filled,media_replay,user_nek).
Removed
AurumSnackbar(internalcomponent/scaffold/) — deleted. It pairedsurface.bgSurfaceHighContrast(#DCDDE3, a *light* surface) withsurface.textDefaultInverse(#FFFFFF, white) and rendered white-on-light-grey (illegible), and it had no Figma counterpart. The design system's feedback primitive is the Figma-backedAurumToast(a light, tone-coloured strip — fileYvIxqu2oTlM6UnkL0OloHc, node6014:2621), not a dark M3 snackbar.
Changed
AurumLoader— added optionallabel+labelPosition(right / bottom) to match the Figma Spinner'sshownLabelvariants, and added the previously-missing Code Connect binding +@AurumFigma(node4530-2084). It was wrongly tagged code-only; it's a Figma-backed component (thesize/colorFigma axes were already covered by its continuousDp/Colorparams).- Renamed
AurumTopAppBar→AurumPageHeader(andAurumTopAppBarAction/AurumTopAppBarButton→AurumPageHeaderAction/AurumPageHeaderButton; fileAurumPageHeader.kt). The component's Figma name is "Page Header" (fileYvIxqu2oTlM6UnkL0OloHc, set4826:1058), and "Page Header" is the industry convention for a content-level title-and-actions row (Atlassian, GitHub Primer, Polaris, Ant Design, Salesforce). The old Material-derived name wrongly implied it wrapsmaterial3.TopAppBar— which it explicitly does not (it's a scratch component). Clean rename, no deprecation alias (Aurum is pre-release / in active light-theme migration); the single jar-android consumer migrated in lockstep. AurumPageHeaderprimary button synced to Figma (4826:1058, chip5431:2985) — thesnackbarHostslot renders the canonicalAurumToast(Neutral tone, Large) instead of the removedAurumSnackbar. The publicsnackbarHostState: SnackbarHostStateAPI is unchanged (non-breaking);snackbarHostState.showSnackbar(...)now surfaces the legible, Figma-faithful toast. M3SnackbarDatacarries no tone, so screen-level snackbars are Neutral — for tone-specific feedback (Error/Success/…), useAurumToastHost+showToast(tone = …)directly.AurumToastleading-icon override — new optionalleadingIcon: ImageVector? = nullparam (default → the tone's status glyph). Supply to swap the glyph — still tinted to the tone's content colour + sized by the toast — orshowLeadingIcon = falseto hide it. A controlled override (not a free@Composableslot) so the DS keeps tint/size consistent; lets consumers (and thesnackBar()migration) keep a bespoke icon without losing the tonal default.AurumTopAppBarprimary button synced to Figma (4826:1058, chip5431:2985) — now 36dp tall with a 1dpinteractive.borderPrimaryMutedring, 12dp horizontal padding, and alabelLMedium(12/16 Medium) label (was 32dp, no border, 8dp,titleXSSemiBold14/20). Every other Page Header slot (variant axes, titletitleSSemiBold, subtitle, back chevron, 56dp/16dp layout, icons) already matched the design.
Fixed
AurumToastnow renders opaque — composites each tone's subtle (low-alpha) fill (e.g.feedback.bgNegativeSubtle=#D8320917, 9% alpha) oversurface.bgPageBase(opaque white) inside the component. Previously only the low-alpha tint was painted, so a toast floating over app content — rather than the white Figma page the design was drawn on — let the backdrop bleed through. It now reads as the intended solid pastel on any surface.AurumToastHostapplies a consistent 16dp margin — the default renderer now insets the toast byspace.s5(16dp) on the sides and the bottom (was horizontal-only), so it floats with the design's 16dp gap on any screen. Callers supply only window insets (e.g.navigationBarsPadding()); no per-screen bottom offset needed.- Error toast icon —
leadingIconFor(Error)now uses the filled⊗(Navigation.CloseFilled, the fill variant ofIcons/X) instead of the plainNavigation.Close(✕), which duplicated the trailing dismiss ✕. Matches the Figma Error toast (node6014:2621); the other five tones were already correct.
[0.3.4] - 2026-05-21
Added
AurumButton.progressparam — optionalFloat?(0f..1f) that renders the auto-advance progress state from the Figma buttonstate=progressvariant (fileYvIxqu2oTlM6UnkL0OloHc, node4692:1074). When non-null the button paints a faded-primary track (interactive.bgPrimaryFaded) with a primary fill (interactive.bgPrimaryDefault) that grows toprogress, swaps the M3 container to transparent, and dims the label/icon tointeractive.textOnPrimaryDisabled.null(default) keeps the normal fill — non-breaking, additive. Driveprogressfrom a countdown for CTAs that proceed on their own (e.g. onboarding auto-advance). NewPreviewProgressVariants.
Fixed
AurumGlobalHeaderOnDarkpill fidelity — restored translucent radial fill + linear-gradient border + linear-gradient divider per the FigmaGlobal Headercomponent (fileCXq7IVmAMMc7qCKT82GrM9, node7174:11139). The previousOnDarkarm rendered every pill asSolidColor(interactive.bgStaticWhiteFaded)with a bakedColor.White.copy(alpha = 0.09f)hairline andColor.White.copy(alpha = 0.18f)divider — flat and tokenless. Now matches the Aurum Compose Figma plugin emission verbatim: pill fill isaurumRadialBrush(bgStaticWhiteFaded@α0.18 → bgStaticBlackFaded@α0.18, center=(1.55, -0.56), radius=1.47), border isaurumLinearBrush(180°, borderNeutralMuted@α0.09 → borderSurfaceHighContrast → borderNeutralMuted@α0.09), divider isaurumLinearBrush(90°, borderNeutralMuted@α0.04 → borderSurfaceHighContrast@α0.4 → borderNeutralMuted@α0.04).HeaderPillColors.borderanddividerTintwidened fromColortoBrush(and the field renameddivider) to carry the gradients — internal type, no public API impact.OnLightarm visually unchanged (the existing solid border is wrapped inSolidColor(…)). Consumers that render the header withcolorScheme = OnDark(e.g. the jar-android home feed) pick up the canonical translucent-glass treatment automatically.
[0.3.3] - 2026-05-19
Added
AurumGlobalHeader.colorSchemeparam — newAurumGlobalHeaderColorSchemesealed type (OnLight,OnDark). DefaultOnLightpreserves the existing pill treatment;OnDarkswaps every pill background to a solid translucent-white wash (interactive.bgStaticWhiteFaded), border to a faded white hairline, and icon + text tints to theiconStaticWhiteNormal/textStaticWhiteNormal/textStaticWhiteSubtletones. UseOnDarkwhen the header sits on a dark hero backdrop (e.g. the home-feed locker zone); pair withcontainerColor = Color.Transparentso the underlying backdrop reads through. NewPreviewOnDarkLivePricecovers the dark path. Internal refactor: a privateHeaderPillColorsdata class threads the resolved tone set into every sub-component (ProfilePill / SingleIconPill / RewardsAndNotificationsPill / LiveBuyPricePill / PillFrame), replacing the previous in-linepillSheen()brush + hardcodediconDefaultNormal/textDefaultNormalreads. No call-site change required for existing consumers.
Changed
- Typography scale rebuilt as a 1:1 mirror of the Figma Typography page (
YvIxqu2oTlM6UnkL0OloHc#5077:1488). The old hand-curated scale (20 tokens) had multiple sizes (11sp, 18sp, 40-72sp) and weights (Inter Medium in Title family, SemiBold at 14sp Label) that don't exist in Figma's catalog. The new scale ships 44 composites across 5 Figma-aligned families: Display (Frank Ruhl Libre S/M/L/XL/XXL × Bold/Medium), Title (Inter XS/S/M/L/XL/XXL × Bold/SemiBold), Body (Inter XS/S/M/L/XL × Regular/Medium), Label (Inter S/M/L × Bold/Medium), Num (Inter Bold XS/S/M/L/XL/XXL). Naming follows<family><Size><Weight>(e.g.numXL,bodyMMedium,titleSSemiBold). All ~210 internal Aurum usages migrated to the new tokens; M3MaterialBridge.ktremapped to the new scale. - Breaking — every removed legacy token has a clear replacement. Migration map:
| Removed | Replacement | Notes |
|---|---|---|
| bodyLarge / bodyMedium / bodySmall / bodyXSmall | bodyLRegular / bodyMRegular / bodySRegular / bodyXSRegular | Same value, Figma-aligned naming |
| bodyB3 | bodySRegular | Was duplicate of bodySmall |
| captionMedium (11sp) | bodySRegular (12sp) | 11sp not in Figma scale; 1sp upsize |
| titleT1 (Inter Medium 16/24) | bodyLMedium | Title family is Bold/SemiBold only in Figma; this was Body-shaped |
| titleT2 (Inter Medium 14/20) | bodyMMedium | Same reasoning |
| titleT1.copy(SemiBold) | titleSSemiBold | Exact value preserved |
| titleT2.copy(SemiBold) | titleXSSemiBold | Exact value preserved |
| titleT2.copy(Bold) | titleXSBold | Exact value preserved |
| labelL1 (SemiBold 14/20) | titleXSSemiBold | 14sp not in Label scale (Label tops at 12sp); SemiBold lives in Title |
| labelL1.copy(Bold) | titleXSBold | Exact value preserved |
| labelL2 (SemiBold 12/16) | labelLMedium | SemiBold→Medium weight shift (no Inter SemiBold 12/16 in Figma) |
| headingH6 (Inter Bold 14/20) | titleXSBold | Same value, Figma-aligned naming |
| headingSmall (display 18/22) | displaySBold | 18sp not in Figma; size 16sp + weight Bold |
| headingMedium (display 20/24) | displayMBold | Line height 24→28 + SemiBold→Bold |
| headingLarge (display 24/28) | displayLBold | Line height 28→32 + SemiBold→Bold |
| headingXLarge (display 32/36) | displayXXLBold | Line height 36→40 + SemiBold→Bold |
| heading2XLarge (display 40/44) | displayXXLBold | 40sp not in Figma; size 32sp |
| displayXLarge (72sp) / displayLarge (64sp) / displayMedium (56sp) / displaySmall (48sp) | displayXXLBold (32sp) | None in Figma; size capped at scale max 32sp |
Roborazzi baselines will shift wherever a visible-value change applies (line-height fixes on Display, SemiBold→Bold on Display family, captionMedium 11→12, labelL2 SemiBold→Medium, hand-tuned Display 40-72sp clamped to 32sp). The migration is mechanical 1:1 for >80% of call sites.
- **Token drift fix —
interactive.borderNeutral*realigned.**borderNeutralDefaultNeutral300→Neutral50,borderNeutralHighlightedNeutral400→Neutral200,borderNeutralDisabledNeutral200→NeutralA50 (translucent wash). Matches Figma. Visible on every neutral-bordered Aurum control — borders ~5 shades lighter than before. - Typography fix —
headingH6.lineHeight14sp → 20sp. Matches Figma'sTitle/XS-Boldspec (verified via plugin API:fontSize 14, lineHeight 20 PIXELS, Inter Bold); fixes collapsed leading on wrap. AurumTransactionListCardrealigned with Figma. Corner radiusshape.lg→shape.xlon both outer wash and inner card (8dp → 16dp; designers updated the spec). Status icons remapped: ErrorStatus.Warning(exclamation) →Navigation.CloseFilled(X-in-circle, matches FigmaIcons/Xat 5311:823); PendingStatus.Pending(clock) →Status.Warning(exclamation-in-circle, matches FigmaIcons/Warningat 5308:802). All glyphs now match the canonical component instances verified viafigma.getNodeByIdAsync().
[0.3.2] - 2026-05-14
Changed
AurumBottomSheetclose button removed. TheonClose: (() -> Unit)?parameter is gone from bothAurumBottomSheetand the privateStrictPageHeader; the top-right X icon is no longer rendered. Figma5564:43216shows the canonicalbottom sheetcomponent (6002:939) with only the drag handle + title + bottom CTA — no close affordance. Dismissal is now exclusively via drag-handle / scrim / system-back. Source-incompatible for any caller that was passingonClose; the sole in-tree consumer (TransactionV2FilterBottomSheetin jar-android) never set it. KDoc updated;Spacer,AurumIconButton,AurumIcon, andAurumIconsimports dropped from the file.AurumBadgePainter overload now ships MCP-readiness KDoc. The Painter-flavoured overload was missing all three required tags (@AurumIntendedUse,@AurumDo,@AurumDont); the published manifest would have surfaced a stub on hover. The full block is mirrored verbatim from the ImageVector overload so both shapes ship identical identity / axes / dos / don'ts.AurumTabRowpreview annotation aligned. The lone@Preview(name = "tablet-wide(640dp)", widthDp = 640)onPreviewTabRowFourTabsTabletis now@AurumPreviewso the catalog preview sweep + screenshot pipeline pick it up alongside every other Aurum preview. The redundantandroidx.compose.ui.tooling.preview.Previewimport is dropped.docs/components/classification.mdrefresh. Table was ~6 months stale at 30 rows; now lists every public composable (29 scratch / 13 wrap). ReclassifiedAurumChip,AurumCheckbox, andAurumNavBarfrom Wrap to Scratch (source confirms none of them importsmaterial3.*); renamedAurumRadio→AurumRadioButtonandAurumBottomNavBar→AurumNavBarto match actual file names; movedAurumTabfrom the Wrap half to the Scratch half. Added rows forAurumLinkButton,AurumOtpInput,AurumAmountInput,AurumStepper,AurumSectionHeader,AurumRadioGroup,AurumCheckboxGroup,AurumGlobalHeader,AurumTransactionListCard,AurumLabel.- Icon slots inside Aurum surfaces now inherit the surface's content color via
LocalContentColor.AurumIcon's defaulttintresolves toLocalContentColor.current.takeOrElse { Aurum.colors.surface.iconDefaultNormal }, so icons in anAurumButtonleading/trailing slot (and any future Aurum surface that providesLocalContentColor) auto-tint to match the label — no more manualtint = Aurum.colors.interactive.textOnPrimaryNormalboilerplate at each call site.AurumButtonnow wraps its contentRowinCompositionLocalProvider(LocalContentColor provides labelColor)so slotted icons follow the button's variant + enabled state. Callers passing an explicittintare unaffected. AurumPreviewSurfacedefaults to no content padding. Previously hardcoded a 16 dp (Aurum.space.s5) inset on every preview, which clipped full-bleed components (locker cards, top app bars, hero gradients) into looking like they had a white margin. New signature acceptscontentPadding: Dp = 0.dp; component previews that want breathing room pass an explicit value (e.g.AurumPreviewSurface(contentPadding = Aurum.space.s5) { … }). Source-incompatible only for callers that were relying on the inset; trailing-lambda usage (AurumPreviewSurface { … }) compiles unchanged.AurumTopAppBarback icon now matches Figma source. The leading back-button glyph defaults toAurumIcons.Navigation.ChevronLeft(Figma node5426:1363, exactly what the canonical Page Header component_set4826:1058renders) instead of the previously hardcodedAurumIcons.Navigation.ArrowLeft. Implementation had drifted from the Figma source; this realigns them. Visible on every existing call-site (catalogNavigationDemo, jar-android transaction-detail hero, etc.) — a one-glyph swap with no API change for callers that took the default.AurumTopAppBar.backIconslot. Added an optionalbackIcon: ImageVector = AurumIcons.Navigation.ChevronLeftparameter so callers can override the leading glyph (e.g.AurumIcons.Navigation.Closeon modal-style surfaces) without losing the 32×40 dp wrapper orinteractive/icon/neutral/normaltint. NewPreviewWithBackIconClosecovers the override path;BackIconButtonmade glyph-agnostic.AurumTopAppBaricon wrappers honour Figma's 32×40 dp bounds.BackIconButtonandActionIconButtonpreviously inflated their wrappers to a 48×48 dp Material minimum-touch-target box that centered the visible 32×40 dp icon inside, which (a) shifted each glyph 8 dp inward of where Figma places it (Icon_wrapper4826:1086 isw-[32px] h-[40px]) and (b) cumulatively pushed the page title 16 dp right of its design position. Both wrappers now collapse to a single 32×40 dp clickable box, matching Figma exactly. Net effect: tighter leading and trailing slots flush with the 16 dp container padding, page title visually anchored at its Figma-spec 60 dp from the screen left edge.- Compose BOM bumped
2026.01.00→2026.04.01. Re-resolvescompose-uifrom1.10.1to1.11.0, fixing a Layout Inspector crash that prevented live component-tree inspection of the catalog app.material3is pinned outside the BOM at1.3.2and is unaffected.
Added
AurumToast+AurumToastHost— toast feedback family (component/feedback/). Mapped to Figmawrapper(6014:2621).AurumToastis a scratch composable: rounded 8 dp container (borderRadius.large) with 1 dpfeedback/border/<tone>/subtleborder,feedback/background/<tone>/subtlewash (Neutral falls back tosurface/background/surface/lowcontrast+surface/border/surface/lowcontrast), per-tone leading status glyph (Selection.CheckFilledfor Neutral / Brand; matchingStatus.<Tone>Filledfor Success / Warning / Info;Navigation.Closefor Error per Figma'sIcons/Xreference at node6107:432), label rendered atBody/M-Medium(Inter 14 / 20, weight 500) tinted withfeedback/text/<tone>/intense, and a trailing closeAurumIconButtonwired throughonDismiss. Six tones (Neutral / Brand / Success / Error / Warning / Info) × two sizes (Smallfixed 48 dp single-line ellipsis ·Largevertical-padded multi-line wrap up to 3 lines) = 12 variants matching the Figma component set.showLeadingIconparameter hides the leading glyph for text-only status. Wraps its label inCompositionLocalProvider(LocalContentColor provides toneColor)so any nested AurumIcon inherits the tone tint without per-call boilerplate. Ships Code Connect mapping (AurumToast.figma.kt) withstateandsizeaxes wired toAurumToastTone/AurumToastSizeenums, MCP-readiness KDoc tags (@AurumIntendedUse+ 3 ×@AurumDo+ 3 ×@AurumDont), and 3@AurumPreviewpreviews (small all-tones · large all-tones ·showLeadingIcon = false).AurumToastHostis the codebase-only orchestration glue (no Figma counterpart): aStableAurumToastHostStatewith aMutex-serialised single-toast slot plus asuspend fun showToast(label, tone, size, duration): AurumToastResultAPI that resumes when the strip is dismissed (timer / X tap / explicitdismiss()).AurumToastDuration.{Short=4s, Long=10s, Indefinite}drives the auto-dismiss timer;rememberAurumToastHostState()is the canonical entry point.AurumToastHostwrapsAnimatedVisibilitywith a 220 ms slide-up + fade enter and 180 ms slide-down + fade exit, preservinglastVisibleacross the exit animation so the strip keeps rendering while it slides out. Defaulttoastslot renders anAurumToastwithfillMaxWidth+ 16 dp horizontal padding; callers can override for custom width / placement. CatalogToastDemoextended with a live host section: 6 trigger buttons (one per tone) + a "Queue 3 in a row" button proving the FIFO mutex queue.AurumGlobalHeader— persistent top bar for top-level destinations (component/navigation/). Mapped to FigmaGlobal Header(5252:2274). SealedAurumGlobalHeaderRightContentwith two variants:Default(optional Support pill + optional Rewards/Notifications pill) andLivePrice(live gold-buy-price pill on a dark surface + optional Rewards/Notifications pill). Each pill is 44 dp tall, 22 dp corner radius, 1 dpinteractive/border/neutral/mutedborder, with a subtleaurumRadialBrushsheen overlay matching Figma's SVG-encoded radial fill. Profile pill accepts either anImageVectorglyph (defaultAurumIcons.User.User) or a caller-suppliedprofileContentslot — the slot pattern lets consumers render URL-loaded avatars (Glide / Coil) without dragging an image-loading dep into Aurum. Ships Code Connect mapping (AurumGlobalHeader.figma.kt), MCP-readiness KDoc tags (@AurumIntendedUse+ 3 ×@AurumDo+ 3 ×@AurumDont), and 6@AurumPreviewpreviews covering all variant combinations. CatalogNavigationDemoextended with three live examples.AurumTab+AurumTabRow— tab navigation family (component/navigation/). Mapped to Figma_Tabs(5430:3115) andGroupRoot(5531:795).AurumTabis a scratch composable (FoundationBox+Row+selectable,role = Role.Tab) with an optional leadingImageVectoricon atAurum.iconSize.xl(24 dp) and a label rendered atTitle/XS-Bold(14/20 sp, Bold 700) withTextOverflow.Clip. Selected usesinteractive/text/primary/normal+interactive/icon/primary/normal; unselected usesinteractive/text/neutral/subtle+interactive/icon/neutral/subtle. No disabled variant — Figma's_Tabsset has none; callers omit unavailable destinations.AurumTabRowuses aSubcomposeLayoutprobe pass to measure each tab's natural width, then auto-fits or scrolls: whentabCount × max(widestNatural, 100.dp) ≤ viewportit wrapsmaterial3.PrimaryTabRowand tabs flex to share the row equally (matching Figma's two/three-tabflex-[1_0_0]variants); otherwise it wrapsmaterial3.PrimaryScrollableTabRowand pins each tab to the computed width viaLocalAurumTabWidth(matching Figma's four-tab fixed-100px+scroll variant and gracefully extending to 5 + tabs). Indicator isborderWidth/lg(2 dp)interactive/border/primary/default; bottom divider isborderWidth/sm(1 dp)interactive/border/neutral/highlighted. Both ship Code Connect mappings (AurumTab.figma.kt,AurumTabRow.figma.kt) and 10@AurumPreviewpreviews including a 640 dp tablet tile and a 5-tab scroll demo. CatalogTabGalleryadded under Navigation with two/three/four/with-icons sections.
Manifest
- Manifest jumps from 28 → 33 components:
AurumToast,AurumToastHost,AurumGlobalHeader,AurumTab,AurumTabRow(5 new).AurumBottomSheetwas already in the manifest — this cycle ships its first Code Connect mapping plus the close-button removal. Code Connect mappings ~158 → 178: 5 new component mappings (AurumToast,AurumGlobalHeader,AurumTab,AurumTabRow,AurumBottomSheet) plus 18 new icon mappings (9 pairs:ArrowDownLeft,ArrowUpRight,ChatBubble,Filter,Nek,Phone,Replay,Timer,WhatsApp× line + filled). The 7 drift-fix mappings from PR #22 updated existing files, not new ones. Schema version unchanged ("2"); changes are additive.
[0.3.0] - 2026-05-04
Added
AurumCheckbox+AurumCheckboxGroup— multi-select selection family (component/selection/).AurumCheckboxis a tri-state control (AurumCheckState.Unchecked / Checked / Indeterminate) mapped to Figma5169:1314. Closed enum chosen overBoolean?to avoidnull-as-indeterminate ambiguity. MirrorsAurumRadioButton's API:selected,onCheckStateChange,label,subtext,enabled,error,labelPosition(End/Start). The 24 dp box is rendered viaCanvas— checked state fills withAurum.colors.interactive.bgPrimaryDefaultand overlays a stroked checkmark; indeterminate fills the box and overlays a centred horizontal bar; error tints both outline and glyph withfeedback-negative.AurumCheckboxGroup<T>mirrorsAurumRadioGroup<T>but withselected: ImmutableSet<T>andonSelectionChange: (T, Boolean) -> Unit; usestriStateToggleableper row soIndeterminate → Checkedadvancement is a single tap. Both ship Code Connect mappings (AurumCheckbox.figma.ktat5169:1314,AurumCheckboxGroup.figma.ktat5169:1796) plus 8 + 5@AurumPreviewpreviews. CatalogSelectionDemoextended with single-checkbox and group examples.AurumAmountInput— currency-prefixed numeric input mapped to Figma5080:261(component/field/AurumAmountInput.kt). Delegates toAurumTextFieldfor state, validation, helper/error/success text, label plumbing — currency symbol (default₹) is rendered in the leading slot usingAurum.type.headingLarge; optionalsuffixText(e.g. "0.0097 g") sits in the trailing slot.loading = trueswaps the trailing slot for an inlineAurumLoader(size = Aurum.iconSize.lg)and forces read-only. Caller is responsible for formatting bothvalueandsuffixText(locale + currency conventions are app-level concerns) — flagged in KDoc. Numeric keyboard viaKeyboardOptions(keyboardType = KeyboardType.Number). 8@AurumPreviewpreviews + Code Connect.AurumNavBar+AurumNavBarItem— bottom navigation family (component/navigation/). Mapped to the layout component_set at Figma5575:14226.AurumNavBaris a slot-based composable taking anImmutableList<AurumNavBarItem>(label + line/fill icon pair) plusselectedIndex,onSelect, and alayout: AurumNavBarLayout.AurumNavBarLayoutis asealed interfaceexposing four data variants —Standard3,Standard4,Standard5,CenterQr5(onQrClick)— each carrying anitemCountenforced viarequire()at composition time.CenterQr5takes 4 items (the QR action is rendered by the layout, not surfaced as an item) and inserts the raised QR FAB between items 1 and 2 usingAurumIcons.Action.QrCode. The per-cell rendererAurumNavBarCellisprivate— exposing it would only invite cells without a parent bar. 6@AurumPreviewpreviews (one per layout + selected-state variants) + Code Connect. CatalogNavigationDemoextended with all 4 layouts running interactiveselectedIndexstate.AurumTransactionListCard— opens the Cards family (component/card/, new package). Mapped to Figma5576:19749. Status-tinted card (AurumTransactionStatus.{Success, Error, Pending}) composingAurumSurface+AurumText+AurumIcon. Outer wash usesAurum.colors.feedback.{positive, negative, notice}/subtle; status badge icons map to the newAurumIcons.Status.{Success, Warning, Pending}glyphs landed in v0.2.1; amount and helper-text colours match the wash family. Caller hands in pre-formatted strings fordateTextandamount— no locale or currency handling inside (consistent withAurumAmountInput).helperTextandleadingIconare optional. 7@AurumPreviewpreviews + Code Connect. StandaloneCardDemocomposable wired into the catalog showcase as a new "Cards" section between Navigation and Chips.
Changed
tooling/gallery/generate.py— registered thecardfamily inFAMILY_LABELSso the gallery site renders the newcomponent/card/family with a proper "Cards" heading rather than falling back to the raw directory name.AurumLinkButtonCode Connect mapping validated against Figma4784:1286("Component 1") — the existingAurumLinkButton.figma.ktalready targets the right node, no changes needed. The Figma component name is misleading ("Component 1") but the underlyingvariant=link buttonaxis maps cleanly.
Manifest
- Manifest jumps from 24 → 28 components:
AurumAmountInput,AurumCheckbox,AurumCheckboxGroup,AurumNavBar,AurumTransactionListCard(5 new) —AurumNavBarItemis a public data class but not a composable, so it doesn't count. Code Connect mappings 150 → ~158. Schema version unchanged ("2"); changes are additive.
Known gaps
Icons/NEK(Figma5566:781) is referenced by Jar's nav bar item set but not yet imported intoAurumIcons. Catalog NavBar previews use placeholder icons (Home,Gift,Document, etc.) so compile + render succeed. Action: design to confirm the canonical NEK glyph node, then add anIconEntrytotooling/icons/import_from_figma.py:ICON_MANIFESTand re-runmake icons-import.Icons/Checkstill resolves to a single-weight glyph (5308:800);Icons/Checkat5480:5047remains an empty/orphaned component in Figma (see v0.2.1 ghost-component note inadd-an-icon.md). No action.
[0.2.1] - 2026-05-04
Added
- 11 new Figma-derived icons imported via
tooling/icons/import_from_figma.py. Sourced authoritatively from the Jar Light Design System file (YvIxqu2oTlM6UnkL0OloHc) by enumerating everyIcons/*master component via the Figma REST/v1/files/{key}/componentsendpoint and diffing againstICON_MANIFEST. Each ships a 24×24 vector drawable + AurumIcons accessor (line + filled) + per-weight Code Connect mapping. Breakdown:AurumIcons.Action.{Minus, MoreHorizontal},AurumIcons.Content.Image,AurumIcons.Status.{Pending, Warning, Success, Loader},AurumIcons.Commerce.Withdraw. Single-weight icons (Success,Loader,Selection.Check) reuse the same Figma node id for both weights, producing identical line/fill XMLs while keeping the<Name>+<Name>FilledAPI contract intact.
Changed
AurumIcons.Action.AddandAurumIcons.Action.Overflownow Figma-derived. Previously hand-drawnaurum_ic_action_add.xmlandaurum_ic_action_overflow.xmlare replaced with imports from Figma'sIcons/Plus(5322:1592/5322:1593) andIcons/DotsThreeVertical(5431:2848/5431:2850). Public Kotlin API names unchanged — call sites inAurumButton,AurumIconButton,AurumTextField, andAurumTopAppBarneed no edits. TheirFilledaccessors (AddFilled,OverflowFilled) are now also available.AurumIcons.Selection.Checknow Figma-derived. Hand-drawnaurum_ic_selection_check.xmlreplaced with import from Figma'sIcons/Check(5308:800). Used byAurumSwitchfor the on-state tick. Initial discovery missed this node because the file's components index points at a stale duplicate (5480:5047) that's an empty/orphaned component;5308:800lives near the Warning glyphs and renders fine. Aurum now has zero hand-drawn icons — every icon flows from Figma throughmake icons-import.Icons/X(Close) fill node updated from5162:954→5311:823. Design moved the X fill variant; the old node returns null from/v1/images. Visual unchanged.tooling/icons/import_from_figma.pycleanup. Removed the special-case blocks at the end ofgenerate_aurum_icons_ktthat hand-wiredAction.Add,Action.Overflow, andSelection.Checkfrom legacy XMLs — all three are now regularIconEntryrows. AddedselectiontoCATEGORY_ORDER+CATEGORY_DOCSTRINGS. Removedaurum_ic_selection_check.xmlfrom the obsolete-detection exception set.aurum-catalog/.../IconGallery.ktextended with the 11 new icons (Action, Content, Status, Commerce sections) plus a new Selection section showingCheck.
Tooling
- Documented icon ghosts in
aurum/docs/workflows/add-an-icon.md. FiveIcons/*names appear in the file's/componentsindex but are deleted/orphaned components in Figma — opening their URLs prompts a "Restore component" dialog and/v1/imagesreturns null. They are NOT placeholders awaiting drawings:Icons/InstantSave(5343:1795/1796),Icons/DailySavings(5343:1779/1780),Icons/WeeklySavings(5343:1781/1782),Icons/MonthlySavings(5343:1783/1784), olderIcons/Withdrawon5343:*(superseded by the live pair at5358:456/5358:465which is imported asCommerce.Withdraw). The doc explicitly tells future contributors to skip them rather than chase a "fix it in Figma" thread.
Manifest
- Manifest jumps from 60 → 68 icons. Code Connect mappings 130 → 150. Components count unchanged (24).
- Schema version unchanged (
"2"); changes are additive on the existing icon list.
[0.2.0] - 2026-05-04
Tooling
- MCP manifest schema v2 — enrichment fields for
aurum-mcpv0.3. Bumpedtooling/manifest/schema.jsonschemaVersionenum from["1"]to["1","2"]and added four optional, additive fields: component.intendedUse: string— when-to-reach-for prose authored in a new@AurumIntendedUseKDoc tag.component.usage: { do: string[]; dont: string[] }— guardrails authored in@AurumDo/@AurumDontKDoc tags (one bullet per tag instance).component.relatedTokens: string[]— qualified Aurum token names (surface.bgPageBase,spacing.s12,typography.bodyMedium) the component references in its source. Static-analyzed byanalyze_token_refs(source)againstAurum.{colors,space,type,radius,borderWidth,elevation,iconSize}.<leaf>accessors.icon.tags: string[]— hand-curated synonyms (Delete→[trash, remove, bin, garbage, discard]) sourced from a newaurum/icons/tags.tomlfile. Powers the synonym-awareaurum_search_iconstool.
All four are absent from v1 manifests and ignored gracefully by older readers. The generator emits schemaVersion: "2" whenever any of them are populated, otherwise stays on "1".
@AurumIntendedUse/@AurumDo/@AurumDontKDoc tags authored on all 24 components. Every component in the manifest now carries intended-use prose + Do/Don't guardrails. Counts: 24 ×intendedUse, 70 totaldoentries, 70 totaldontentries. The 6 priority components (Chip, Button, RadioButton, RadioGroup, TopAppBar, OtpInput) landed first; this extends coverage to AurumIconButton, AurumLinkButton, AurumTextField, AurumPhoneNumberInput, AurumSearchField, AurumSwitch, AurumBadge, AurumLoader, AurumSkeleton, AurumSectionHeader, AurumSurface, AurumScreen, AurumSnackbar, AurumStepper, AurumDivider, AurumIcon, AurumText, AurumLabel. Tags are stripped from the rendered KDoc body and re-emitted as structured manifest fields.- Cross-repo dispatch wired up. Committed
.github/workflows/notify-mcp.yml, which fires arepository_dispatch: aurum-content-changedevent atChangejarapp/aurum-mcpon every push tomainand every release. Drops the manifest-sync latency in aurum-mcp from ≤24 h (cron) to ~1 min. Requires theMCP_DISPATCH_PATorg secret (a fine-grained PAT scoped to aurum-mcp with Actions: read+write). - README — manifest pipeline section. Documents how component changes propagate to
aurum-mcpend-to-end: pages.yml → manifest URL → notify-mcp dispatch → sync-manifest auto-PR → human merge + release dispatch. Includes the@AurumIntendedUse/@AurumDo/@AurumDontauthoring convention and theaurum/icons/tags.tomlsynonym format with quality-bar guidance. aurum/icons/tags.toml— curated synonyms for all 60 icons across 9 categories (Action / Commerce / Content / Media / Navigation / Selection / Status / System / User). 222 tags total. Format is TOML keyed by category → icon name → tag list.- Pages workflow now publishes the manifest.
.github/workflows/pages.ymlinvokesgenerate.py --emit-manifest build/gallery/data/manifest.json --also-build-gallery --validateon every deploy, exposinghttps://changejarapp.github.io/aurum-android/data/manifest.json(previously 404). Closes the cross-repo sync gap that leftaurum-mcp's drift-check soft-failing on every PR. - MCP manifest pipeline. Added
tooling/manifest/schema.jsondefining a JSON Schema for an LLM-consumable Aurum manifest, and extendedtooling/gallery/generate.pywith--emit-manifest <path>and--validateflags. The same parsers that drive the static gallery now also emit a structured JSON describing every component (KDoc + signature + params + Figma deeplink + Code Connect path + gallery URL), every token (semantic colour / visual palette / spacing / radius / border-width / icon-size / elevation / typography), every icon (with paired line/fill Figma node IDs), every Code Connect mapping, and the full Keep-a-Changelog history. Single source of truth, two render targets — HTML for humans, JSON for agents. Consumed by the newatri-jar/aurum-mcp(and laterChangejarapp/aurum-mcp) MCP server. Manifest carries aplatforms[]field on each component for forward-compatible cross-platform support (aurum-iosplugs in as a sibling manifest source without restructuring).
[0.1.5] - 2026-04-28
Fixed
- All 114 icons re-rendered to match Figma. The previous import pipeline used Figma MCP asset URLs that returned only the inner SVG path with
viewBoxset to the path's tight bounding box (e.g.7.5 × 13.5for ChevronRight). Combined withwidth/height = 24dp, this caused non-uniform stretch and stripped the surrounding 24×24 frame padding — the chevron rendered fat and squashed, every other non-square icon was distorted, and even square-bbox icons lost their intended 2-3 dp inset. - Stroke-only icons no longer get a fill. Phosphor regular-weight SVGs carry
fill="none"at the<svg>root, cascading to children. The previous import didn't honour the cascade and emitted bothfillColorandstrokeColor— so e.g.Homerendered as a solid black house instead of the intended outline.
Changed
- Icon import pipeline rewritten to fetch via the Figma REST API (
/v1/images?…&format=svg) using$FIGMA_ACCESS_TOKEN. REST exports include the 24×24 frame and proper SVG-level fill cascade, so the conversion is a clean 1:1 to Vector Drawable. The per-iconCOMPOUND_TRANSLATESworkaround (previously hand-coded for SpeakerSimpleX) is no longer needed and was removed. The stalefigma-icon-urls.jsonURL manifest was deleted.
Added
/icons.htmlpage on the gallery website — every icon's line + fill weights side by side, grouped by category, with live search and click-to-copy onAurumIcons.<Category>.<Symbol>. ReadsAurumIcons.ktand inlines each Vector Drawable ascurrentColorSVG so icons follow the page theme. No longer need to install the catalog APK to scan the icon set.
[0.1.4] - 2026-04-28
Changed
AurumChiprealigned with the Figma "Action" chip component (YvIxqu2oTlM6UnkL0OloHc, node4446-701). Addssize(AurumChipSize.Large/Small) andleadingIconparameters; height tightened to 38 dp Large / 30 dp Small (from 40 dp); padding now asymmetric (12 dp text-side, 8 dp icon-side); inter-element gap reduced 8 → 4 dp; text style varies by size (titleT2/bodySmall). Existing call sites are unaffected — new parameters default to the prior behaviour. Previews regrouped into Large-trailing / Large-leading / Large-both / Large-text-only / Small / Disabled.- Code Connect for
AurumChippicks up the newSizeaxis (large↔Large,small↔Small).
[0.1.3] - 2026-04-27
Added
- Compose perf guardrails. Detekt +
mrmans0n/compose-ruleswired in, with the perf/stability rules active (UnstableCollections,MutableStateAutoboxing,MutableParams,MutableStateParam,LambdaParameterInRestartableEffect,Material2). Compose Compiler Metrics enabled on:aurumand:aurum-catalog(build/compose_compiler/). - Compose stability CI gate. New
verifyComposeStabilityGradle task in:aurumfails the build whenaurum_release-classes.txtreports more inferred-unstable classes thancomposeStabilityThreshold(currently0). Wired intocheck.ymlafter detekt. - Compose metrics dashboard deployed alongside the gallery at changejarapp.github.io/aurum-android/metrics/, rendered from
build/compose_compiler/viaPatilShreyas/compose-report-to-html. Per-PRcompose-metricsartifact uploaded bycheck.yml. - Aurum icon set — 57 icons × 2 weights = 114 vector drawables imported from the Figma "Component Icons" frame, exposed under
AurumIcons.<Category>.<Name>(and<Name>Filledfor the fill variant). 8 categories:Navigation,Action,Content,Media,Commerce,System,Status,User. Ingested by the newtooling/icons/import_from_figma.pyscript (make icons-import); idempotent re-runs. IconGalleryscreen in the catalog showing every icon × weight, grouped by category.- 114 Code Connect mappings for the new icons under
aurum/src/main/kotlin/com/jar/app/aurum/component/icon/figma_connect/AurumIcon*.figma.kt. Auto-published to Figma via thefigma-code-connect.ymlworkflow.
Changed
- 6 overlapping icons replaced from the Figma source-of-truth:
Navigation.Back→ArrowLeft,Navigation.ChevronForward→ChevronRight,Media.Like→Content.Heart(renames; 12 call-site migrations acrossAurumTopAppBar,AurumChip,AurumSectionHeader,AurumLinkButton, and the catalog gallery).Navigation.Close,Action.Edit,Action.Searchkept their names — only their underlying XML content was replaced. - 5 components marked codebase-only:
AurumSearchField,AurumIconButton,AurumDivider,AurumLoader,AurumSkeleton— verified absent from the Figma library via MCP search. File-level marker added so future Code-Connect audits don't keep flagging them. AurumIcons.ktregenerated from the import script. The 3 legacy entries that lack a Figma counterpart (Action.Add,Action.Overflow,Selection.Check) remain hand-authored underres/drawable/and are flagged in-file pending design escalation.record.ymlnow also dispatchespages.ymlafter committing fresh baselines onmain, so the gallery's snapshot embeds redeploy without a manual trigger.
Fixed
AurumOtpInput: keyedLaunchedEffecton the completion-boundary transition (value.length == maxLength) instead ofvalueitself, so the coroutine no longer relaunches on every keystroke.AurumSkeleton: moved theshimmerProgressstate read out of thedrawWithCachecache block and intoonDrawBehind, so the cache is no longer invalidated on every animation frame. The gradientcolorslist is nowremember-ed.AurumText:inlineContentparameter typed asImmutableMap<…>instead ofMap<…>, restoring skippability (caught by the new compose-rulesUnstableCollectionsrule).- CI Java mismatch:
compose-report-to-htmlv1.5.0 JAR is built against Java 21;check.ymlandpages.ymlnow install JDK 21 alongside JDK 17 and invoke the JAR via$JAVA_HOME_21_X64/bin/java.
Tooling
- New Makefile targets:
make lint-compose,make compose-metrics,make compose-metrics-html,make icons-import,make icons-brand(rename of the priormake iconsfor clarity vs the new icon-set sync). - New tooling scripts:
tooling/icons/import_from_figma.py(Figma SVG → Vector Drawable + AurumIcons.kt + Code Connect codegen) andtooling/gallery/render_metrics_index.py(gallery/metrics/landing page).
[0.1.2] - 2026-04-23
Added
- Screenshot testing via Roborazzi + ComposablePreviewScanner. 334 baseline
PNGs committed under aurum/src/test/snapshots/ (Git LFS-tracked) covering
every @Preview and every tile of the @AurumPreview 6-device fan-out.
Any visual regression fails CI before merge. Tasks: recordRoborazziDebug
(refresh baselines), verifyRoborazziDebug (CI check), compareRoborazziDebug
(diff without failing).
.github/workflows/check.yml— PR + main-push workflow running library +
catalog build, lint, and snapshot verification. Diff PNGs uploaded as a
workflow artifact on any screenshot drift so design reviewers can eyeball
the exact delta.
- Git LFS (
.gitattributes) trackingaurum/src/test/snapshots/**/*.png
— keeps pack files small, surfaces binary diffs in PR UIs.
[0.1.1] - 2026-04-23
Changed
- Maven coordinate realigned with Jar's library convention.
- Before:
com.jarapp:aurum:<ver> - After:
com.jar.internal.library.aurum-android:core:<ver> - Kotlin import package inside the AAR stays
com.jar.app.aurum.*— no source rename. - This lets consumers resolve Aurum via the existing
Changejarapp/*wildcard
Maven repo in jar-android/settings.gradle.kts, identical to how
com.jar.internal.library.core-network:shared and siblings are resolved.
- The previous
com.jarapp:aurum:0.1.0artifact is stale and should not be
consumed — it's kept in GitHub Packages only to avoid the "published once,
cannot re-publish the same coord" rule.
Removed
AurumElevation.toast+ElevationTintColors.toast+AurumLightElevation.toastentry +AurumLightColors.elevationTint.toastvalue — Figma ships only a tint forelevation/_toast(no dedicated dims) and the fallback shape matchedlowRaised, so the Kotlin surface added API surface without semantic value. Snackbars/toasts now useAurum.elevation.lowRaiseddirectly. The plugin mapping (figma-plugin-aurum-sync) marks_toastas an explicitly skipped elevation token and bumps to0.1.1.
Added
AurumColors.visual— new decorative palette subgroup exposing 77 chromatic tokens (blue/green/orange/pink/purple/red/yellow × shades 50…1000). Mirrors Figma'svisual_colorscollection 1:1 and sources values fromAurumPaletteprimitives. Feature code usesAurum.colors.visual.<family><shade>for palette-keyed decorative colours that have no semantic meaning. RawAurumPalettestaysinternal.AurumPhoneNumberInput— phone-number variant ofAurumTextFieldwith country-code prefix slot, optional flag composable, digit-only input filter,KeyboardType.Phone, and a default 10-digit max length. Mirrors the Figma "Phone Number Input" component set.AurumTextField.figma.kt— Code Connect stub against Figma4623:373mappingstate,validationState,multi_line,label,showHelpTexttoAurumTextFieldAPI props.AurumPhoneNumberInput.figma.kt— Code Connect stub against Figma4904:2455mappingstate,validationState,hasValue,label,showHelpText.AurumOtpValidationState.Timer— fourth validation state for resend-countdown UX. Renders identically toNonebut provides a semantic channel matching the FigmavalidationState=timervariant.Modifier.aurumHardShadow(color, offsetY, shape)— solid-colour offset drop shadow for skeuomorphic "stacked card" effects (matches Figma'sshadow(0, Ypx, 0, 0, color)spec). Encapsulates the double-box idiom into a single modifier that expands layout byoffsetYand paints the shape outline behind content.
Fixed
AurumOtpInputdisabled digits now usesurface.textDefaultDisabled(matching Figmatext/default/disabled) instead oftextDefaultNormalat 10% alpha.AurumTopAppBarsynced to Figma4826:1057Page Header: title uses SemiBold (was Medium); subtitle useslabelL2Medium 12/16 intextDefaultNormal(wasbodyB3Normal intextDefaultSubtle); primary button uses SemiBold label and natural 36 dp height from 8 dp padding (was fixed 32 dp, Medium); back + action icons tint viainteractive.iconNeutralNormal(wassurface.textDefaultNormal— same hex, correct token). Docstring fix: icon wrapper is 32 × 40 dp (w × h), not 40 × 32.AurumBadgesynced to Figma4240:10843: both emphases now render atLabel/L-Medium(12/16 Inter Medium) — previously had a 18 sp line-height and Intense emphasis rendered Normal weight. Emphasis-specific text styles collapsed to a single shared style.AurumSectionHeadersynced to Figma3702:162168: title, link label, and text-action label render SemiBold (Title/S-SemiBold/Title/XS-SemiBold); icon-action tint usesinteractive.iconNeutralNormal(wassurface.iconDefaultNormal— same hex, correct semantic).AurumSwitchsynced to Figma4018:557: thumb now usesinteractive.bgNeutralInverse(wassurface.bgPageBase— same hex, correct semantic); checked icon usesinteractive.iconPrimaryNormal(wasbgPrimaryDefault); disabled-checked icon usesinteractive.iconNeutralDisabled(wasbgNeutralDisabled— real hex drift fixed).AurumSteppersynced to Figma3834:139631: numeric value and ± symbols render Bold (Num/XS); Neutral and Brand state colours moved to theinteractive.*token family; disabled-state bg/border/icon hexes corrected (#6C849D17/#C3C7D1were previously rendering as#ECEEF3/#848A99).AurumLabelsynced to Figma3774:137816: all variants render Medium weight (was SemiBold);Strongvariant now useslabelL2size (waslabelL1) andfeedback.textPrimaryIntensecolour (wassurface.textDefaultNormal).AurumButtonsynced to Figma4692:1074: primary-disabled text token changed totextPrimaryDisabled(wastextOnPrimaryDisabled); secondary variant border usesborderPrimaryDefaultwhen enabled andborderNeutralMutedwhen disabled (wasborderNeutralDefault/borderNeutralDisabled).
[0.2.0] - 2026-04-16
Added
- Figma Code Connect infrastructure: Gradle plugin, CLI,
*.figma.ktpattern AurumIconsnamespace with 8 XML Vector Drawables from Figma exportsAurumLinkButton— new component from Figma Button pageAurumBadge— 6 colors × 2 emphases × 2 sizes from FigmaAurumOtpInput— digit-by-digit OTP from Figma specAurumStepper— numeric +/− from Figma specAurumLabel— styled text label from Figma specAurumSectionHeader— section divider from Figma specAurumSwitch— toggle from Figma specversion.propertiesfor semver tracking
Changed
- AurumButton rebuilt from Figma spec: 3 variants (removed Ghost/Destructive), corrected heights (40/48/56dp), added
isFullWidth+isLoading, 12dp corner radius - AurumTypography restructured to match Figma type scale: 14 scale composites (Display/Heading/Body/Caption) + 6 component-level styles
- AurumTextField audited: added success state, readonly treatment, character counter, fixed error token layer
- All Material Icons replaced with
AurumIcons.*(XML Vector Drawables loaded viaImageVector.vectorResource()) - Button size enum renamed
Sm/Md/Lg→Small/Medium/Large - Button style enum renamed
AurumButtonStyle→AurumButtonVariant
Fixed
- Secondary button was filled grey — now transparent bg + outline border per Figma
- Typography composites were engineering assumptions — now 14 match actual Figma scale
- Hand-drawn
ImageVector.Builderpaths replaced with proper XML drawables
[0.1.0] - 2026-04-16
Added
- Initial Aurum module scaffold (
:core-designsystem+:core-designsystem-catalog) - 196 semantic colour tokens from Figma export (6 sub-structs)
- Spacing, radius, border-width, icon-size, elevation, motion, opacity tokens
AurumThemecomposable withMaterialBridge(hybrid M3 architecture)- Foundation primitives:
AurumText,AurumIcon,AurumSurface,AurumDivider - Interactive primitives:
AurumButton,AurumIconButton,AurumTextField,AurumSearchField - Navigation:
AurumTopAppBar(10 Figma variants) - Feedback:
AurumLoader,AurumSkeleton - Preview infrastructure:
@AurumPreview,AurumPreviewSurface Modifier.aurumShadow()for elevation rendering- CLAUDE.md module guide + 30 documentation files
- Catalog app with 6 foundation gallery screens