From 9423a49aa3cf0bff3006631d34be942dcefbf025 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 15 Aug 2026 22:16:01 +0000 Subject: [PATCH 1/2] feat: use caption-1 text for the small size of Button, MenuItem, Tabs and form fields Button, MenuItem, Tabs, TextField, Select and PinField rendered body-2 text in their small size, matching the medium size. They now use caption-1, following Checkbox and Radio which already do that. caption-1 has a smaller line height, so the components would shrink. Their vertical padding grows by half of the line height difference on each side to keep the size unchanged. The difference is derived from the theme tokens via --rs-caption-1-line-height-offset, so themes where both line heights match resolve it to 0 and are unaffected. Button min-width was expressed through the horizontal padding, which relied on it being exactly one unit larger than the vertical one. It now reuses the same value as min-height so icon-only buttons stay square. PinField and Tabs size their items independently of the text, so they only switch the Text variant. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UVFEsPkaDMhhb3CVc1zWkE --- .changeset/small-size-caption-text.md | 5 +++++ .../src/components/Button/Button.module.css | 18 ++++++++++-------- .../components/MenuItem/MenuItem.module.css | 9 +++++---- .../components/PinField/PinFieldControlled.tsx | 8 +++++--- .../src/components/Reshaped/Reshaped.css | 9 +++++++++ .../src/components/Select/Select.module.css | 12 +++++++----- .../src/components/Tabs/Tabs.module.css | 3 ++- .../reshaped/src/components/Tabs/TabsItem.tsx | 2 +- .../components/TextField/TextField.module.css | 14 +++++++++----- 9 files changed, 53 insertions(+), 27 deletions(-) create mode 100644 .changeset/small-size-caption-text.md diff --git a/.changeset/small-size-caption-text.md b/.changeset/small-size-caption-text.md new file mode 100644 index 00000000..ce5303f3 --- /dev/null +++ b/.changeset/small-size-caption-text.md @@ -0,0 +1,5 @@ +--- +"reshaped": patch +--- + +Button, MenuItem, Tabs, TextField, Select and PinField: Small size now renders caption-1 text, their vertical padding grows by the line height difference so the component size stays the same diff --git a/packages/reshaped/src/components/Button/Button.module.css b/packages/reshaped/src/components/Button/Button.module.css index f5b32e89..58f53580 100644 --- a/packages/reshaped/src/components/Button/Button.module.css +++ b/packages/reshaped/src/components/Button/Button.module.css @@ -6,6 +6,7 @@ /* Using --rs-button-p and --rs-p to dynamically reassign --rs-p for all sizes of ghost buttons, used by Aligner */ --rs-p-v: var(--rs-button-p-v); --rs-p-h: var(--rs-button-p-h); + --rs-button-min-size: calc(var(--rs-button-line-height) + var(--rs-button-p-v) * 2); transition: var(--rs-duration-fast) var(--rs-easing-standard); transition-property: background-color, box-shadow, border-color, color, transform, opacity; @@ -29,10 +30,10 @@ line-height: var(--rs-button-line-height); letter-spacing: var(--rs-button-letter-spacing); box-sizing: border-box; - min-height: calc(var(--rs-button-line-height) + var(--rs-p-v) * 2); - min-width: calc( - var(--rs-button-line-height) - (var(--rs-unit-x1) * 2) + (var(--rs-button-p-h) * 2) - ); + + /* Keeps icon-only buttons square by using the same value for both dimensions */ + min-height: var(--rs-button-min-size); + min-width: var(--rs-button-min-size); background-color: var(--rs-button-background-color); color: var(--rs-button-color); isolation: isolate; @@ -142,13 +143,14 @@ @responsive .--size { @value small { - --rs-button-p-v: var(--rs-unit-x1); + /* Padding grows by the line height difference to keep the size the same as with body-2 text */ + --rs-button-p-v: calc(var(--rs-unit-x1) + var(--rs-caption-1-line-height-offset)); --rs-button-p-h: var(--rs-unit-x2); --rs-button-gap: var(--rs-unit-x1-5); --rs-button-icon-align: var(--rs-unit-x0-5); - --rs-button-line-height: var(--rs-line-height-body-2); - --rs-button-font-size: var(--rs-font-size-body-2); - --rs-button-letter-spacing: var(--rs-letter-spacing-body-2); + --rs-button-line-height: var(--rs-line-height-caption-1); + --rs-button-font-size: var(--rs-font-size-caption-1); + --rs-button-letter-spacing: var(--rs-letter-spacing-caption-1); --rs-button-radius: var(--rs-radius-small); } diff --git a/packages/reshaped/src/components/MenuItem/MenuItem.module.css b/packages/reshaped/src/components/MenuItem/MenuItem.module.css index 4179533a..dccc37c3 100644 --- a/packages/reshaped/src/components/MenuItem/MenuItem.module.css +++ b/packages/reshaped/src/components/MenuItem/MenuItem.module.css @@ -32,13 +32,14 @@ button.root { @responsive .--size { @value small { - --rs-p-v: var(--rs-unit-x1); + /* Padding grows by the line height difference to keep the size the same as with body-2 text */ + --rs-p-v: calc(var(--rs-unit-x1) + var(--rs-caption-1-line-height-offset)); --rs-p-h: var(--rs-unit-x1-5); --rs-menu-item-radius: var(--rs-radius-small); - font-size: var(--rs-font-size-body-2); - line-height: var(--rs-line-height-body-2); - letter-spacing: var(--rs-letter-spacing-body-2); + font-size: var(--rs-font-size-caption-1); + line-height: var(--rs-line-height-caption-1); + letter-spacing: var(--rs-letter-spacing-caption-1); } @value medium { diff --git a/packages/reshaped/src/components/PinField/PinFieldControlled.tsx b/packages/reshaped/src/components/PinField/PinFieldControlled.tsx index b8e315bf..a5861b20 100644 --- a/packages/reshaped/src/components/PinField/PinFieldControlled.tsx +++ b/packages/reshaped/src/components/PinField/PinFieldControlled.tsx @@ -45,9 +45,11 @@ const PinFieldControlled: React.FC = (props) => { } = props; const patternRegexp = patternMap[pattern]; const responsiveInputSize = responsivePropDependency(size, (value) => sizeMap[value]); - const responsiveTextVariant = responsivePropDependency(size, (value) => - value === "medium" ? "body-2" : "body-1" - ); + const responsiveTextVariant = responsivePropDependency(size, (value) => { + if (value === "small") return "caption-1"; + if (value === "medium") return "body-2"; + return "body-1"; + }); const responsiveRadius = responsivePropDependency(size, (value) => value === "small" ? "small" : "medium" ); diff --git a/packages/reshaped/src/components/Reshaped/Reshaped.css b/packages/reshaped/src/components/Reshaped/Reshaped.css index 4db62359..636818b1 100644 --- a/packages/reshaped/src/components/Reshaped/Reshaped.css +++ b/packages/reshaped/src/components/Reshaped/Reshaped.css @@ -4,6 +4,15 @@ --rs-outline: var(--rs-outline-width) solid var(--rs-color-border-primary); --rs-outline-shadow: 0 0 0 var(--rs-outline-width) var(--rs-color-border-primary) inset; --rs-radius-circular: 9999px; + + /* + Small components render caption-1 text while keeping the height they had with body-2 text. + Their vertical padding grows by this value on each side to compensate for the line height difference. + Themes where both line heights match resolve it to 0 and stay unaffected. + */ + --rs-caption-1-line-height-offset: calc( + (var(--rs-line-height-body-2) - var(--rs-line-height-caption-1)) / 2 + ); } [data-rs-theme] body, diff --git a/packages/reshaped/src/components/Select/Select.module.css b/packages/reshaped/src/components/Select/Select.module.css index e5c0e799..bacf38a1 100644 --- a/packages/reshaped/src/components/Select/Select.module.css +++ b/packages/reshaped/src/components/Select/Select.module.css @@ -107,13 +107,15 @@ --rs-select-gap: var(--rs-unit-x1-5); --rs-select-chevron-size: var(--rs-unit-x4); --rs-select-radius: var(--rs-radius-small); - --rs-select-p-v: var(--rs-unit-x1); + + /* Padding grows by the line height difference to keep the size the same as with body-2 text */ + --rs-select-p-v: calc(var(--rs-unit-x1) + var(--rs-caption-1-line-height-offset)); --rs-select-p-h: var(--rs-unit-x2); - --rs-select-font-size: var(--rs-font-size-body-2); - --rs-select-line-height: var(--rs-line-height-body-2); - --rs-select-letter-spacing: var(--rs-letter-spacing-body-2); + --rs-select-font-size: var(--rs-font-size-caption-1); + --rs-select-line-height: var(--rs-line-height-caption-1); + --rs-select-letter-spacing: var(--rs-letter-spacing-caption-1); --rs-select-icon-align: var(--rs-unit-x0-5); - --rs-select-min-height: calc(var(--rs-select-line-height) + var(--rs-unit-x1) * 2); + --rs-select-min-height: calc(var(--rs-select-line-height) + var(--rs-select-p-v) * 2); } @value medium { diff --git a/packages/reshaped/src/components/Tabs/Tabs.module.css b/packages/reshaped/src/components/Tabs/Tabs.module.css index dd34dd31..f8b1f62e 100644 --- a/packages/reshaped/src/components/Tabs/Tabs.module.css +++ b/packages/reshaped/src/components/Tabs/Tabs.module.css @@ -355,7 +355,8 @@ } .--size-small { - --rs-tabs-item-p-v: var(--rs-unit-x1); + /* Padding grows by the line height difference to keep the size the same as with body-2 text */ + --rs-tabs-item-p-v: calc(var(--rs-unit-x1) + var(--rs-caption-1-line-height-offset)); --rs-tabs-item-p-h: var(--rs-unit-x2); --rs-tabs-icon-gap: var(--rs-unit-x1-5); --rs-tabs-radius: var(--rs-radius-small); diff --git a/packages/reshaped/src/components/Tabs/TabsItem.tsx b/packages/reshaped/src/components/Tabs/TabsItem.tsx index 72f61986..cbf2680d 100644 --- a/packages/reshaped/src/components/Tabs/TabsItem.tsx +++ b/packages/reshaped/src/components/Tabs/TabsItem.tsx @@ -87,7 +87,7 @@ const TabsItem = React.forwardRef((props, ref) => { {icon && } {children && ( diff --git a/packages/reshaped/src/components/TextField/TextField.module.css b/packages/reshaped/src/components/TextField/TextField.module.css index 9eaf210b..b620cf9f 100644 --- a/packages/reshaped/src/components/TextField/TextField.module.css +++ b/packages/reshaped/src/components/TextField/TextField.module.css @@ -194,14 +194,18 @@ @value small { --rs-text-field-gap: var(--rs-unit-x1-5); --rs-text-field-radius: var(--rs-radius-small); - --rs-text-field-p-v: var(--rs-unit-x1); + + /* Padding grows by the line height difference to keep the size the same as with body-2 text */ + --rs-text-field-p-v: calc(var(--rs-unit-x1) + var(--rs-caption-1-line-height-offset)); --rs-text-field-p-h: var(--rs-unit-x2); --rs-text-field-icon-align: var(--rs-unit-x0-5); - --rs-text-field-font-size: var(--rs-font-size-body-2); - --rs-text-field-line-height: var(--rs-line-height-body-2); - --rs-text-field-letter-spacing: var(--rs-letter-spacing-body-2); + --rs-text-field-font-size: var(--rs-font-size-caption-1); + --rs-text-field-line-height: var(--rs-line-height-caption-1); + --rs-text-field-letter-spacing: var(--rs-letter-spacing-caption-1); --rs-text-field-action-inset: var(--rs-unit-x1); - --rs-text-field-min-height: calc(var(--rs-text-field-line-height) + var(--rs-unit-x1) * 2); + --rs-text-field-min-height: calc( + var(--rs-text-field-line-height) + var(--rs-text-field-p-v) * 2 + ); } @value medium { From ecb93826a5ce0977fbd56b5168092eee449e475f Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 15 Aug 2026 22:24:17 +0000 Subject: [PATCH 2/2] refactor: inline the caption-1 line height compensation in each component Replaces the --rs-caption-1-line-height-offset global variable with the same calc written directly in each small size block, so no new theme-level variable is introduced. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UVFEsPkaDMhhb3CVc1zWkE --- .../reshaped/src/components/Button/Button.module.css | 6 ++++-- .../reshaped/src/components/MenuItem/MenuItem.module.css | 6 ++++-- packages/reshaped/src/components/Reshaped/Reshaped.css | 9 --------- .../reshaped/src/components/Select/Select.module.css | 6 ++++-- packages/reshaped/src/components/Tabs/Tabs.module.css | 6 ++++-- .../src/components/TextField/TextField.module.css | 6 ++++-- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/packages/reshaped/src/components/Button/Button.module.css b/packages/reshaped/src/components/Button/Button.module.css index 58f53580..f0fca2c5 100644 --- a/packages/reshaped/src/components/Button/Button.module.css +++ b/packages/reshaped/src/components/Button/Button.module.css @@ -143,8 +143,10 @@ @responsive .--size { @value small { - /* Padding grows by the line height difference to keep the size the same as with body-2 text */ - --rs-button-p-v: calc(var(--rs-unit-x1) + var(--rs-caption-1-line-height-offset)); + /* Padding absorbs the caption-1 line height difference to keep the size it had with body-2 text */ + --rs-button-p-v: calc( + var(--rs-unit-x1) + (var(--rs-line-height-body-2) - var(--rs-line-height-caption-1)) / 2 + ); --rs-button-p-h: var(--rs-unit-x2); --rs-button-gap: var(--rs-unit-x1-5); --rs-button-icon-align: var(--rs-unit-x0-5); diff --git a/packages/reshaped/src/components/MenuItem/MenuItem.module.css b/packages/reshaped/src/components/MenuItem/MenuItem.module.css index dccc37c3..2e000d2c 100644 --- a/packages/reshaped/src/components/MenuItem/MenuItem.module.css +++ b/packages/reshaped/src/components/MenuItem/MenuItem.module.css @@ -32,8 +32,10 @@ button.root { @responsive .--size { @value small { - /* Padding grows by the line height difference to keep the size the same as with body-2 text */ - --rs-p-v: calc(var(--rs-unit-x1) + var(--rs-caption-1-line-height-offset)); + /* Padding absorbs the caption-1 line height difference to keep the size it had with body-2 text */ + --rs-p-v: calc( + var(--rs-unit-x1) + (var(--rs-line-height-body-2) - var(--rs-line-height-caption-1)) / 2 + ); --rs-p-h: var(--rs-unit-x1-5); --rs-menu-item-radius: var(--rs-radius-small); diff --git a/packages/reshaped/src/components/Reshaped/Reshaped.css b/packages/reshaped/src/components/Reshaped/Reshaped.css index 636818b1..4db62359 100644 --- a/packages/reshaped/src/components/Reshaped/Reshaped.css +++ b/packages/reshaped/src/components/Reshaped/Reshaped.css @@ -4,15 +4,6 @@ --rs-outline: var(--rs-outline-width) solid var(--rs-color-border-primary); --rs-outline-shadow: 0 0 0 var(--rs-outline-width) var(--rs-color-border-primary) inset; --rs-radius-circular: 9999px; - - /* - Small components render caption-1 text while keeping the height they had with body-2 text. - Their vertical padding grows by this value on each side to compensate for the line height difference. - Themes where both line heights match resolve it to 0 and stay unaffected. - */ - --rs-caption-1-line-height-offset: calc( - (var(--rs-line-height-body-2) - var(--rs-line-height-caption-1)) / 2 - ); } [data-rs-theme] body, diff --git a/packages/reshaped/src/components/Select/Select.module.css b/packages/reshaped/src/components/Select/Select.module.css index bacf38a1..0750f7c9 100644 --- a/packages/reshaped/src/components/Select/Select.module.css +++ b/packages/reshaped/src/components/Select/Select.module.css @@ -108,8 +108,10 @@ --rs-select-chevron-size: var(--rs-unit-x4); --rs-select-radius: var(--rs-radius-small); - /* Padding grows by the line height difference to keep the size the same as with body-2 text */ - --rs-select-p-v: calc(var(--rs-unit-x1) + var(--rs-caption-1-line-height-offset)); + /* Padding absorbs the caption-1 line height difference to keep the size it had with body-2 text */ + --rs-select-p-v: calc( + var(--rs-unit-x1) + (var(--rs-line-height-body-2) - var(--rs-line-height-caption-1)) / 2 + ); --rs-select-p-h: var(--rs-unit-x2); --rs-select-font-size: var(--rs-font-size-caption-1); --rs-select-line-height: var(--rs-line-height-caption-1); diff --git a/packages/reshaped/src/components/Tabs/Tabs.module.css b/packages/reshaped/src/components/Tabs/Tabs.module.css index f8b1f62e..41eacb7c 100644 --- a/packages/reshaped/src/components/Tabs/Tabs.module.css +++ b/packages/reshaped/src/components/Tabs/Tabs.module.css @@ -355,8 +355,10 @@ } .--size-small { - /* Padding grows by the line height difference to keep the size the same as with body-2 text */ - --rs-tabs-item-p-v: calc(var(--rs-unit-x1) + var(--rs-caption-1-line-height-offset)); + /* Padding absorbs the caption-1 line height difference to keep the size it had with body-2 text */ + --rs-tabs-item-p-v: calc( + var(--rs-unit-x1) + (var(--rs-line-height-body-2) - var(--rs-line-height-caption-1)) / 2 + ); --rs-tabs-item-p-h: var(--rs-unit-x2); --rs-tabs-icon-gap: var(--rs-unit-x1-5); --rs-tabs-radius: var(--rs-radius-small); diff --git a/packages/reshaped/src/components/TextField/TextField.module.css b/packages/reshaped/src/components/TextField/TextField.module.css index b620cf9f..181675b9 100644 --- a/packages/reshaped/src/components/TextField/TextField.module.css +++ b/packages/reshaped/src/components/TextField/TextField.module.css @@ -195,8 +195,10 @@ --rs-text-field-gap: var(--rs-unit-x1-5); --rs-text-field-radius: var(--rs-radius-small); - /* Padding grows by the line height difference to keep the size the same as with body-2 text */ - --rs-text-field-p-v: calc(var(--rs-unit-x1) + var(--rs-caption-1-line-height-offset)); + /* Padding absorbs the caption-1 line height difference to keep the size it had with body-2 text */ + --rs-text-field-p-v: calc( + var(--rs-unit-x1) + (var(--rs-line-height-body-2) - var(--rs-line-height-caption-1)) / 2 + ); --rs-text-field-p-h: var(--rs-unit-x2); --rs-text-field-icon-align: var(--rs-unit-x0-5); --rs-text-field-font-size: var(--rs-font-size-caption-1);