Density & Sizing
CDX controls derive their geometry from CdxConfig so a single override retunes every button, dropdown trigger, segmented tab, and chip in the app. There are three sizing axes:
- Control height — vertical rhythm of standalone controls
- Compact size — dense rows (toolbars, inline chips)
- Header height — chrome bands across page tops
CdxControlSize
CdxControlSize { standard, compact } is the one way to say "dense or normal" on a CDX control or component. Every control that comes in two sizes takes size: CdxControlSize (default standard); there is no compact flag and no per-widget density enum.
Button.outlined(label: 'Cancel', size: CdxControlSize.compact, onPressed: close)
Button.icon(icon: FluentIcons.edit_24_regular, size: CdxControlSize.compact)
Banner.warning(message: 'Unsaved changes', size: CdxControlSize.compact)
EmptyState(title: 'No builds', size: CdxControlSize.compact)
CdxSegmentedTabs(size: CdxControlSize.compact, ...)
CdxPanelPage(headerSize: CdxControlSize.compact, ...)size.heightOf(CdxConfig.of(context)) resolves the one-line height at that size: controlHeight for standard, compactControlSize for compact.
controlHeight (default 36)
The baseline height of every CDX control that builds its own frame:
Button.filled / .outlined / .text— CDX baseline button height- A
CdxMenusplit trigger (outlined variant) — outer frame CdxSegmentedTabs—heightparameter falls back tocontrolHeightCdxMenufield triggers
Tune once on CdxConfig and every control follows.
CdxConfig(controlHeight: 36) // tighter app
CdxConfig(controlHeight: 44) // roomier touch-friendly appcompactControlSize (default 32)
The dense-row size for inline / list-row contexts:
Button.icon(size: CdxControlSize.compact)— 32 px squareCdxChip(size: CdxChipSize.compact)— 32 px hit targetCdxDismissAffordance(size: regular)— paired with compact controlsCdxMenu.actions(size: CdxControlSize.compact, trigger: CdxMenuTrigger.split(...))— 32 px outer height with 8 px h-padding
Use CdxControlSize.compact only inside dense contexts (toolbars, list-row trailing slots). Don't use it as a global default — it breaks the standard 40 px tap target.
headerHeight (default 70)
The shared band height for chrome headers — list headers, panel headers, dialog headers — that span the top of a surface and host a 40 px control plus 16 px vertical breathing room. Keeps headers aligned when they share a horizontal band.
Padding tokens
| Token | Default | Use |
|---|---|---|
controlPadding | 4 | Base unit for badge / chip padding (multiplied — small chips use cp * 2 h, cp * 1 v) |
containerPadding | 16 | SectionCard body padding, Banner h-padding, LockedSurface padding |
horizontalGap | 16 | Dialog footer actions, toolbars, sibling controls in a Row |
verticalGap | 16 | Stacked form groups, setting sections, sibling controls in a Column |
Reading sizing in custom controls
For custom controls that build their own frames, read the scaled CdxConfig directly. CdxConfig.of(context) falls back to defaults when no extension is registered and scales dimensions with the ambient MediaQuery.textScaler.
import 'package:vyuh_cdx_ui/vyuh_cdx_ui.dart';
final cdx = CdxConfig.of(context);
final radius = cdx.controlBorderRadius;
final height = cdx.controlHeight;
final gap = cdx.horizontalGap;
final compact = cdx.compactControlSize;
final icon = cdx.iconSize;Icon size convention
Default icon size across CDX is 16 px. The chip body, dialog action icons, dropdown trigger leading icons, segmented tab icons, and timeline indicators all use 16. Don't shrink to 12/14 to compress vertical rhythm — adjust vertical padding via controlPadding instead.