Browse docs
Browse docs
Live playground for theme.components.<Name>.defaults. Pin defaults in
this page's theme and see every rendered component update in real time.
Copy the exact patchTheme snippet you see into your app to adopt the
same DS identity.
For the mental model + precedence chain, start with Component Defaults System.
patchTheme({
components: {
Button: {
defaults: {
variant: 'solid',
color: 'primary',
size: 'md',
radius: 'md',
},
},
IconButton: { defaults: { variant: 'ghost', size: 'md' } },
Chip: { defaults: { variant: 'outlined', size: 'sm' } },
Badge: { defaults: { variant: 'solid', size: 'sm', color: 'primary' } },
Avatar: { defaults: { size: 'md', variant: 'circular' } },
},
});patchTheme({
components: {
TextField: { defaults: { layout: 'stacked', size: 'md' } },
Textarea: { defaults: { layout: 'stacked', size: 'md' } },
NumberField:{ defaults: { layout: 'stacked', size: 'md' } },
OTPField: { defaults: { size: 'md' } },
Autocomplete: { defaults: { layout: 'stacked', size: 'md' } },
Select: { defaults: { layout: 'stacked', size: 'md' } },
Slider: { defaults: { color: 'primary', size: 'md' } },
Checkbox: { defaults: { size: 'md', color: 'primary' } },
Switch: { defaults: { size: 'md', color: 'primary' } },
RadioGroup: { defaults: { size: 'md', color: 'primary' } },
},
});patchTheme({
components: {
Calendar: { defaults: { size: 'md', color: 'primary' } },
DatePicker: { defaults: { size: 'md', layout: 'stacked' } },
TimePicker: { defaults: { size: 'md', layout: 'stacked' } },
DateRangePicker: { defaults: { size: 'md', layout: 'stacked' } },
DateTimePicker: { defaults: { size: 'md', layout: 'stacked' } },
},
});patchTheme({
components: {
Box: { defaults: { p: 4, rounded: 'md' } },
Stack: { defaults: { gap: 3, direction: 'col' } },
Grid: { defaults: { gap: 4 } },
Container:{ defaults: { size: 'lg' } },
Divider: { defaults: { color: 'neutral', thickness: 'sm' } },
Card: { defaults: { variant: 'elevated', elevation: 1 } },
},
});patchTheme({
components: {
Alert: { defaults: { variant: 'soft', density: 'comfortable' } },
Skeleton: { defaults: { animation: 'pulse' } },
Spinner: { defaults: { size: 'md', color: 'primary' } },
Snackbar: { defaults: { severity: 'info', position: 'bottom-right' } },
Progress: { defaults: { variant: 'linear', color: 'primary', size: 'md' } },
Tooltip: { defaults: { size: 'sm', side: 'top', align: 'center' } },
},
});patchTheme({
components: {
Dialog: { defaults: { size: 'md', showCloseButton: true } },
Drawer: {
defaults: {
position: 'right',
size: 'md',
variant: 'temporary',
showCloseButton: true,
},
},
Popover: { defaults: { side: 'bottom', align: 'start' } },
ConfirmDialog: { defaults: { severity: 'warning' } },
},
});patchTheme({
components: {
Tabs: { defaults: { variant: 'underline', orientation: 'horizontal' } },
Menu: { defaults: { align: 'start', side: 'bottom' } },
Stepper: {
defaults: {
color: 'primary',
size: 'md',
orientation: 'horizontal',
labelPlacement: 'end',
},
},
Breadcrumbs: { defaults: { size: 'md' } },
Pagination: { defaults: { variant: 'outlined', size: 'md' } },
Link: {
defaults: { color: 'primary', underline: 'hover', weight: 'medium' },
},
},
});patchTheme({
components: {
Table: { defaults: { size: 'md', density: 'comfortable' } },
DataGrid: { defaults: { size: 'md', density: 'comfortable', variant: 'default' } },
},
});patchTheme({
components: {
TopBar: { defaults: { variant: 'plain', density: 'comfortable' } },
LeftNav: { defaults: { variant: 'plain', size: 'md' } },
Typography: { defaults: { color: 'neutral', weight: 'normal' } },
},
});Once you've called patchTheme({ components: ... }), every subsequent
render of that component inherits the defaults. To sanity-check:
<Button>Save</Button>.<Button size="sm">Cancel</Button>.If the bare instance doesn't inherit, common causes:
patchTheme must run BEFORE the first <Button> mounts.
Put the call in your app entry (main.tsx) or a top-level provider,
not in a lazy-loaded route.DashforgeTailwindProvider receives.<Name>VariantProps
type export (e.g. ButtonVariantProps) for the exact fields
defaults accepts.patchTheme({
components: {
Chip: {
defaults: {
variant: 'outlined', // ← DS says: chips are always outlined
color: 'neutral', // ← ...and always neutral
size: 'sm', // ← ...and always small
},
},
},
});
// Now every <Chip>text</Chip> renders as outlined + neutral + sm.
// Consumers who need a specific variant still write it explicitly:
// <Chip variant="filled" color="success">success</Chip>Use tokens for this — a single theme.radius.md change updates every
rounded-md class in every component. That's the reason tokens exist.
Only reach for theme.components when the variant CHOICE (not the
underlying token value) differs from the TV baseline.
patchTheme({
components: {
Button: {
defaults: { variant: 'solid', color: 'primary', size: 'md', radius: 'sm' },
},
},
});
// 90% of buttons — bare instance, inherit everything
<Button>Save</Button>
// Occasional escape hatch — specific site
<Button variant="ghost" size="sm">Cancel</Button>
// Nuclear utility escape — sx wins over everything
<Button sx="!bg-purple-500">Special</Button>slotProps layer for chrome-level overrides.