feat(remix): add segmented control component - #108
Merged
Conversation
Brings in the data list component (#103) and the publish-foundation change (#102). Both conflicts were additions at the same insertion point in the public API tests, so both sides are kept: the segmented control cases and the data list cases now sit side by side. The barrel export, docs nav, and both playground lists auto-merged, keeping Data List alongside the alphabetical segmented control placement.
# Conflicts: # packages/remix/test/public_api_compatibility_test.dart # packages/remix/test/public_api_test.dart
leoafarias
marked this pull request as ready for review
August 5, 2026 19:09
The four cross-axis intrinsic overrides derived each segment's share from the raw `spacing`, while `_mainAxisLayout` clamps it so gaps can never starve every segment. When `spacing` exceeded the queried extent the overrides floored the per-child budget to zero, so an `IntrinsicWidth` parent sized the track to zero even though real layout gave each segment a positive share. Both paths now go through `_effectiveSpacingFor`, which also removes the duplicated budget expression from all four overrides. Also adds `segmented_control_style.dart` with `call<T extends Object>()`, matching the hand-written pattern generic components use — codegen's `@MixableSpec(target:)` cannot express a generic widget, so ToggleGroup and Radio carry their own. Without it `RemixSegmentedControl.styleFrom` could not build the widget in one step, unlike every other component.
Brings in the labeled checkbox contracts (#105) and the compound menu items (#101). The only conflict was CHANGELOG.md, where both sides inserted at the top of `## Unreleased`. Both sides are kept: the segmented control entry now sits above the checkbox label and menu item entries. Everything else auto-merged — the playground registry took the segmented control and menu entries side by side, and the public API compatibility test kept both sets of cases.
The merge with main dropped the closing `);` of the `segmentedControl` declaration, causing 9 analyzer errors in CI. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds
RemixSegmentedControl<T extends Object>: a controlled, non-clearable single-select control with equal segment sizing, a persistent track, roving keyboard focus, RTL-aware navigation, and horizontal or vertical orientation.This is stacked on Remix publish foundation #102.
Component API
RemixSegmentedControl<T>acceptsitems, nullableselectedValue, non-null-emittingonChanged,enabled,orientation,loop,semanticLabel,excludeSemantics,style, and authoritativestyleSpec.RemixSegmentedControlItem<T>accepts a stable non-nullvalue, optional label/icon, required accessible name for icon-only items, per-item enabled/focus/autofocus state, and a per-item style.Reuse and implementation
NakedToggleGroupandNakedToggleOptionprimitives for selection, focus, keyboard, pointer, and semantics behavior.RemixStyleSpecBuilder,StyleSpecBuilder,RemixBoxWithEffects,StyledText, andStyledIcon.RemixToggleGroup: segmented control has a persistent track, equal-segment geometry, and effects-aware item surfaces that are a different public anatomy.Mix/code-generation surface
@MixableSpec.containerand itemcontaineruse generated forwardedBoxStylerAPIs.mainAxisSize, trackspacing, nesteditem, label, icon, and item spacing are generated fields.SegmentedControlItemSpec.lerp, required so Remix box effects interpolate instead of snap-lerping an otherwise unrecognized custom spec type.No
FortalSegmentedControlorfortalSegmentedControlStylepreset ships in v1. The docs now make explicit styling required, the icon-only example accepts a requiredSegmentedControlStyler, and the playground records why it hand-rolls its visual recipe. A Radix/Fortal preset remains a deliberate visual-design follow-up rather than an invented default in this correctness PR.Visual Evidence
Captured and visually verified locally; the PNGs are ignored and are not part of the package diff:
.context/screenshots/segmented-control-light.png— 388×344, SHA-256b396d71c614c392e0930ff3a11d747fc47d77f97a3aab547b55178fb8407725b.context/screenshots/segmented-control-dark.png— 388×344, SHA-25612f83a6f3aee012738506749c7b4b3ec30e680e23a167c01b59bae8db4c23aa9Hosted GitHub attachment upload remains pending because the connector and CLI do not expose the issue-attachment endpoint.
Validation
fvm flutter test packages/remix/test/components/segmented_control packages/remix/test/components/toggle_group packages/remix/test/public_api_test.dart packages/remix/test/public_api_compatibility_test.dart— 159/159 passed on hostednaked_ui 1.0.0-beta.9.isInMutuallyExclusiveGroup: true, matching Naked's segmented-control semantics.fvm dart run melos run generate:check— 26 generated artifacts reproduced byte-for-byte.fvm flutter analyze --fatal-infos— clean.naked_ui 1.0.0-beta.9resolution while retaining the compatible^1.0.0-beta.8package constraint.test / Run tests for all packageson final head3cd570db3— passed.git diff --check— clean.naked_ui 1.0.0-beta.9contains the mutually-exclusive ToggleOption semantics fix from conceptadev/naked_ui#84, and this branch's lockfile now resolves that hosted release.Related Issues
naked_ui 1.0.0-beta.9.Draft gates
naked_ui 1.0.0-beta.9.trueand final CI passes on that dependency.Breaking Change
Does this PR require users of the package to manually update their code?