Styler API
Factory constructors, fluent methods, contextual shorthand, and Remix styler conventions
Remix stylers expose matching named factories and fluent methods for canonical style operations. This symmetry lets a state variant use Dart's contextual dot shorthand without constructing another styler explicitly:
Styler and spec names are unprefixed: use ButtonStyler, CardStyler,
MenuStyler, and so on. Deprecated RemixXStyler aliases and RemixXSpec
typedefs are available for source compatibility. Widgets and data classes use
the Remix prefix (RemixButton, RemixMenu, RemixMenuItem).
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';
final style = ButtonStyler()
.color(Colors.blue)
.onHovered(.color(Colors.indigo))
.onPressed(.scale(0.97));The following expressions are equivalent:
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';
final shorthand = CardStyler.color(Colors.blue);
final fluent = CardStyler().color(Colors.blue);Factory policy
| API shape | Policy |
|---|---|
| Canonical style operation | Expose both a named factory and a matching fluent method. |
| Direct child styler field | Expose a field factory such as MenuStyler.trigger(...). |
| Primary nested container | Forward one compatible canonical surface from the nested styler. |
| Alias of a canonical operation | Do not add one. A canonical operation has exactly one spelling. |
Slot-forwarding convenience (titleColor, labelFontSize) | Keep it fluent-only. It names a child slot rather than duplicating a canonical operation. |
Styler lifecycle or composition (animate, variants, wrap, modifier, merge) | Keep it fluent-only because it configures or combines an existing parent styler. |
| Generic variant helper | Keep it as an extension method; it operates on an existing styler. |
| Callable widget helper | Generate it with @MixableSpec(target: RemixWidget.new) so it stays aligned with the widget constructor. |
| Name conflict | Give the component-specific behavior a descriptive name and reserve the canonical name for the generated surface. |
Factories are generated from each component spec. Do not add public methods
directly to generated *.g.dart files.
Canonical operations and conveniences
Canonical operations include APIs such as color, padding, borderRadius,
scale, and direct child fields such as label. Each has exactly one
spelling, so contextual shorthand always resolves to the same operation:
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';
final style = CardStyler()
.padding(.all(12))
.color(Colors.white)
.onHovered(.padding(EdgeInsetsGeometryMix.all(16)))
.onPressed(.color(Colors.grey.shade100));Here every call names its operation once: color sets the container color and
.padding(.all(12)) calls padding directly.
Slot-forwarding conveniences
Each slot-forwarding convenience names a child slot that has no canonical spelling of its own on the parent styler.
| Convenience | Expands to |
|---|---|
AccordionStyler.titleColor(value) | .title(.color(value)) |
titleFontSize(value) / titleFontWeight(value) | .title(.fontSize(value)) / .title(.fontWeight(value)) |
titleStyle(value) | .title(.style(value)) |
leadingIconColor(value) / leadingIconSize(value) | .leadingIcon(.color(value)) / .leadingIcon(.size(value)) |
trailingIconColor(value) / trailingIconSize(value) | .trailingIcon(.color(value)) / .trailingIcon(.size(value)) |
contentColor(value) / contentPadding(value) / contentDecoration(value) | .content(.color(value)) / .content(.padding(value)) / .content(.decoration(value)) |
CalloutStyler.iconSize(value) | .icon(.size(value)) |
CalloutStyler.textStyle(value) | .text(.style(value)) |
Forwarded surfaces
Most visual components forward the canonical surface of their primary Box
or FlexBox container. A composite root without one clear visual surface, such
as MenuStyler, exposes factories for its child fields instead:
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';
final style = MenuStyler.trigger(
MenuTriggerStyler.color(Colors.black),
);SelectStyler stores its popup container as a FlexBox, but intentionally
forwards only the compatible Box surface. This exposes operations such as
color, padding, and scale without leaking popup layout controls through
the root select styler.
The forwarded transform factory accepts Alignment. Use a direct child
styler when a directional alignment is required, for example
CardStyler.container(BoxStyler(transform: matrix, transformAlignment: AlignmentDirectional.centerStart)).
Variants and selected state
Widget-state and selected-state helpers consume the same styler type, so named factories work contextually for every generated Remix styler:
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';
final checkboxStyle = CheckboxStyler()
.onHovered(.color(Colors.grey.shade100))
.onSelected(.color(Colors.green));Component-specific operations
Component-specific operations use explicit names when a canonical operation already occupies the shorter name:
| Styler | Canonical generated API | Component-specific helper |
|---|---|---|
TextFieldStyler | color styles the container | textColor styles editable text |
CalloutStyler | textStyle(TextStyler) applies the container text style | contentTextStyle(TextStyleMix) styles callout content |
ButtonStyler.rotate transforms the container, while
ButtonStyler.wrap(.rotate(...)) rotates the complete widget.
This keeps contextual shorthand predictable while preserving each specialized operation without ambiguous overloads.
Generation boundary
Component stylers are generated from @MixableSpec. Preset wrapper classes are
generated from @MixWidget, which is not Remix-internal: any package that
depends on remix can annotate a recipe function with it, and the generator
emits a widget calling the target Remix constructor. The application-owned
fortal preset uses exactly this mechanism to produce its prefixed
catalog. The annotations identify the target Remix constructor and which recipe
parameters become wrapper fields. Generated files remain deterministic build
artifacts and should never be edited directly.