Ergonomics
Small authoring conveniences — the cx class-join helper and semantic tag on Container

Ergonomics#

A couple of small helpers remove boilerplate that otherwise gets copy-pasted across a codebase.

cx: joining class names#

cx joins CSS class names into a single space-separated string, skipping null and blank entries. It replaces the ad-hoc _joinClasses helper that tends to get reinvented at every call site that composes conditional classes.

Source: lib/util/classes.dart

String cx(List<String?> classes);

Pass it to any classes: parameter, mixing always-on classes with conditional ones:

div(
  classes: cx(<String?>[
    'card',
    isActive ? 'is-active' : null,
    size,
  ]),
  children,
);

null and whitespace-only entries are dropped, so a false branch simply contributes nothing:

cx(<String?>['btn', disabled ? 'btn-disabled' : null]);
// disabled == false -> 'btn'
// disabled == true  -> 'btn btn-disabled'

Semantic tags on Container#

Container renders a div by default, but the tag: parameter lets you emit any semantic HTML element instead — nav, section, header, main, aside, and so on. This keeps layout code Flutter-shaped while producing meaningful, accessible markup.

Source: lib/component/layout/flow.dart

Container(
  tag: 'section',
  padding: const EdgeInsets.all(24),
  child: const Text.body('Rendered as a <section>, not a <div>.'),
)
Container(
  tag: 'nav',
  child: navigationLinks,
)

When tag is omitted the output is byte-identical to the previous div-only behavior, so it is a safe, opt-in addition to any existing layout.