Summary
padding is a single value with no axis variants, so a component whose horizontal and vertical insets differ cannot be expressed. Because the value looks complete, a consumer applies it to all four sides and gets geometry the author never specified — it fails silently rather than warning.
Concrete case
Adopting DESIGN.md on a small two-client product (a Chrome extension and an iOS app sharing one system), several components have deliberately asymmetric padding:
components:
input:
padding: "{spacing.3}" # 12px horizontal only; vertical comes from height
height: "42px"
listRow:
padding: "{spacing.3}" # 12px vertical; horizontal is 14px
Both read identically, and neither is what was meant. An input rendered with 12px on all four sides is noticeably taller than the design; a row rendered the same way is too narrow. Nothing in the file distinguishes them, and lint is clean either way.
The workaround is a prose note in the Components section telling the reader which axis the token refers to per component. That works, but it moves a value a consumer could have resolved into text it has to interpret — the opposite of what the token block is for.
Why not just use more components
Splitting input into inputHorizontal/inputVertical is not meaningful; unlike states or variants (#17), the two axes are not different components. This seems structurally different from the variants discussion.
Possible resolutions
- Add
paddingX / paddingY alongside padding, with padding remaining the uniform shorthand. Smallest change, matches how nearly every downstream target (CSS, SwiftUI, Tailwind) models it, and keeps existing files valid.
- Allow a two-value string —
padding: "{spacing.3} {spacing.4}" — CSS-shorthand style. More compact, but complicates reference resolution and diffing.
- Document
padding as strictly uniform in the spec, so authors know asymmetry belongs in prose. No code change; at least makes the current behaviour intentional rather than an unstated gap.
Option 1 seems the most useful, but option 3 alone would have saved the confusion here.
Happy to open a PR for whichever direction maintainers prefer.
Reported from a real adoption on 0.3.0; the file otherwise lints clean at zero errors and zero warnings, and the constraint of the small sub-token vocabulary genuinely improved how the rest of the system was organised.
Summary
paddingis a single value with no axis variants, so a component whose horizontal and vertical insets differ cannot be expressed. Because the value looks complete, a consumer applies it to all four sides and gets geometry the author never specified — it fails silently rather than warning.Concrete case
Adopting DESIGN.md on a small two-client product (a Chrome extension and an iOS app sharing one system), several components have deliberately asymmetric padding:
Both read identically, and neither is what was meant. An input rendered with 12px on all four sides is noticeably taller than the design; a row rendered the same way is too narrow. Nothing in the file distinguishes them, and
lintis clean either way.The workaround is a prose note in the
Componentssection telling the reader which axis the token refers to per component. That works, but it moves a value a consumer could have resolved into text it has to interpret — the opposite of what the token block is for.Why not just use more components
Splitting
inputintoinputHorizontal/inputVerticalis not meaningful; unlike states or variants (#17), the two axes are not different components. This seems structurally different from the variants discussion.Possible resolutions
paddingX/paddingYalongsidepadding, withpaddingremaining the uniform shorthand. Smallest change, matches how nearly every downstream target (CSS, SwiftUI, Tailwind) models it, and keeps existing files valid.padding: "{spacing.3} {spacing.4}"— CSS-shorthand style. More compact, but complicates reference resolution and diffing.paddingas strictly uniform in the spec, so authors know asymmetry belongs in prose. No code change; at least makes the current behaviour intentional rather than an unstated gap.Option 1 seems the most useful, but option 3 alone would have saved the confusion here.
Happy to open a PR for whichever direction maintainers prefer.
Reported from a real adoption on
0.3.0; the file otherwise lints clean at zero errors and zero warnings, and the constraint of the small sub-token vocabulary genuinely improved how the rest of the system was organised.