A labeled Toggle Segmented Control with optional subtext and a small-avatar group below.
subtext × avatars boolean matrix is a slot pattern in disguise — they describe whether content is present, not different visual treatments. Replace with named optional slots (subtext?: String, avatars?: [Avatar]) so the variant count drops to 1 and consumers can compose any future trailing content (a count badge, an inline error) without a new variant.Used in form sections where a binary choice carries supporting metadata — e.g. a "Send to / Request from" picker with the most-recent recipients shown below, or a "Schedule / Now" toggle with a helper subtext explaining the consequence.
subtext=yes|no, avatars=yes|no) instead of slot semantics. Should be subtext?: String + avatars?: [Avatar].- Boolean variant matrix instead of named slots.
subtext × avatarsproduces 4 variants for a slot-presence question. Replace with named optional slots — Figma Slot architecture supports this directly. C1 · Layer Structure & Naming - Inherits all Toggle - Segmented Control issues. No Pressed / Focused / Disabled state, hardcoded 2-segment count, positional
first|secondnaming — all flagged on the parent component and propagate here. C5 · Interaction State Coverage - No way to change avatar count. Avatar group is baked with exactly 3 avatars. Real consumers may want 1, 2, 5+. Should be a slot accepting
avatars: [Avatar]. C4 · Native Mappability - Code Connect mappings not registered. Blocked on the slot restructure — one mapping with optional
subtext+avatarsparams will be cleaner than 4 variant entries. C7 · Code Connect Linkability
- Convert boolean axes to named slots. Target API:
EBSegmentedControlGroup(label, segments, selectedIndex, subtext?, avatars?).subtextandavatarsbecome optional content slots driven by data, not variants. Drops Figma variant count from 4 to 1. Slot - Adopt Figma Slot for both subtext and avatars. Use Figma's native Slot feature so consumers can instance-swap any Subtext Message variant or any Avatar group composition without detaching. Slot
- Promote inner control to a data-driven Segmented Control. Tracked on the Toggle - Segmented Control component — once that ships
segments: [Segment], this group inherits the flexibility automatically. Family - Document the A11y model for the labeled group. Use
aria-labelledbyreferencing the label. Subtext getsaria-describedby. Avatars below should be a separate accessible region with their own labels. A11y
366 wide labeled group. Label on top, 40px-tall Toggle Segmented Control below, then optional subtext and avatar-group rows. Heights: 64 (base) / 86 (+ subtext) / 104 (+ avatars) / 118 (both).
Group-owned tokens are limited to the label color; everything else (segments, subtext, avatars) inherits from its sub-component.
| Role | Token | Default |
|---|---|---|
| Label | segmented-control-group/color/label | #0A2757 |
| Selected bg | toggle-segmented-control/color/selected/bg | #005CE5 |
| Unselected label | toggle-segmented-control/color/unselected/label | #005CE5 |
| Subtext | subtext-message/color/default/text | #6780A9 |
Subtext and Avatars become optional content slots after restructure. The 4-variant boolean matrix collapses to a single component definition.
| Figma Property | SwiftUI | Compose |
|---|---|---|
| subtext=yes/no | subtext: String? | subtext: String? |
| avatars=yes/no | avatars: [Avatar]? | avatars: List |
| segments | segments: [Segment] | segments: List |
| selected=first/second | selectedIndex: Int | selectedIndex: Int |
| #label | label: String | label: String |
| Requirement | iOS | Android |
|---|---|---|
| Label association | Use .accessibilityLabelledBy on the segmented row referencing the label text. | Use Modifier.semantics { contentDescription = label } on the group container. |
| Subtext announce | Wire as .accessibilityHint on the segmented row so VoiceOver reads "Label, hint: Use this space for your subtext." | Use stateDescription on the row. |
| Avatar group | Separate accessibility region; each avatar exposes its own label ("Dela Cruz, recently selected"). | Same — each avatar gets its own contentDescription. |
| ID | Criterion | Status | Notes |
|---|---|---|---|
| C1 | Layer Structure & Naming | Needs Refinement | Boolean axes for slot presence. Convert to named optional slots. |
| C2 | Variant & Property Naming | Needs Refinement | subtext=yes|no and avatars=yes|no describe slot presence, not visual variants. |
| C3 | Token Coverage | Ready | Label color uses main/text/default. All other colors inherit from sub-components. |
| C4 | Native Mappability | Needs Refinement | Maps to a single composable / SwiftUI view with optional slots after restructure. |
| C5 | Interaction State Coverage | Requires Rework | Inherits Toggle - Segmented Control's missing states. |
| C6 | Asset & Icon Quality | Not Applicable | No assets owned by this component. |
| C7 | Code Connect Linkability | Not Mapped | Blocked on slot restructure. |
subtext × avatars boolean matrix. Each combination produces a height variant: 64 / 86 / 104 / 118.
| # | subtext | avatars | Size | Node |
|---|---|---|---|---|
| 1 | no | no | 366 × 64 | 27:30941 |
| 2 | no | yes | 366 × 104 | 27:30946 |
| 3 | yes | no | 366 × 86 | 27:30957 |
| 4 | yes | yes | 366 × 118 | 27:30964 |
subtext × avatars. Composes Toggle - Segmented Control + Subtext Message + Avatar. Documentedsubtext?, avatars?). Drops variant count from 4 to 1 and unlocks any future trailing content. Open