Styling
Form Kit controls draw with vyuh_cdx_ui and are themed through CdxConfig, the CDX ThemeExtension. The look of every field (text fields, dropdown triggers, pickers, switch rows, field labels and section captions) comes from one token set, CdxFieldStyle, with two presets.
Classic and refined
CdxConfig.classic() (default) | CdxConfig.refined() | |
|---|---|---|
| Field style | CdxFieldStyle() | CdxFieldStyle.refined() |
| Label | Floating inside the outline, muted tone | Above the field, 12 px / w500, strong tone |
| Field height | Intrinsic | 32 px, 10 px horizontal padding |
| Radius | controlBorderRadius (4 px) | 6 px |
| Outline | Strong (outline) | Soft (outlineVariant) |
| Focus ring | 1 px | 1.5 px |
| Text | Theme default | 13 px value, 11 px notes and captions |
| Switch rows | Platform size | Fit into 20 px |
| Use for | Existing apps; nothing changes | Designers, blueprints and dense data-entry forms |
CdxConfig.classic() is the same as const CdxConfig(), token for token, so apps that never pass a config keep their look. The refined preset differs from classic only in fieldStyle; every shape and colour token is the same.
import 'package:vyuh_cdx_ui/vyuh_cdx_ui.dart';
// Existing apps: no change, classic look.
final classic = createCdxTheme(colorScheme: scheme, textTheme: textTheme);
// Form Kit apps: refined look, with token overrides on top.
final refined = createCdxTheme(
colorScheme: scheme,
textTheme: textTheme,
config: const CdxConfig.refined(
primary: Color(0xFF1F5FAF),
fieldStyle: CdxFieldStyle.refined(height: 30),
),
);
// Mix: classic chrome, labels above only.
const labelsAbove = CdxConfig(
fieldStyle: CdxFieldStyle(labelPlacement: CdxFieldLabelPlacement.above),
);Read the active look inside a widget:
final style = CdxConfig.of(context).fieldStyle;
if (style.isCompact) {
// fixed-height fields
}CdxFieldStyle tokens
| Token | Type | Classic | Refined |
|---|---|---|---|
labelPlacement | CdxFieldLabelPlacement (floating, above) | floating | above |
labelTone | CdxFieldLabelTone (muted, strong) | muted | strong |
labelStyle | TextStyle? | null | 12 px, w500 |
labelGap | double | 6 | 6 |
borderRadius | BorderRadius? | null (uses controlBorderRadius) | 6 px |
outline | CdxFieldOutline (strong, soft) | strong | soft |
focusWidth | double | 1 | 1.5 |
height | double? | null (intrinsic) | 32 |
horizontalPadding | double? | null | 10 |
textStyle | TextStyle? | null | 13 px |
noteStyle | TextStyle? | null | 11 px |
captionStyle | TextStyle? | null | 11 px, w600, 0.88 letter spacing |
toggleHeight | double? | null | 20 |
Text tokens are partial styles layered over the matching TextTheme slot, so a brand's typography still comes through. null means "keep the Material or caller default". Both CdxConfig and CdxFieldStyle support copyWith, lerp and value equality, so overrides compose:
final config = const CdxConfig.refined().copyWith(
fieldStyle: const CdxFieldStyle.refined().copyWith(focusWidth: 2),
);Supporting widgets
| Widget | Use |
|---|---|
CdxLabeledField(label:, child:, hasError:, active:, labelStyle:) | Draws a label above a field and merges both into one accessibility node, so the field keeps its label as its accessible name. The label takes the primary colour while focus is inside and the error colour when hasError. |
CdxSectionCaption(text) | A group caption styled by the active captionStyle. |
CdxFieldAffixButton(icon:, onPressed:, tooltip:) | A prefix or suffix button inside a field. With a fixed field height it is a square of that height, so it cannot grow the field. |
InputDecoration.withoutLabel() | An extension that strips label / labelText from a decoration, for fields that draw their label above. |
Not affected by the presets
The Material DropdownMenu focus ring (2 px), non-field radii (buttons, cards, dialogs, data tables) and CdxSlider look the same in both presets.
See CDX UI theming for the rest of CdxConfig.