Skip to content

feat(remix): align Fortal with Radix Themes 3.3.0#80

Open
leoafarias wants to merge 34 commits into
mainfrom
feat/fortal-polish
Open

feat(remix): align Fortal with Radix Themes 3.3.0#80
leoafarias wants to merge 34 commits into
mainfrom
feat/fortal-polish

Conversation

@leoafarias

@leoafarias leoafarias commented Jul 20, 2026

Copy link
Copy Markdown
Member

Description

Atlas capture cleanup was merged separately in #83; this PR now targets main without those removals in its diff.

Aligns Fortal with the pinned Radix Themes 3.3.0 contract across 20 mapped component families while retaining Accordion, Toggle, and ToggleGroup as documented Fortal extensions. Reworks component APIs, demos, examples, docs, and the Remix skill around widget composition and enum-based recipes; fixes sizing, scrolling, animation, focus, disabled-state, hit-testing, interpolation, and RTL behavior.

Redesigns advanced container paint around one logical component box. Ordinary fill, border, radius, gradient, and elevation remain in Mix BoxSpec/FlexBoxSpec; RemixBoxEffectsMix now owns only behindContent, backdrop blur, overContent, and offset outlines. The old Surface/PaintShadow API is hard-renamed to BoxEffects/BoxShadow with no compatibility aliases, generic component fields are now containerEffects, and the internal Box/Flex adapters are no longer root-exported.

Moves ordinary Dialog, Menu, Popover, Select, Slider-thumb, and Switch-thumb elevation to Mix BoxShadowMix. Remix shadows remain for true inset paint, shapeInset, explicit layer positioning, focus/error overlays, and mixed inset/outer lists. mix is resolved from pub.dev at 2.2.0-beta.1; annotations and generator remain on hosted beta.0, while the separate unhosted mix_protocol development dependency remains on git. A demo-level hosted mix override is retained because that git package still pins its own git Mix revision.

Restores direct-pixel characterization for gradient insets and ordering, inset blur/spread/offset, shapeInset, borders, clipping, backdrop isolation, foreground decoration, content ordering, ordinary and advanced shadows, and outlines. The maintainer explainer is now docs/remix-box-effects-explainer.html and includes the domain tree, paint order, hard-rename map, ownership rules, and worked component patterns.

Adds a polished Flutter dashboard and component gallery for exercising the Fortal system in realistic product layouts. The dashboard review exposed an expanding Badge recipe: FortalBadge painted the full bounded parent instead of hugging its label. The recipe now remains content-sized, with a regression test covering a badge inside a bounded grid cell.

Parity is enforced through the pinned manifest, Chromium fixtures, coverage ledger, generated-source checks, documentation validation, pixel tests, and widget tests. Naked UI is pinned to the published 1.0.0-beta.7 release.

Related Issues

Resolved upstream by conceptadev/naked_ui#76.


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, and fixed behaviors.
  • I have updated or added relevant documentation.
  • 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.

Fortal's named convenience constructors and several scalar/content properties are replaced by enum-based recipes and widget-compositional APIs. The unreleased advanced-paint API is also a hard cut: RemixPaintShadow* becomes RemixBoxShadow*, RemixSurfaceLayer* becomes RemixBoxEffectLayer*, RemixSurfaceEffects* becomes RemixBoxEffects*, background/foreground become behindContent/overContent, and generic effects becomes containerEffects.

Validation

  • fvm dart run melos run ci --no-select — passed locally.
  • fvm flutter analyze — no issues.
  • Focused Box Effects, direct-pixel, Mix beta contract, and component interpolation tests — 56 passed.
  • Generated sources: 162 library Dart files remained byte-for-byte unchanged after generation.
  • Documentation: 25 MDX files, 87 analyzable Dart examples, and 78 app/example Dart sources passed validation.
  • Fortal parity: 20 mapped families, 3 documented extensions, Chromium fixtures, coverage ledger, Naked UI 1.0.0-beta.7, and no undocumented approximations verified.
  • Flutter tests: Remix 1,591; dashboard 13; demo 2; playground 1 — all passed.
  • Maintainer guide scripts, unique IDs, and static ARIA references passed local checks. Chrome extension policy blocked direct navigation to the local file:// guide, so the requested live desktop/narrow browser inspection could not be completed in that surface.

Review fixes for the Fortal theming foundation:

