Component size props move from t-shirt labels (xs, sm, md) to a numeric ordinal scale (100, 200, 300). Extensible, predictable for humans and LLMs, backward-compatible. Migration tools included.
size props now favor numeric values, e.g. 100 (xs), 200 (sm), 300 (md), 400 (lg), 500 (xl).size props (DtIcon, DtLoader, DtEmoji, DtEmojiTextWrapper, DtProgressCircle, DtBadge's iconSize) now also accept a Number, matching every other component.DtModal's size prop (default / full) is removed and replaced by a fullscreen boolean. See migration script.sm and md? Use 250. No naming gymnastics like "smedium."dt-spacing-*, dt-layout-*, dt-icon-size-*, and color scales.Before
<dt-button size="sm">
...
</dt-button>
<dt-text kind="headline" size="xl">
...
</dt-text>
<dt-input size="lg" label="Name" />
After
<dt-button :size="200">
...
</dt-button>
<dt-text kind="headline" :size="500">
...
</dt-text>
<dt-input :size="400" label="Name" />
| T-shirt | Numeric | Description |
|---|---|---|
xs | 100 | Extra small |
sm | 200 | Small |
md | 300 | Medium (default) |
lg | 400 | Large |
xl | 500 | Extra large |
2xl | 600 | Text headline only |
3xl | 700 | Text headline only |
DtButton, DtInput, DtSelectMenu, DtSegmentedControl, DtText, DtToggle, DtChip, DtCodeblock, DtEmptyState, DtSkeleton, DtSplitButton, DtFilterPill, DtCombobox, DtComboboxMultiSelect, DtComboboxWithPopover, DtTabGroup
100-800 icon scale itself is unchanged; icon-family components just now also accept Number values on the same scale (see below).size Props Now Accept Number #DtIcon, DtLoader, DtEmoji, DtEmojiTextWrapper, DtProgressCircle, and DtBadge's iconSize prop previously only accepted size="500" (a string). They now also accept :size="500" (a number), matching every other Dialtone component. Existing string usage is unaffected.
size → fullscreen #DtModal's size prop (default / full) is replaced by a fullscreen boolean:
<!-- Before -->
<dt-modal size="full">...</dt-modal>
<!-- After -->
<dt-modal fullscreen>...</dt-modal>
The migration script below handles this transform alongside the t-shirt-to-numeric conversion.
deprecated-tshirt-sizes flags t-shirt size usage on Dialtone components and auto-fixes to numeric.
Add to your ESLint config:
// eslint.config.js (flat config)
import dialtone from '@dialpad/eslint-plugin-dialtone';
export default [
{
plugins: { dialtone },
rules: {
'dialtone/deprecated-tshirt-sizes': 'warn',
},
},
];
Then run:
npx eslint --fix "src/**/*.vue"
The rule handles: size, label-size, labelSize, and speed props on dt-* and Dt* components.
Skipped: Dynamic bindings (:size="computedValue"), non-Dialtone components.
dialtone-migrate-tshirt-to-numeric batch-transforms t-shirt sizes to numeric across your codebase.
npx dialtone-migrate-tshirt-to-numeric --dry-run --cwd ./src
npx dialtone-migrate-tshirt-to-numeric --cwd ./src
npx dialtone-migrate-tshirt-to-numeric --yes --cwd ./src
The script handles:
.vue, .md, .html, .js, .ts, .jsx, .tsx filessize, Size, speed, or Speed (future-proof)DtModal's size="full" → fullscreen and size="default" → removedSkipped:
:size="...")button-width-size, background-size, font-size)The ESLint rule flags t-shirt literals inside dynamic bindings (:size="'sm'", :size="condition ? 'sm' : 'md'"), but cannot auto-fix them. The migration script skips dynamic bindings entirely. Both require manual review.
Before
<dt-button :size="isCompact ? 'sm' : 'md'" />
After
<dt-button :size="isCompact ? 200 : 300" />
Before
computed: {
buttonSize () {
return this.isLarge ? 'lg' : 'md';
},
}
After
computed: {
buttonSize () {
return this.isLarge ? 400 : 300;
},
}
Before
const sizeMap = {
compact: 'sm',
default: 'md',
spacious: 'lg',
};
After
const sizeMap = {
compact: 200,
default: 300,
spacious: 400,
};
If a parent component passes a t-shirt string to a child's size prop, update the parent — the child already accepts numeric.
Migrating Component Sizes to Numeric Scale documentation last updated Friday, September 4, 2026
fix/popover-modal-zindex-scope