Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .changeset/banner-action-sm-size.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
"@cloudflare/kumo": patch
---

`Banner`: stop rendering `Banner.Action` children at the deprecated
`size="xs"` in compact (`size="sm"`) banners. Both `base` and compact
banners now render actions at `Button`'s `sm` size (26px), which is the
smallest size in the current Button scale. This silences the
`[Kumo Button]: size="xs" is deprecated` warning that was emitted whenever
a compact banner rendered a `Banner.Action`.

`BannerActionSize` narrows from `"xs" | "sm"` to `"sm"`. Consumers didn't
set this prop directly — `Banner.Action` receives its size via context
from the parent `Banner` — so this is a type-level cleanup with no
behavioral change beyond removing the internal `xs` usage.
37 changes: 37 additions & 0 deletions .changeset/banner-typography-weight-first.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
"@cloudflare/kumo": minor
---

`Banner`: align title and description with the weight-first typography scale.
Both now inherit the banner container's text size (`text-base` in
`size="base"`, `text-sm` in `size="sm"`), and the title is distinguished
from the description by `font-medium` alone — matching how
`<Text variant="heading">` relates to `<Text variant="body">`.

Previously the description carried an internal `text-sm` override that made
it render one step below the container's `text-base` title. That override
is gone; a banner now reads as one hierarchy level, with weight as the
signal.

**Rendered pixel changes (as part of the wider font-scale refresh):**

- `size="base"`: title `text-base` renders at 13px (was 14px on the old
scale). Description was `text-sm` → 13px on both scales; on the new
scale it now inherits `text-base` at 13px. Net: title shrinks 14 → 13px,
description stays at 13px, and the two now sit at identical size
distinguished only by weight.
- `size="sm"`: title and description both render at `text-sm` = 12px (were
both 13px on the old scale). Description already inherited from the
container, so the class change is purely a token rename with the same
net pixel shift the whole scale is undergoing.

The `text-sm` class is no longer applied directly to the description
element in either size; it lives on the banner container. If you were
relying on that class being present on the description node specifically
(e.g. for selector-based styling), update to select the banner container
instead.

**Visual regression note:** consumers with Chromatic or screenshot tests on
`Banner` will see diffs — the title shrinks on `size="base"`, and the
whole component picks up the refreshed scale on both sizes. This is
intentional; approve the new baseline.
33 changes: 33 additions & 0 deletions .changeset/button-sizes-refresh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
"@cloudflare/kumo": minor
---

`Button`: refresh size scale to align with the refreshed typography.

**Height changes:**

| Size | Before | After |
| ---- | ------ | ----- |
| `sm` | 26px | 26px (unchanged) |
| `base` | 36px | 32px |
| `lg` | 40px | 36px |

**Font size:** `sm` buttons render at `text-sm` (12px) — one step below body
— so a small button reads as secondary next to `base` (13px) copy. `base`
and `lg` both render at `text-base` (13px); `lg` signals prominence via
height and padding, not larger type, so a button-plus-input row keeps its
type on one line without vertical bounce.

**Optical centering (`sm`):** `sm` now applies `leading-none` to fix vertical
centering. At 12px the default `text-sm` line-height (~17px) combined with
the 26px button height left ~8.6px of slack that sans-serif ascender-heavy
metrics pushed off-center. Collapsing the line-box to glyph height lets flex
centering land the text exactly on the button's optical midline. Other sizes
keep their default `text-base` line-heights.

**Deprecated:** `size="xs"`. Use `size="sm"` instead. The `xs` variant still
renders and looks the same as before, but emits a `console.warn` in
development and will be removed in a future major version.

Icon-only (`shape="square"` / `shape="circle"`) buttons shrink in step with
their text siblings — `base` is 32×32, `lg` is 36×36.
17 changes: 17 additions & 0 deletions .changeset/collapsible-trigger-text-base.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
"@cloudflare/kumo": patch
---

`Collapsible.DefaultTrigger`: align tokens with the refreshed typography
scale.

- Label class swaps `text-sm` → `text-base`. Rendered pixel size is
unchanged (old `text-sm` = 13px, new `text-base` = 13px); only the class
name changes so the trigger reads consistently with the refreshed body
scale.
- Caret icon shrinks from 16×16 (`h-4 w-4`) to 14×14 (`h-3.5 w-3.5`) so it
sits visually flush with the 13px label rather than looming larger than
it. This is the actual visible change.