- Radio surface selected indicator uses accentContrast instead of
  hardcoded white, matching Checkbox and Radix base-radio.css (the dot
  was near-invisible on light accents like amber).
- Toggle outline selected foreground uses accent11 (text-calibrated)
  instead of accent10 (background-hover step), matching the ghost
  variant and every sibling component.
- Badge soft/surface/outline foregrounds use accentA11 instead of
  accentA10 for legible low-contrast label text.
- buildFortalShadows now bakes fully-resolved colors into the shadow
  token map instead of nested token refs; refs inside List<BoxShadow>
  values never resolved through MixScope, so consuming shadow1-6
  crashed at paint time and the protocol encoder rejected them with
  constraint violations.
- Dialog/Popover/Menu overlays consume FortalTokens.shadow6/shadow5
  directly instead of hand-duplicated dark-only recipes, so light mode
  now gets the correct Radix gray-alpha layers (closes the in-code
  "follow-up work" deferral).
- Protocol probe drops the expected-failure + concretize scaffolding;
  themes now encode cleanly (goldens and atlas bundle regenerated,
  theme JSON values unchanged).
- Pin shadow1/4/5 light+dark layers in fortal_tokens_test (previously
  untested), and unify dartdoc on the color/radius/highContrast
  override fields across all Fortal presets.
# Conflicts:
#	atlas/fortal/README.md
#	atlas/fortal/capture.json
#	atlas/fortal/protocol/coverage.json
#	packages/demo/test/atlas/fortal_protocol_probe_test.dart
#	packages/demo/test/atlas/goldens/protocol/coverage.json
#	packages/remix/CHANGELOG.md
#	packages/remix/lib/src/components/badge/fortal_badge_styles.dart
#	packages/remix/lib/src/components/button/button.g.dart
#	packages/remix/lib/src/components/button/button_widget.dart
#	packages/remix/lib/src/components/button/fortal_button_styles.dart
#	packages/remix/lib/src/components/callout/callout_widget.dart
#	packages/remix/lib/src/components/textfield/fortal_textfield_styles.dart
#	packages/remix/test/components/button/button_widget_test.dart
#	packages/remix/test/components/callout/callout_widget_test.dart
#	packages/remix/test/components/fortal_widget_test.dart
#	packages/remix/test/components/textfield/textfield_widget_test.dart
#	packages/remix/test/utilities/spinner_style_mixin_test.dart
#	skills/using-remix/SKILL.md
#	skills/using-remix/references/components.md
#	skills/using-remix/references/fortal-reference.md
CI verifies atlas goldens on pinned macOS 15 while they are captured on
newer macOS. CoreText antialiases the spinner arc and text_field glyphs a
few pixels differently across macOS versions, drifting ~0.02% of pixels
while the components are unchanged, which exceeded the previous 0.01%
tolerance. Raise precisionTolerance to 0.05% — ~2.5x above the measured
host noise, far below any real regression. Structured capture hashes
remain exact.
@leoafarias
leoafarias marked this pull request as ready for review July 21, 2026 00:21
- menu: inline a needless assign-then-return in _RemixMenuPanel.build
- slider: check values.length instead of allocating percentages just to
  count thumbs; document _visualPercentage as a naked_ui flip mirror
- tabs: drop the dead, misleading `size` param from fortalTabBarStyler
- surface: comment the const-context finiteness assert so it is not
  "simplified" to .isFinite (which breaks const evaluation)
Move standard decoration into Mix box specs, consolidate component effect slots, and keep private adapters only for advanced paint. Add responsive dashboard coverage and preserve exact Fortal fills.

BREAKING CHANGE: retired surface and paint-overlay fields are replaced by effects aggregates and role-specific effects fields.
Keep arbitrary widget icon content while restoring Flutter-conventional IconButton naming across Remix, Fortal, examples, and tests. Extend documentation validation to cover the dashboard, READMEs, and consumer skill guidance so removed slot and variant syntax cannot drift again.
# Conflicts:
#	packages/demo/pubspec.yaml
#	pubspec.yaml
@leoafarias
leoafarias changed the base branch from main to agent/remove-fortal-atlas July 23, 2026 04:14
Base automatically changed from agent/remove-fortal-atlas to main July 23, 2026 04:23
# Conflicts:
#	packages/demo/pubspec.yaml
#	pubspec.yaml
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