docs(fuselage): propose enforcing the spacing scale
Proposed changes (including videos or screenshots)
The spacing scale is x4, x8, x12, x16, x20, x24, x32 and x40. Fuselage doesn't enforce it: there are no spacing tokens, spacing() accepts any x<n> or number, and the margin, padding and gap props take any value.
This draft adds:
docs/proposals/fuselage-spacing-scale.md:- what
developuses today; - where each 2px comes from and why
x2stays off the scale; - how space, radius and border width split into token families;
- a plan of one pull request per step;
- the list of every off-scale site as
file:line.
- what
packages/fuselage/scripts/scan-spacing.mjs: an AST scan that reproduces the numbers. Runnode packages/fuselage/scripts/scan-spacing.mjs [out.json]from the repository root.
Key numbers on develop:
- 1,383 spacing literals, 115 of them off the scale. Most are 2px (40) and 10px (36).
- About 22 of the 2px values are gap emulation, which becomes
gap='x4'with the same pixels. - 1,043 on-scale values are written as numbers rather than tokens.
- Sizes use
x<n>827 times, with 68 distinct values, but they shouldn't be tokens.
Handoff checklist
This PR only carries the proposal. Each step below is its own PR, stacked as docs/change-organization.md describes.
- Scale: add
spacing.jsontofuselage-tokens, exportSpacingToken, and havespacing()read it. No runtime change. - 2px:
- gap emulation becomes
gap='x4'on the parent, with the same pixels; - focus-ring padding/margin moves into
ScrollableandModalContent; - optical nudges get a screenshot review.
- gap emulation becomes
- 10, 14, 28 and 36px, grouped as the proposal suggests, with screenshots before and after for each view:
- Marketplace logs filters;
- Outbound skeleton and forms;
- modals;
- Account and E2E;
- the scattered ones.
- Values above the scale (56, 60, 64, 96, 144) move out of the spacing props into explicit CSS.
- Codemod on-scale numbers to tokens (
8→'x8'): same pixels, one commit per package. - Codemod size
x<n>values to numbers (width='x120'→width={120}): same pixels. - Narrow the spacing prop types to the scale, its negatives,
0,'none'and'auto'. Add a development-only warning inspacing(), plus a major changeset for@rocket.chat/fuselage. - Radius cleanup:
borderRadius={4}becomes'medium';- the about 30 raw CSS radii move to the radius tokens;
5pxand3pxgo to design.
- Stroke compensations in
Button,BannerandSidebarreadborderWidth('medium'). - Re-run the scan; the off-scale count must reach 0.
Still to decide with design:
- Rounding of 10, 14, 28 and 36px: one rule, or site by site?
- Whether numbers equal to a step (
8) stay accepted as an alias of the token.
Issue(s)
https://rocketchat.atlassian.net/browse/ARCH-2568
Steps to test or reproduce
node packages/fuselage/scripts/scan-spacing.mjs from the repository root, with dependencies installed. It prints the totals and the off-scale values by area. The 4 ResponsiveBar hits are nivo chart props, a known false positive.
Further comments
The Tamagui pilot (#42942) builds on this. Its space tokens become the eight steps plus their negatives, instead of about 400 x<n> tokens, each injected as a :root custom property.