Only affects `Collapsible.DefaultTrigger`. Bare `Collapsible.Trigger` still
inherits its label size from its consumer as before.
51 changes: 51 additions & 0 deletions .changeset/font-scale-multiplier.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
"@cloudflare/kumo": minor
---

Expose `--font-scale` as a hookable multiplier on every font-size token.

**Why:** we want to give products a way to let users bump up type size
without breaking layout. Neither browser zoom nor rem-based font scaling
solves this today:

- **Browser zoom** scales everything — including the viewport and pixel
values in CSS — so raising font size also enlarges paddings, gaps,
container widths, and cursor targets. The layout you designed at 100%
is not the layout the user sees at 125%.
- **Native browser font-size preferences** would work if the library
reserved `rem` strictly for font-size. It doesn't — and neither does
Tailwind's default theme, which uses `rem` for paddings, margins, and
gaps as well. So changing the browser's base font-size would rescale
spacing along with type, producing the same "zoomed layout" effect.

`--font-scale` sidesteps both by living inside font-size tokens only.
Every font-size token is now emitted as `calc(<px> * var(--font-scale, 1))`.
Consumers override the variable at any scope; spacing tokens are
untouched, so the layout grid stays put while type scales inside it.

**Mechanics:**

- Default multiplier (`1`) lives in the `var()` fallback, so no `:root`
rule is emitted — consumers can override `--font-scale` at any scope
without fighting `:root` specificity.
- Line-heights stay as raw ratios and multiply against the already-scaled
font-size at use time, so they grow naturally.
- No named presets ship with the library. Density modes are an
application-level UX concern; consumers who want a "compact" or
"comfortable" mode declare their own selectors (e.g.
`[data-density="compact"] { --font-scale: 0.875; }`) in their own
stylesheet.
- Recommended multipliers are terminating decimals so every scaled size
is also a terminating decimal — `0.875` (7/8) and `1.125` (9/8) work
cleanly; `12/13` and `14/13` produce infinite decimals like `13.9997px`
that read as floating-point noise in DevTools.

**Future work (not in this PR):** for `--font-scale` to fully deliver
"scale type without scaling layout", the library needs to move to
`rem`-for-font-size + `px`-for-spacing as a hard convention. Tailwind
default utilities still emit `rem` for spacing, so a follow-up will
either swap the spacing scale to `px` or ship a Tailwind preset that
does. Icon sizing is already `em`-relative (see the `icons-em-relative-sizing`
changeset) so icons come along for the ride automatically.

No visual regression at the default multiplier.
37 changes: 37 additions & 0 deletions .changeset/form-controls-size-refresh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
"@cloudflare/kumo": minor
---

Align form control sizes with the refreshed Button scale. Affects `Input`,
`InputArea`, `Select`, `Combobox`, `Autocomplete`, and `InputGroup`.

**Height changes:**

| Size | Before | After |
| ------ | ------ | ---------------- |
| `sm` | 26px | 26px (unchanged) |
| `base` | 36px | 32px |
| `lg` | 40px | 36px |

**Font size:** `sm` form controls now use `text-sm` (12px) instead of
`text-xs` (11px), matching Button's `sm`. `base` and `lg` remain at
`text-base` (13px) — form inputs stay at body-text legibility across
their larger sizes rather than scaling their type up with height. Button
follows the same policy at `lg` (also `text-base`, 13px), so a
button-plus-input row keeps its type on one line; `lg` here signals a
larger touch target and prominence, not larger type.

**Deprecated:** `size="xs"` on all form controls. Use `size="sm"` instead.
The `xs` variant still renders and looks the same as before, but emits a
`console.warn` in development and will be removed in a future major
version.

**Trigger icons** (`Select` caret, `Combobox` caret + clear X) no longer
carry per-size hardcoded pixel values. They now inherit their size from
the containing control's text size — see the `icons-em-relative-sizing`
changeset for the pattern. Net effect: at `base` size a caret renders
around 13px (matching the label) instead of the previous 16px, which
read heavy against 13px labels.

Select's Figma styling metadata is updated accordingly
(`height: 36 → 32`, `fontSize: 16 → 13`).
57 changes: 57 additions & 0 deletions .changeset/icons-em-relative-sizing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
"@cloudflare/kumo": minor
---

**Icons now scale with the surrounding text.** Hardcoded pixel sizes on
icons across ~20 components were replaced with em-relative sizes (or
dropped entirely so icons inherit Phosphor's `1em` default). Following
Apple's SF Symbols pattern — a UI icon is a glyph in the text's context,
and should shrink and grow with the text it sits alongside.

**Rationale:**

Under the old scale we used hardcoded pixel sizes (`size={12}`, `h-4 w-4`)
per component + per size variant, which meant every time the type scale
shifted, dozens of icon sizes across the library had to be re-audited by
hand. Worse, hardcoded sizes broke `--font-scale` (see the
`font-scale-multiplier` changeset): scaling body text up without touching
icons produced surfaces where icons floated at fixed pixel sizes while
their labels grew around them.

Em-based sizing solves both problems:

- Icons inside a `text-sm` (12px) label render at 12px automatically; the
same icon inside a `text-base` (13px) label renders at 13px.
- When `--font-scale` shifts the whole type scale, icons come along for
the ride without any per-component intervention.
- Component-internal decisions collapse from "what pixel size at what
variant" to "what ratio to the surrounding text" — expressed in one
place, valid at every scale.

**Sizing conventions established:**

| Ratio | Use for |
| ----------------------- | ------------------------------------------------------------ |
| **Bare (`1em`)** | Caret / chevron icons in form controls, buttons, pagination |
| **`0.85em`** | Inline glyphs inside chips, badges, checkboxes (X, check) |
| **`1.15em`** | Leading icons in dropdown items, menu items |
| **`1.25em`** | Sidebar menu icons, larger inline actions |
| **`var(--text-lg)`** | One-offs where the icon size must survive nested type scopes |

**Affected components** (icon sizing internals only — no API changes):

`Autocomplete`, `Button` (`RefreshButton`, loader glyph),
`Checkbox` (indicator glyph), `Collapsible` (caret), `Combobox` (caret,
clear X, chip X), `CommandPalette` (leading icons, back-arrow),
`DatePicker` (nav carets, globe), `DateRangePicker` (nav carets),
`Dropdown` (leading icons, submenu caret, check indicator, external-link
glyph), `Empty` (illustration icon), `InputGroup.Addon`,
`InputGroup.Button`, `Menubar` (leading icons via `IconContext`),
`Pagination` (nav carets), `Select` (caret), `SensitiveInput` (eye
toggle), `Sidebar` (menu-button icons, submenu chevron), `Toast` (close
X, variant icon).

**Visual regression:** icons on nearly every component will shift by 1–3px
per size variant to align with the refreshed type scale. This is
intentional — the previous hardcoded values were tuned for the 14px body
baseline and read heavy against 13px labels.
9 changes: 9 additions & 0 deletions .changeset/label-tooltip-button-sm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@cloudflare/kumo": patch
---

`Label`: bump the inline "More information" help button from `size="xs"` to
`size="sm"` (20px → 26px). Follows the Button `xs` deprecation — the label
tooltip trigger is internal, so this is a size increase rather than a
deprecation. The 26px button sits comfortably next to `text-base` (13px)
label copy without dominating it.
22 changes: 22 additions & 0 deletions .changeset/line-height-ratios-tighten.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
"@cloudflare/kumo": patch
---

Tighten line-height ratios on the refreshed typography scale so dense UI
surfaces (sidebar rows, table of contents, form controls) don't gain
excess leading versus the previous scale:

- `--text-sm--line-height`: `1.45` → `1.35` (12px × 1.35 = 16.2px)
- `--text-base--line-height`: `1.5` → `1.4` (13px × 1.4 = 18.2px)
- `--text-lg--line-height`: `1.5` → `1.45` (15px × 1.45 ≈ 21.75px)

Rationale: the old scale used tight ratios (`1/0.85 ≈ 1.176` for sm,
`1/0.75 ≈ 1.333` for xs) that produced roughly constant absolute leading
across the small end of the scale. The refreshed scale switched to
conventional per-size ratios, which loosened `text-sm` and `text-base`
by ~2–4px per line at the same rendered font-size. Components that
swapped from `text-sm` → `text-base` (Sidebar, TableOfContents) were
particularly affected. The new ratios split the difference — still
airier than the old tight scale, but closer to the previous dense feel.

`xs`, `xl`, and `2xl` ratios are unchanged.
16 changes: 16 additions & 0 deletions .changeset/table-header-weight.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"@cloudflare/kumo": patch
---

`Table`: align header styling with the refreshed typography scale.

- Column header (`<th>`) weight bumped down from `font-semibold` to
`font-medium`. 13px semibold was louder than any Text heading variant;
medium matches the `Text variant="heading"` role, which is what a column
header structurally is.
- Compact table header size bumped up from `text-xs` (11px) to `text-sm`
(12px). 11px is the escape-hatch tier reserved for chart labels and dense
metadata; a compact table header is still a header and reads more
comfortably at 12px.

Body cell typography is unchanged (`text-base`, 13px).
42 changes: 42 additions & 0 deletions .changeset/text-role-based-variants.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
"@cloudflare/kumo": minor
---

`Text` component: introduce role-based heading variants and deprecate raw
size steps on body variants.

**New variants** (all require the `as` prop for document-outline safety):

- `variant="display"` — hero / prominent moments (24px semibold)
- `variant="page-title"` — the single title of a page or dialog (19px medium)
- `variant="section-title"` — card / panel / section heading (15px medium)
- `variant="heading"` — inline / row / list-item heading (13px medium)

**Deprecated (still functional, emits a dev warning):**

- `variant="heading1"` → use `variant="display"`
- `variant="heading2"` → use `variant="page-title"`
- `variant="heading3"` → use `variant="section-title"`
- `size="xs"` (11px) and `size="lg"` (15px) on body variants → use `size="sm"`
(12px) or `size="base"` (13px), or reach for a heading variant for
hierarchy. Both still render and look the same as before but emit a
`console.warn` in development and will be removed in a future major
version.

For monospace variants, `size="lg"` remains accepted for backwards
compatibility but no longer changes the rendered size (mono always renders
at 12px, one step below body, for optical parity).

**`bold` prop (kept, refined):**

The `bold` prop is retained but its type is now narrowed to copy variants
only (`body`, `secondary`, `success`, `error`), where it bumps weight to
`font-medium` (500). Passing it on heading or monospace variants is a type
error — headings already carry their role's weight, and mono deliberately
stays regular.

The role-based names make it obvious which variant to reach for based on
what the text **is**, not what size you want. Weight-first hierarchy —
differentiating by weight rather than raw size steps on body text — is the
recommended pattern going forward. Use `bold` for inline emphasis; use
`variant="heading"` for structural hierarchy inside a document outline.
13 changes: 13 additions & 0 deletions .changeset/toast-typography-role-based.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@cloudflare/kumo": patch
---

Toast: align title and description with the role-based typography scale.

- Title: `text-[0.975rem]` (15.6px) → `text-lg` (15px medium) — matches `Text variant="section-title"` role.
- Description: `text-[0.925rem]` (14.8px) → `text-lg` (15px regular) — body-lg, muted color.
- Weight-first hierarchy: title and description share the 15px `lg` size; the medium weight on the title carries the differentiation (consistent with Linear's approach).
- `leading-5` retained on both for a compact toast footprint (vs. the default `lg--line-height` of 1.5).
- Figma metadata (`KUMO_TOAST_STYLING`) updated: title fontSize 16 → 15.

No API changes.
35 changes: 35 additions & 0 deletions .changeset/token-refresh-class-swaps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
"@cloudflare/kumo": minor
---

Align internal typography class tokens with the refreshed scale for `Badge`,
`Sidebar`, and `TableOfContents`. **Rendered font-size is unchanged** in
every case — old `text-sm` / `text-xs` and new `text-base` / `text-sm`
resolve to the same pixel values on their respective scales. Only the
class names change so component internals read consistently with the
refreshed scale (body = `text-base`, caption = `text-sm`, escape hatch =
`text-xs`).

Note: rendered *line-height* shifts slightly because the refreshed scale
uses different ratios (see the accompanying line-height tuning changeset).
Sidebar rows in particular gain ~1px of leading vs. the old scale even
though the font-size is identical.

**Affected surfaces:**

- `Badge` (`KUMO_BADGE_BASE_STYLES`): `text-xs` → `text-sm` (12px both
scales)
- `Sidebar.GroupLabel`, `Sidebar.MenuButton` (`base` and `sm`), and
`Sidebar.MenuSubButton`: `text-sm` → `text-base` (13px both scales)
- `TableOfContents` items and group-labels: `text-sm` → `text-base` (13px
both scales). `TableOfContents.Title` (uppercase eyebrow) remains
`text-xs`.

Consumers extending these components via `className` or selecting on the
old class names (e.g. `[class*="text-sm"]` on sidebar rows, custom styling
that extends `KUMO_BADGE_BASE_STYLES`) will need to update their
references. The bump is `minor` (not `patch`) because sidebar internals in
particular ship stringly-typed class contracts that consumers occasionally
lean on.

No visible change to rendered typography on any of these components.
Loading