Skip to content

Add control styles: button, picker, toggle, text field#55

Merged
colemancda merged 5 commits into
masterfrom
feature/control-styles
Jul 24, 2026
Merged

Add control styles: button, picker, toggle, text field#55
colemancda merged 5 commits into
masterfrom
feature/control-styles

Conversation

@colemancda

Copy link
Copy Markdown
Member

The style system was the largest remaining parity gap — there was no way to restyle any control. This adds .buttonStyle, .pickerStyle, .toggleStyle, and .textFieldStyle.

The design decision worth reviewing

A style is not a per-node modifier. In SwiftUI VStack { … }.buttonStyle(.bordered) styles every button in the subtree, so a style has to propagate down. This codebase already had exactly the right mechanism — the CompositionLocal inheritance that carries font, foreground color, disabled, and tint (#38) — so styles ride the same unconditional CompositionLocalProvider fold in RenderChild. Each control reads its own local.

(Provided unconditionally, never behind a branch: conditional provision tears down remembered state in the subtree, the gotcha from the animation work.)

Each control's style is its own modifier kind (buttonStyle, pickerStyle, …), so styles for different controls compose on one view instead of overwriting each other — covered by a test.

Presentations

  • buttonautomatic/borderedProminent filled, bordered outlined, plain/borderless label-only
  • pickerautomatic/menu dropdown, segmented a real segmented control, inline a radio list
  • toggleswitch, checkbox, button (a selectable chip)
  • text fieldroundedBorder/automatic outlined, plain with the box and indicators stripped

Verification

  • swift test — 3 new tests, 87 total passing. The load-bearing one asserts a container carries the style while its buttons carry none of their own, which is what distinguishes inheritance from a per-node modifier.
  • Emulator (new "Control Styles" screen), screenshot-checked across three captures:
    • all four button styles visibly distinct, and both buttons under a single container-level .buttonStyle(.bordered) render outlined — inheritance working end to end
    • the three picker styles all render, and tapping "Cocoa" in the segmented one updates the shared binding so the menu, segmented, and inline pickers plus the "Chosen:" label all follow — styling doesn't disturb the binding
    • switch / checkbox / chip all distinct; plain text field has no box where roundedBorder does

Scope

Built-in style spellings only — the ButtonStyle/ToggleStyle/… protocols for authoring custom styles aren't modeled, and .listStyle / .labelStyle aren't included. borderedProminent currently renders the same as automatic (both filled), since Material's filled button is already the prominent affordance.

@colemancda
colemancda merged commit 114fa9a into master Jul 24, 2026
6 checks passed
@colemancda
colemancda deleted the feature/control-styles branch July 24, 2026 01:17
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