Skip to content

Design system: density tiers via data-density and size props - #45

Merged
dauglyon merged 1 commit into
kbase:mainfrom
dauglyon:ds/density
Sep 10, 2026
Merged

Design system: density tiers via data-density and size props#45
dauglyon merged 1 commit into
kbase:mainfrom
dauglyon:ds/density

Conversation

@dauglyon

@dauglyon dauglyon commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

What

Controls take their height, side padding and type size from per-tier tokens in tokens.css: --ctl-h, --ctl-px, --ctl-fs, --btn-px, --btn-fs, --row-py, --row-px, --item-py, --th-fs, --gap, --gap-tight. Tiers are xs, sm, md.

Two ways to pick a tier, both plain CSS so static HTML, Solara and JupyterLab get them too:

  • data-density="comfortable" | "compact" on any element sets the tokens for its subtree (compact = the sm tier).
  • size="xs" | "sm" | "md" on a component sets them on that one element via data-size. An element's own data-size wins over an inherited region; unset, it inherits.

size is on Button, Input, Textarea, Select.Trigger, Select.Popup, Autocomplete, Tabs.Root, Menu.Popup, Toolbar.Root, Table and SearchBar. Popups are portaled to <body>, so they take size rather than inheriting a mid-page region.

Behaviour changes

  • Button no longer defaults to size="md" — an unset size inherits from the region. Explicit sizes are unchanged in meaning.
  • Table compact keeps the frameless look and now also means size="sm"; size alone keeps the frame.
  • A pill Input defaults to size="sm".
  • Native size (width in characters) is dropped from Input, Textarea, Autocomplete and SearchBar props; the fields are 100% wide anyway.
  • vuetify.css: min-height: var(--ctl-h) restated for Button and Tab, whose height the geometry reset would otherwise zero.

Pixel changes at md: Button 35→34 (sm 29→30); Select trigger 30→34, matching Input; table header 31→35 (padding 6/10 → 8/12); pill input 28→30. Everything else measures the same as before.

Not in this PR

Tree, Chip, Pagination, SegmentedControl, Row and Field are untouched. No <Theme> component; the data grid is separate.

Checks

tsc --noEmit, eslint --max-warnings=0, prettier --check, vitest run src/design-system (251 tests), pytest tests (47 tests) all pass. Heights measured in the showcase as served and with data-density="compact" on <html>: every control without an explicit size drops from the md to the sm tier; explicit sizes hold.

Controls read their height, padding and type from per-tier role tokens
(--ctl-h, --ctl-px, --ctl-fs, --btn-px, --btn-fs, --row-py, --row-px,
--item-py, --th-fs, --gap, --gap-tight). A [data-density] attribute on
any element sets them for its subtree; a component `size` prop sets them
on one element via [data-size]. Tiers are xs, sm and md; an unset size
inherits from the region, so Button no longer defaults to md.

Button, Input, Textarea, Select (trigger and popup), Autocomplete, Tabs,
Menu.Popup, Toolbar, Table and SearchBar take `size`. Table `compact`
keeps its frameless look and now means size="sm"; a pill Input defaults
to sm. Popups are portaled to <body>, so they take `size` rather than
inheriting a mid-page region.

vuetify.css restates min-height for Button and Tab, whose height the
geometry reset zeroed now that it comes from --ctl-h rather than padding.
@dauglyon
dauglyon merged commit dd28c3a into kbase:main Sep 10, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant