Sizes and radii
One size scale for every control
Section titled “One size scale for every control”Each entry in sizes describes one step of the control scale:
sizes: { xs: { height: '1.75rem', paddingX: '0.625rem', fontSize: '0.75rem', iconSize: '0.75rem' }, sm: { height: '2rem', paddingX: '0.75rem', fontSize: '0.8125rem', iconSize: '0.875rem' }, md: { height: '2.5rem', paddingX: '1rem', fontSize: '0.875rem', iconSize: '1rem' }, lg: { height: '3rem', paddingX: '1.25rem', fontSize: '1rem', iconSize: '1.25rem' }, xl: { height: '3.5rem', paddingX: '1.5rem', fontSize: '1.125rem', iconSize: '1.5rem' },},Buttons, icon buttons, inputs, selects, comboboxes, tabs, menus, checkboxes, radios, switches and badges all read the same base entry, so controls of the same size line up unless a component overrides that size:
| Field | Used for |
|---|---|
height |
the fixed height of buttons, inputs, selects and tabs |
paddingX |
horizontal padding |
fontSize |
text inside the control |
iconSize |
<svg> icons inside controls, and the box of checkboxes, radios and switches |
Use rem, so controls scale with the user’s browser font size. Keep px for borders and focus rings.
defaults.size is the size every control uses when size is omitted. Set it to sm and the whole app becomes compact.
Per-component sizes
Section titled “Per-component sizes”Use allowedSizes to expose only part of the global scale on a component. Its size prop accepts exactly those keys:
components: { Button: { allowedSizes: ['sm', 'md'] }, Input: { allowedSizes: ['md'] },},Omit allowedSizes to accept every global size, including sizes added later. The list cannot be empty. The component’s resolved default, components.<Name>.size or defaults.size, must be in the list.
Use sizeOverrides separately when a component needs different measurements at a global size:
components: { Button: { allowedSizes: ['sm', 'md'], sizeOverrides: { sm: { paddingX: '0.875rem' }, md: { paddingX: '1.25rem' }, }, }, Input: { allowedSizes: ['md'], },},Each override is partial. Unset fields still come from the global size, and an override alone does not restrict the component’s prop type. Override keys must be allowed when allowedSizes is present.
Keep height shared when controls should line up in the same row. Overriding it is an explicit choice to opt that component out of shared height alignment.
Sizes and spacing are different scales
Section titled “Sizes and spacing are different scales”sizes is for controls: how big a button or input is to click and read. spacing is for layout: the padding inside cards and dialogs (defaults.padding) and the gap between items (defaults.gap). They’re separate so a dense app can have small controls with generous spacing, or the other way around. Their keys are independent too.
A theme must define every size your app uses
Section titled “A theme must define every size your app uses”If <Button size="xl"> is rendered with a theme that has no xl, the button gets the class yarcl-size-xl but no CSS for it, so it collapses. With a config, that’s a type error. For themes switched at runtime, check them against a shared contract (see switching themes).
Radius scale
Section titled “Radius scale”radii is an open group. The convention is to name the steps like your sizes, plus two exceptions:
radii: { square: '0', sm: '0.25rem', md: '0.375rem', lg: '0.5rem', xl: '0.75rem', rounded: '9999px',},defaults.radius is the radius every component uses when radius is omitted: buttons, inputs, cards, dialogs, badges, alerts. The library default is md.
defaults: { radius: 'md' }, // every componentcomponents: { Button: { radius: 'square' } } // except buttonsSee component defaults for per-component overrides.
Modal sizes
Section titled “Modal sizes”modalSizes is a separate open group for the widths of dialogs and drawers. It’s separate from sizes because the two scales measure different things: control sizes set a button’s height, modal sizes set a panel’s width.
modalSizes: { sm: '24rem', md: '32rem', lg: '48rem', xl: '64rem', full: '100vw',},defaults: { modalSize: 'md' },components: { Drawer: { size: 'sm' } },Widths are capped to the screen, so full leaves a small margin around dialogs.
Layout widths and breakpoints
Section titled “Layout widths and breakpoints”Use widths for page and container geometry. These keys do not become valid dialog or drawer sizes.
widths: { sidebar: '15rem', reading: '44rem', page: '72rem' },breakpoints: { xs: '30rem', sm: '40rem', md: '48rem', lg: '64rem', xl: '80rem' },The generator emits each width as --yarcl-width-{key}. Breakpoints become named media queries. In CSS imported through a yarcl build plugin, write @media (--yarcl-max-md) or @media (--yarcl-min-md). The plugin replaces the name with the configured threshold before the browser receives the stylesheet.
Breakpoint names must start with a letter and contain only letters, numbers, hyphens or underscores. Breakpoints are resolved at build time; changing themes at runtime does not change media-query thresholds.
.page { max-width: var(--yarcl-width-page); }
@media (--yarcl-max-md) { .page { padding-inline: var(--yarcl-space-sm); }}The generated stylesheet also contains @custom-media definitions. For app CSS, import the file through the yarcl build plugin so those names are expanded before they reach the browser.
Matching radius to size (opt-in)
Section titled “Matching radius to size (opt-in)”Set defaults.radius: 'size' to give each control the radius named like its size: an lg button gets radii.lg, an sm input gets radii.sm. Components without a size use the radius of defaults.size. size is reserved and can’t be used as a radius key.