Skip to content

feat(ios): add the button-ios visual recipe and alias button to it - #1588

Merged
GarthDB merged 1 commit into
mainfrom
feat/ios-button-recipe
Nov 1, 2026
Merged

GarthDB merged 1 commit into
mainfrom
feat/ios-button-recipe

Conversation

@GarthDB

@GarthDB GarthDB commented Nov 1, 2026

Copy link
Copy Markdown
Member

Known difference from Figma

Proposal 014 acceptance 3 is not met: the rendered height for size m is 32, and Figma has 39 (node 3956:67377). The renderer does not draw paddingBlockStart or paddingBlockEnd, so the container height is the renderer default (32) for s, m and l. This PR ships with the mismatch: no literal height and no renderer change. The recipe keeps the v-padding bindings (5, 8, 16) so they take effect once the renderer draws block padding. Tracked in p6ga.8.58, which blocks p6ga.8.40; that bead stays open until the height matches or acceptance 3 is amended on purpose. No foundation or other platform recipe binds block padding, so drawing it later will not change foundation snapshots. The mismatch is visible in the images: at size l the 28 radius on a 32 high container draws as an oval.

Description

Adds the platform-owned iOS Button recipe and points button at it for the ios platform (slice 1 of p6ga.8.6, PR 3 of the platform-recipes series after #1585, #1586 and #1587). All changes are under platforms/ios plus tests; no published package is touched.

  • platforms/ios/extensions/visuals/button-ios.json: the recipe. {size} binds padding, gap and corner radius. {style} binds one fill entry each for default, hover, down and disabled, and one label color entry plus a disabled one. Down binds the real down tokens from feat(ios): add button-ios component and stopgap button tokens #1587. The label is hidden through visibleWhen on isLabelHidden. No focus entry (Figma has no focus variant).
  • platforms/ios/manifest.json: componentAliases: { "button": "button-ios" }. It ships with the recipe because an alias without one would break render button --platform ios.
  • platforms/ios/extensions/implementations/button-ios.json: one row, ios / SPButton / spectrum-ios.
  • Tests: the platform-recipes e2e test and cli_platform.rs (below).
  • docs/proposals/014-platform-owned-visual-recipes.md: the recorded recipe line counts.

Recipe size. button-ios.json is 121 lines with Accent only, 121 with Accent and Primary, and 121 for the eight-style projection. A style adds zero recipe lines when its tokens follow the {style} pattern. I checked this by adding a throwaway negative style (one option value and its tokens, recipe file untouched) in a scratch copy and rendering it. The explicit per-style sketch in the proposal would have cost 144, 197 and 250 lines for one, two and three styles.

Left out, on purpose.

  • Label font and icon size: the renderer draws the label with its default size and no warning. Decision 8.7 allows a literal with a stated reason, but this slice is colors and layout, so I left both out rather than invent values. Tracked in p6ga.8.57.
  • Primary stays Figma-only (Swift has no Primary style) until p6ga.8.53 gets an answer from the iOS team.
  • documentationUrl is optional (p6ga.8.56) and not part of this PR.

Two corrections to the proposal sketch. Disabled is selected with options.isDisabled: true, because a recipe states condition matches only the request's interaction states (hover, down). Down binds the down tokens, not the hover token.

Related Issue

Beads p6ga.8.40, under epic p6ga.8 (platform-aware rendering). Follows #1585, #1586 and #1587; proposal 014.

Motivation and Context

render button --platform ios should draw the iOS Button, not the foundation recipe. With the recipe, the alias and the implementation row, the iOS platform manifest now owns one component end to end, and the template-based recipe stays the same size as styles are added.

How Has This Been Tested?

  • 48 scenes (Accent and Primary x default, hover, down, disabled x light and dark x s, m, l): fill, label color, horizontal padding, gap and radius match Figma, with no differences. Accent resolves through the foundation tokens: fill #3b63fb and #4069fd (default), #274dea and #345bf8 (hover and down), label white. Disabled is rgba(0,0,0,0.03) and rgba(255,255,255,0.07) with label rgba(0,0,0,0.22) and rgba(255,255,255,0.28). The one difference is height (see "Known difference from Figma").
  • Desktop and mobile scale scenes are identical for all 48 scenes, so the Layout tokens (no scale key) resolve under both.
  • The recipe guard (SPEC-079) reports every binding resolves for ios. validate --platform ios with the guard's arguments exits 0 on main and on the branch with the same 1,328 warnings and no new diagnostic.
  • Without --platform ios, catalog export and the foundation renders of every recipe are byte-identical to main, and with --platform ios only button changes (plus its site entry and the button-ios catalog row). recipe_snapshots, goldens and the legacy output are unchanged.
  • platform-recipes.e2e: renamed the first test to "ios as shipped passes with its button-ios recipe" and moved tests 2 and 3 to the foundation badge recipe, since button no longer resolves to the foundation file under ios. They still prove a replacement is reported as SPEC-080 and an unresolvable binding fails the guard.
  • cli_platform.rs: new ios_render_button_draws_button_ios_and_foundation_is_unchanged (distinct size, radius and Primary fill from the foundation button; same scene as render button-ios; plain render button is the foundation). The existing no-warning check for render button --platform ios still passes.
  • Run: cargo fmt --check, cargo clippy --all-targets -- -D warnings, moon run sdk:test sdk-wasm:test design-data:validate design-data:validate-dataset tokens:verifyLegacyOutput root:validate-platform-recipes root:test-platform-recipes-guard root:test-platform-recipes-e2e --force, the changeset linter with --fail-on-warnings, check-ci-coverage and ai:check, all passing. pnpm-lock.yaml is unchanged.
  • docs/proposals/014-platform-owned-visual-recipes.md already fails Prettier on main (table alignment); I left that formatting alone and the paragraph I added is Prettier-clean.
  • Not covered: the WASM applyPlatform path with the real iOS manifest. The embedded dataset carries no manifests, and the existing WASM test already covers the alias with a fixture.

Screenshots (if appropriate):

Rendered with design-data render button --platform ios (sizes s, m, l; default, hover, disabled; Accent and Primary), converted to PNG with headless Chrome:

  • /private/var/folders/lv/cnbsxznj0z3c_3r74g6xr0h40000gq/T/opencode/shots840/button-ios-light.png
  • /private/var/folders/lv/cnbsxznj0z3c_3r74g6xr0h40000gq/T/opencode/shots840/button-ios-dark.png

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have signed the Adobe Open Source CLA.
  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

Binds padding, gap, radius, fill and label color through {size} and {style}
templating. Adds the SPButton implementation row and aliases button to
button-ios so render button --platform ios draws it.
@changeset-bot

changeset-bot Bot commented Nov 1, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: fce755d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

🎨 Token Changes Report

Tokens Changed (0)

Original Branch: main


This comment was automatically generated by the token diff tool. 🤖

@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

🧩 Component Schema Changes Report

No component schema changes detected.

This comment was automatically generated by the component schema diff tool. 🤖

@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Run report for fce755dd

Total time: 8m 58s | Comparison time: 22m 58s | Estimated savings: 14m (61.0% faster)

Action Time Status Info
⬛️ SetupProto(0.57.4) 0ms Skipped
🟩 SyncWorkspace 9.9ms Passed
🟩 SyncProject(sdk) 3.5ms Passed
🟩 SyncProject(design-data-spec) 4.4ms Passed
🟩 SyncProject(sdk-wasm) 0.8ms Passed
🟩 SyncProject(root) 0.7ms Passed
🟩 SyncProject(design-data) 1ms Passed
🟩 SyncProject(design-data-glue) 0.6ms Passed
🟩 SyncProject(design-data-mcp) 0.8ms Passed
⬛️ SetupToolchain(node:20.17.0) 508ms Skipped
⬛️ SetupToolchain(rust:1.88.0) 945.4ms Skipped
🟩 SetupEnvironment(rust, sdk) 95.9ms Passed
⬛️ InstallDependencies(rust, sdk) 2.4ms Skipped
⬛️ SetupToolchain(pnpm:10.17.1) 811.4ms Skipped
⬛️ SetupToolchain(javascript) 0ms Skipped
🟩 SetupEnvironment(javascript) 0.8ms Passed
⬛️ SetupEnvironment(javascript, sdk) 0.9ms Skipped
⬛️ InstallDependencies(javascript) 0.1ms Skipped
🟩 RunTask(sdk:fmt-check) 904.1ms Passed
🟩 InstallDependencies(javascript, sdk) 4.5s Passed
And 12 more...
Expanded report
Action Time Status Info
🟩 RunTask(sdk:codegen-check) 86.1ms Passed
🟩 RunTask(sdk:lint) 52.6s Passed
🟩 RunTask(sdk:test-doc) 1m 45s Passed
🟩 RunTask(sdk-wasm:cache-build) 2m 11s Passed SLOW
🟩 RunTask(sdk:build) 2m 58s Passed SLOW
🟩 RunTask(root:validate-platforms) 8s Passed
🟩 RunTask(root:validate-platform-recipes) 2m 30s Passed SLOW
🟩 RunTask(sdk:test) 6m 27s Passed SLOW
🟩 RunTask(sdk-wasm:build) 4m 45s Passed SLOW
🟩 RunTask(design-data-mcp:stage) 1.2s Passed
🟩 RunTask(design-data-agent-mcp:test) 6.2s Passed
🟩 RunTask(root:test-platform-recipes-e2e) 5m 5s Passed SLOW
Changed files
.github/scripts/validate-platform-recipes.e2e.test.mjs
docs/proposals/014-platform-owned-visual-recipes.md
moon.yml
platforms/ios/extensions/implementations/button-ios.json
platforms/ios/extensions/visuals/button-ios.json
platforms/ios/manifest.json
sdk/cli/tests/cli_platform.rs

@GarthDB
GarthDB merged commit 513a65c into main Nov 1, 2026
9 checks passed
@GarthDB
GarthDB deleted the feat/ios-button-recipe branch November 1, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant