Skip to content

refactor(remix)!: generate callable component stylers - #152

Merged
leoafarias merged 1 commit into
mainfrom
chore/better_mix_generator_support
Aug 14, 2026
Merged

refactor(remix)!: generate callable component stylers#152
leoafarias merged 1 commit into
mainfrom
chore/better_mix_generator_support

Conversation

@leoafarias

@leoafarias leoafarias commented Aug 14, 2026

Copy link
Copy Markdown
Member

Description

Use Mix's @MixableSpec(target:) support to generate callable component-styler methods from the corresponding Remix widget constructors.

  • add widget targets to 27 specs, bringing Remix to 29 target-backed specs including the existing DataList and Skeleton surfaces
  • replace 26 handwritten Styler.call(...) forwarders and remove 14 call-only part files
  • add the previously missing callable DataTableStyler surface while preserving generic types and constructor defaults
  • preserve Accordion's nullable transitionBuilder call contract by normalizing null to the component default in the widget constructor
  • pin mix_generator to the reviewed commit from conceptadev/mix#1025 so this validation branch is reproducible

Ordinary styler.call(...) and callable styler(...) usage remains source-compatible. Explicit references to the old Remix*StylerRemixHelpers call extensions must instead invoke the styler instance; this is marked as a breaking change.

The upstream generator work remains unmerged, so this branch uses an exact-SHA override to keep the workspace reproducible. The Remix integration also exposed an upstream edge case for constructor defaults that reference a target class's static member; Accordion avoids invalid generated output while retaining its existing behavior. The override should be removed once the generator support ships.

Validation

  • flutter analyze
  • full monorepo melos run ci --no-select, including clean generation checks, documentation validation, Fortal parity, and 3,028 Flutter tests
  • focused generated-call and Accordion regression suite (58 tests)
  • formatter and base-to-head whitespace checks

Related Issues


Checklist

Note: Updating the pubspec.yaml and CHANGELOG.md is not required. These are handled automatically during the release process.

  • My PR includes unit or integration tests for all changed/updated/fixed behaviors.
  • I have updated or added relevant documentation (doc comments with ///).
  • I am prepared to follow up on review comments in a timely manner.

Breaking Change

Does this PR require users of the package to manually update their code?

  • Yes, this is a breaking change.
  • No, this is not a breaking change.

BREAKING CHANGE: Explicit Remix*StylerRemixHelpers call extension references are removed; invoke the styler instance directly.
@leoafarias
leoafarias marked this pull request as ready for review August 14, 2026 13:49
@leoafarias
leoafarias merged commit 98b1c55 into main Aug 14, 2026
4 checks passed
@leoafarias
leoafarias deleted the chore/better_mix_generator_support branch August 14, 2026 13:54
leoafarias added a commit that referenced this pull request Aug 14, 2026
Adopts the `@MixableSpec(target:)` generation that landed in #152. The
hand-written `RemixLinkStylerRemixHelpers` extension is deleted; the
generator now emits an identical `LinkStyler.call` into link.g.dart, so the
constructor and its callable form can no longer drift apart.

link_style.dart held nothing but that extension, so it goes entirely, the
way badge's and button's did. The style files that survive #152 keep other
helpers besides `call`.

Adds LinkStyler to the generated-call test's non-generic group. It needs a
label because RemixLink asserts on having a name.
leoafarias added a commit that referenced this pull request Aug 14, 2026
Adds a first-class Link component to `remix` — `LinkSpec`, the generated
`LinkStyler`, and `RemixLink` built on naked_ui's `NakedLink` — and rebuilds
`FortalLink` on top of it, replacing the hand-rolled `NakedButton` plus outer
`Semantics(link:)` workaround.

A link publishes the Link role and activates on Enter and Numpad Enter, where a
button publishes the Button role and also takes Space. `onPressed: null` and
`enabled: false` mean the same thing, matching Flutter's convention that a null
callback disables a control; ordinary text is the right tool for prose that was
never meant to navigate.

`fortalLinkStyle` absorbs the old `_fortalInteractiveLinkStyle` and returns the
complete style, so `FortalLink` sheds its mirrored focus field, its duplicated
inert widget path, and its `excludeSemantics` workaround, and no longer branches
on actionability.

Requires `NakedLink`, released in naked_ui 1.0.0-beta.11 (conceptadev/naked_ui#65). The
floor is raised in both package pubspecs and in the Fortal parity contract, which
move together by design. The styler adopts the `@MixableSpec(target:)` generation
from #152, so `LinkStyler.call` is generated rather than hand-written.

Closes #137
Closes #143

BREAKING CHANGE: four changes to `remix_fortal` link behaviour.

1. `FortalLink` no longer activates on Space. Space belongs to the Button role;
   a link takes Enter and Numpad Enter, matching an anchor on the web. Use
   `FortalButton` where Space should activate.
2. `fortalLinkStyle` returns `LinkStyler` instead of `BadgeStyler`, and its
   `hovered` and `focused` parameters are gone. They were the only raw
   widget-state parameters on any Fortal recipe and existed solely to build the
   variant snapshots the recipe now assembles itself. Pass `actionable` and let
   the returned style resolve its own states.
3. A disabled `FortalLink` no longer publishes the Link role, because
   `NakedLink` gates the role on effective-enabled. This covers `onPressed: null`
   as well as `enabled: false`: a callback-less link now reports
   `hasEnabledState` and announces as unavailable, where it previously published
   a plain text node with no interactive metadata.
4. A disabled `FortalLink` is no longer reachable under
   `NavigationMode.directional`. The old `NakedButton`-backed recipe left
   disabled controls traversable on directional platforms; `NakedLink` does not.
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