feat: unify typography and layout tokens#799
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThis PR standardizes spacing and typography: introduces shared numeric gap utilities (1–17) and rewires Flex and Grid to use class-variant gap mappings. Text and Headline components drop deprecated sizes/weights in favor of narrowed tokens, with CSS and tests updated. Grid is refactored to class-based gaps and display variants. The apps and docs are migrated to numeric gaps and new Text/Headline props, including many playgrounds and examples. Sequence Diagram(s)(skip) Possibly related issues
Suggested reviewers
|
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/www/src/app/examples/page.tsx (2)
2513-2523:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winFix invalid Text size prop in custom zeroState.
Textno longer accepts numericsizevalues. Line 2517 usessize={2}which should be migrated tosize='small'.🐛 Proposed fix
<Text - size={2} + size='small' style={{ color: 'var(--rs-color-text-subtle)' }} >🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/www/src/app/examples/page.tsx` around lines 2513 - 2523, The Text component in the zero-state UI is using a numeric size prop (size={2}) which is invalid; update the JSX where Text is used (the secondary message Text element) to use the new string token size='small' instead of size={2} so the component renders with the correct small text styling.
1980-1984:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winFix invalid Text size prop.
Textno longer accepts numericsizevalues. The numeric scale (1–10) was removed in favor of named aliases.🐛 Proposed fix
<Text - size={10} + size='large' weight='medium' style={{ marginTop: '32px', marginBottom: '16px' }} >🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/www/src/app/examples/page.tsx` around lines 1980 - 1984, The Text component is being passed a numeric size (size={10}) which is invalid now; replace the numeric size prop on Text with the design-system named alias (for example size="xl" or the appropriate alias your theme uses) in the Text JSX where size={10} appears, update any similar occurrences, and run TypeScript/linters to ensure the chosen alias matches the Text component's allowed prop type.
🧹 Nitpick comments (3)
packages/raystack/shared/gap/gap.ts (1)
3-63: ⚡ Quick winReduce duplicated 1–17 mappings to avoid drift across gap variants.
The mappings are correct, but maintaining three hand-written scales in Line 3–Line 63 is brittle. A small generator keeps
gap,column-gap, androw-gapguaranteed in sync.♻️ Suggested refactor
import styles from './gap.module.css'; +const gapScale = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] as const; +export type GapValue = (typeof gapScale)[number]; + +function createGapVariants(prefix: 'gap' | 'column-gap' | 'row-gap') { + return Object.fromEntries( + gapScale.map((value) => [value, styles[`${prefix}-${value}`]]) + ) as Record<GapValue, string>; +} + -export const gapVariants = { - 1: styles['gap-1'], - ... - 17: styles['gap-17'] -} as const; +export const gapVariants = createGapVariants('gap'); -export const columnGapVariants = { - 1: styles['column-gap-1'], - ... - 17: styles['column-gap-17'] -} as const; +export const columnGapVariants = createGapVariants('column-gap'); -export const rowGapVariants = { - 1: styles['row-gap-1'], - ... - 17: styles['row-gap-17'] -} as const; +export const rowGapVariants = createGapVariants('row-gap'); -export type GapValue = keyof typeof gapVariants;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/raystack/shared/gap/gap.ts` around lines 3 - 63, The three hand-written maps gapVariants, columnGapVariants, and rowGapVariants duplicate the same 1–17 mapping and risk drifting; replace them by programmatically generating each map (e.g., a small helper that iterates i from 1 to 17 and assigns styles[`gap-${i}`], styles[`column-gap-${i}`], styles[`row-gap-${i}`]) so all scales stay in sync, then export the generated objects with the same names (gapVariants, columnGapVariants, rowGapVariants) and keep GapValue defined as keyof typeof gapVariants; ensure the generated objects are typed/returned as const to preserve literal types.apps/www/src/content/docs/components/grid/props.ts (1)
45-62: ⚡ Quick winExtract the repeated spacing union into a shared type alias.
The
1 | ... | 17union is duplicated three times. A single alias improves maintainability and keeps docs/types in sync.Suggested refactor
export interface GridProps { + // Consider hoisting this near the top-level exports + // export type GapScale = 1 | 2 | ... | 17; + /** * Sets the gap between grid items. * Each step maps directly to `--rs-space-1` through `--rs-space-17`. */ - gap?: - | 1 - | 2 - | 3 - | 4 - | 5 - | 6 - | 7 - | 8 - | 9 - | 10 - | 11 - | 12 - | 13 - | 14 - | 15 - | 16 - | 17; + gap?: GapScale; @@ - columnGap?: - | 1 - | 2 - | 3 - | 4 - | 5 - | 6 - | 7 - | 8 - | 9 - | 10 - | 11 - | 12 - | 13 - | 14 - | 15 - | 16 - | 17; + columnGap?: GapScale; @@ - rowGap?: - | 1 - | 2 - | 3 - | 4 - | 5 - | 6 - | 7 - | 8 - | 9 - | 10 - | 11 - | 12 - | 13 - | 14 - | 15 - | 16 - | 17; + rowGap?: GapScale;Also applies to: 67-84, 89-106
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/www/src/content/docs/components/grid/props.ts` around lines 45 - 62, Create a shared type alias (e.g., GridSpacing = 1 | 2 | ... | 17) and replace each repeated numeric union for the gap properties with that alias; specifically add the alias at the top of the file and update the three occurrences of the verbose union (the gap? properties around the current blocks and the similar unions at the other two locations referenced in the review) to use GridSpacing instead, exporting the alias if these props are exported so consumers can reference it.packages/raystack/components/grid/__tests__/grid.test.tsx (1)
33-37: ⚡ Quick winAssert base grid class in inline mode as well.
Inline mode should still include the base grid class; asserting both catches regressions where
inlineaccidentally replaces base layout classing.Proposed test hardening
it('applies inline-grid class when inline is true', () => { const { container } = render(<Grid inline>Content</Grid>); const grid = container.firstChild as HTMLElement; + expect(grid).toHaveClass(styles.grid); expect(grid).toHaveClass(styles['grid-inline']); });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/raystack/components/grid/__tests__/grid.test.tsx` around lines 33 - 37, The test for Grid inline mode only asserts styles['grid-inline'] but should also assert the base grid class is present; update the spec in packages/raystack/components/grid/__tests__/grid.test.tsx to render <Grid inline> and assert that the rendered element (grid) has both styles['grid'] and styles['grid-inline'] (e.g., expect(grid).toHaveClass(styles['grid'], styles['grid-inline'])), keeping the existing Grid component render and variable names.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/www/src/content/docs/components/text/demo.ts`:
- Line 136: The example in the alignDemo uses both the Flex prop align="center"
and an inline style alignItems: "stretch", which conflict; update the alignDemo
snippet by removing the redundant alignment so intent is clear—either delete the
align="center" prop from the Flex component (to keep style={{ alignItems:
"stretch" }}) or remove alignItems: "stretch" from the style (to honor
align="center"); locate the Flex usage in the alignDemo and make one of these
two deletions so only a single alignment mechanism remains.
In `@docs/V1-migration.md`:
- Around line 1128-1148: The "After" example in the Headline migration still
uses deprecated aliases (size="large"/"medium"/"small"); update the example
instances to the new token names (size="t4", "t3", "t2") so it matches the text
and the new HeadlineProps['size'] contract, and confirm any adjacent prose or
examples no longer reference the removed aliases.
---
Outside diff comments:
In `@apps/www/src/app/examples/page.tsx`:
- Around line 2513-2523: The Text component in the zero-state UI is using a
numeric size prop (size={2}) which is invalid; update the JSX where Text is used
(the secondary message Text element) to use the new string token size='small'
instead of size={2} so the component renders with the correct small text
styling.
- Around line 1980-1984: The Text component is being passed a numeric size
(size={10}) which is invalid now; replace the numeric size prop on Text with the
design-system named alias (for example size="xl" or the appropriate alias your
theme uses) in the Text JSX where size={10} appears, update any similar
occurrences, and run TypeScript/linters to ensure the chosen alias matches the
Text component's allowed prop type.
---
Nitpick comments:
In `@apps/www/src/content/docs/components/grid/props.ts`:
- Around line 45-62: Create a shared type alias (e.g., GridSpacing = 1 | 2 | ...
| 17) and replace each repeated numeric union for the gap properties with that
alias; specifically add the alias at the top of the file and update the three
occurrences of the verbose union (the gap? properties around the current blocks
and the similar unions at the other two locations referenced in the review) to
use GridSpacing instead, exporting the alias if these props are exported so
consumers can reference it.
In `@packages/raystack/components/grid/__tests__/grid.test.tsx`:
- Around line 33-37: The test for Grid inline mode only asserts
styles['grid-inline'] but should also assert the base grid class is present;
update the spec in packages/raystack/components/grid/__tests__/grid.test.tsx to
render <Grid inline> and assert that the rendered element (grid) has both
styles['grid'] and styles['grid-inline'] (e.g.,
expect(grid).toHaveClass(styles['grid'], styles['grid-inline'])), keeping the
existing Grid component render and variable names.
In `@packages/raystack/shared/gap/gap.ts`:
- Around line 3-63: The three hand-written maps gapVariants, columnGapVariants,
and rowGapVariants duplicate the same 1–17 mapping and risk drifting; replace
them by programmatically generating each map (e.g., a small helper that iterates
i from 1 to 17 and assigns styles[`gap-${i}`], styles[`column-gap-${i}`],
styles[`row-gap-${i}`]) so all scales stay in sync, then export the generated
objects with the same names (gapVariants, columnGapVariants, rowGapVariants) and
keep GapValue defined as keyof typeof gapVariants; ensure the generated objects
are typed/returned as const to preserve literal types.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 8b8634e3-48da-44fb-864b-c3ea8d197d7e
📒 Files selected for processing (124)
apps/www/src/app/examples/datatable-virtual/page.tsxapps/www/src/app/examples/datatable/page.tsxapps/www/src/app/examples/dataview/page.tsxapps/www/src/app/examples/page.tsxapps/www/src/app/not-found.tsxapps/www/src/components/playground/alert-dialog-examples.tsxapps/www/src/components/playground/amount-examples.tsxapps/www/src/components/playground/announcement-bar-examples.tsxapps/www/src/components/playground/avatar-examples.tsxapps/www/src/components/playground/badge-examples.tsxapps/www/src/components/playground/breadcrumb-examples.tsxapps/www/src/components/playground/button-examples.tsxapps/www/src/components/playground/calendar-examples.tsxapps/www/src/components/playground/callout-examples.tsxapps/www/src/components/playground/checkbox-examples.tsxapps/www/src/components/playground/chip-examples.tsxapps/www/src/components/playground/code-block-examples.tsxapps/www/src/components/playground/collapsible-examples.tsxapps/www/src/components/playground/combobox-examples.tsxapps/www/src/components/playground/command-examples.tsxapps/www/src/components/playground/container-examples.tsxapps/www/src/components/playground/context-menu-examples.tsxapps/www/src/components/playground/dialog-examples.tsxapps/www/src/components/playground/drawer-examples.tsxapps/www/src/components/playground/field-examples.tsxapps/www/src/components/playground/fieldset-examples.tsxapps/www/src/components/playground/filter-chip-examples.tsxapps/www/src/components/playground/flex-examples.tsxapps/www/src/components/playground/floating-actions-examples.tsxapps/www/src/components/playground/headline-examples.tsxapps/www/src/components/playground/icon-button-examples.tsxapps/www/src/components/playground/image-examples.tsxapps/www/src/components/playground/indicator-examples.tsxapps/www/src/components/playground/input-examples.tsxapps/www/src/components/playground/label-examples.tsxapps/www/src/components/playground/link-examples.tsxapps/www/src/components/playground/menu-examples.tsxapps/www/src/components/playground/menubar-examples.tsxapps/www/src/components/playground/number-field-examples.tsxapps/www/src/components/playground/popover-examples.tsxapps/www/src/components/playground/preview-card-examples.tsxapps/www/src/components/playground/radio-examples.tsxapps/www/src/components/playground/search-examples.tsxapps/www/src/components/playground/select-examples.tsxapps/www/src/components/playground/separator-examples.tsxapps/www/src/components/playground/sidebar-examples.tsxapps/www/src/components/playground/skeleton-examples.tsxapps/www/src/components/playground/slider-examples.tsxapps/www/src/components/playground/spinner-examples.tsxapps/www/src/components/playground/switch-examples.tsxapps/www/src/components/playground/tabs-examples.tsxapps/www/src/components/playground/text-area-examples.tsxapps/www/src/components/playground/text-examples.tsxapps/www/src/components/playground/toast-examples.tsxapps/www/src/components/playground/toggle-examples.tsxapps/www/src/components/playground/toolbar-examples.tsxapps/www/src/components/playground/tooltip-examples.tsxapps/www/src/content/docs/(overview)/getting-started.mdxapps/www/src/content/docs/(overview)/styling.mdxapps/www/src/content/docs/components/avatar/demo.tsapps/www/src/content/docs/components/badge/demo.tsapps/www/src/content/docs/components/breadcrumb/demo.tsapps/www/src/content/docs/components/button/demo.tsapps/www/src/content/docs/components/callout/demo.tsapps/www/src/content/docs/components/checkbox/demo.tsapps/www/src/content/docs/components/chip/demo.tsapps/www/src/content/docs/components/combobox/demo.tsapps/www/src/content/docs/components/copy-button/demo.tsapps/www/src/content/docs/components/datatable/index.mdxapps/www/src/content/docs/components/drawer/demo.tsapps/www/src/content/docs/components/empty-state/demo.tsapps/www/src/content/docs/components/flex/demo.tsapps/www/src/content/docs/components/flex/props.tsapps/www/src/content/docs/components/grid/demo.tsapps/www/src/content/docs/components/grid/props.tsapps/www/src/content/docs/components/headline/demo.tsapps/www/src/content/docs/components/icon-button/demo.tsapps/www/src/content/docs/components/image/demo.tsapps/www/src/content/docs/components/indicator/demo.tsapps/www/src/content/docs/components/input/demo.tsapps/www/src/content/docs/components/label/demo.tsapps/www/src/content/docs/components/link/demo.tsapps/www/src/content/docs/components/meter/demo.tsapps/www/src/content/docs/components/popover/demo.tsapps/www/src/content/docs/components/preview-card/demo.tsapps/www/src/content/docs/components/progress/demo.tsapps/www/src/content/docs/components/radio/demo.tsapps/www/src/content/docs/components/search/demo.tsapps/www/src/content/docs/components/select/demo.tsapps/www/src/content/docs/components/separator/demo.tsapps/www/src/content/docs/components/sidebar/demo.tsapps/www/src/content/docs/components/skeleton/demo.tsapps/www/src/content/docs/components/slider/demo.tsapps/www/src/content/docs/components/spinner/demo.tsapps/www/src/content/docs/components/switch/demo.tsapps/www/src/content/docs/components/tabs/demo.tsapps/www/src/content/docs/components/text/demo.tsapps/www/src/content/docs/components/textarea/demo.tsapps/www/src/content/docs/components/toast/demo.tsapps/www/src/content/docs/components/toggle/demo.tsapps/www/src/content/docs/components/tooltip/demo.tsdocs/V1-migration.mdpackages/raystack/components/announcement-bar/announcement-bar.tsxpackages/raystack/components/calendar/range-picker.tsxpackages/raystack/components/data-view-beta/components/grouping.tsxpackages/raystack/components/data-view-beta/components/ordering.tsxpackages/raystack/components/empty-state/empty-state.tsxpackages/raystack/components/filter-chip/filter-chip.tsxpackages/raystack/components/flex/__tests__/flex.test.tsxpackages/raystack/components/flex/flex.module.csspackages/raystack/components/flex/flex.tsxpackages/raystack/components/grid/__tests__/grid.test.tsxpackages/raystack/components/grid/grid.module.csspackages/raystack/components/grid/grid.tsxpackages/raystack/components/headline/__tests__/headline.test.tsxpackages/raystack/components/headline/headline.module.csspackages/raystack/components/headline/headline.tsxpackages/raystack/components/side-panel/side-panel.tsxpackages/raystack/components/text/__tests__/text.test.tsxpackages/raystack/components/text/text.module.csspackages/raystack/components/text/text.tsxpackages/raystack/shared/gap/gap.module.csspackages/raystack/shared/gap/gap.tspackages/raystack/shared/gap/index.ts
💤 Files with no reviewable changes (3)
- packages/raystack/components/headline/headline.module.css
- packages/raystack/components/flex/flex.module.css
- packages/raystack/components/text/text.module.css
Summary
size(1–10) and free-form weights; keepmicro | mini | small | regular | largeandregular | medium.small | medium | largealiases; keept1 | t2 | t3 | t4.gap(andcolumnGap/rowGapon Grid) to a numeric1–17scale mapped to--rs-space-1through--rs-space-17; drop named aliases (extra-small | small | medium | large | extra-large). Values10–17are newly accessible.shared/gaputility consumed by both Flex and Grid.docs/V1-migration.mdwith per-prop migration maps and update internal consumers, demos, playground, and docs to the new scales.