diff --git a/.changeset/standardize-small-controls.md b/.changeset/standardize-small-controls.md
new file mode 100644
index 0000000000..1ace199d25
--- /dev/null
+++ b/.changeset/standardize-small-controls.md
@@ -0,0 +1,5 @@
+---
+"@cloudflare/kumo": patch
+---
+
+Standardize small interactive controls at 30px high with the base text size, including medium corner radii for small toolbars, and restore `Toolbar size="sm"` as a supported API while keeping `xs` and `lg` deprecated.
diff --git a/packages/kumo-docs-astro/src/components/demos/ToolbarDemo.tsx b/packages/kumo-docs-astro/src/components/demos/ToolbarDemo.tsx
index d21fe4c28e..8d69fe6cff 100644
--- a/packages/kumo-docs-astro/src/components/demos/ToolbarDemo.tsx
+++ b/packages/kumo-docs-astro/src/components/demos/ToolbarDemo.tsx
@@ -23,11 +23,11 @@ export function ToolbarDemo() {
);
}
-/** @deprecated Toolbar size customization remains for compatibility. */
+/** Supported compact and default Toolbar sizes. */
export function ToolbarSizesDemo() {
return (
- {(["xs", "sm", "base", "lg"] as const).map((size) => (
+ {(["sm", "base"] as const).map((size) => (
{size}
diff --git a/packages/kumo-docs-astro/src/pages/components/toolbar.mdx b/packages/kumo-docs-astro/src/pages/components/toolbar.mdx
index 60ebe6e3b4..63c6e1dd55 100644
--- a/packages/kumo-docs-astro/src/pages/components/toolbar.mdx
+++ b/packages/kumo-docs-astro/src/pages/components/toolbar.mdx
@@ -78,7 +78,7 @@ export default function Example() {
Toolbar item components intentionally own grouped control presentation:
- Every `Toolbar.*` control uses the `base` size by default.
-- The Toolbar `size` prop remains available for compatibility but is deprecated; omit it for the base size.
+- Set `size="sm"` for a compact 30px-high toolbar with medium corner radii.
- `Toolbar.Button` always renders with quiet toolbar button styling.
- `Toolbar.InputGroup` passes props directly to `InputGroup` with the resolved toolbar size.
- Give Select `render={ }` to compose its trigger into the toolbar.
@@ -133,11 +133,11 @@ inline addon or suffix.
-### Deprecated sizing
+### Sizing
-The `size` prop still supports `xs`, `sm`, `base`, and `lg` for compatibility,
-but it is deprecated and will be removed in a future major release. Omit it to
-use the default `base` size.
+Use `size="sm"` for compact toolbars or omit `size` to use the default `base`
+size. The legacy `xs` and `lg` values are deprecated and remain available only
+for backwards compatibility.
@@ -187,10 +187,10 @@ options instead.
Toolbar controls rendered as one grouped card.
- size Deprecated
+ size
"xs" | "sm" | "base" | "lg"
"base"
- Sets every supported item size. Omit this deprecated prop to use the default base size.
+ Sets every supported item size. Use "sm" for compact toolbars; "xs" and "lg" are deprecated compatibility values.
className
diff --git a/packages/kumo-figma/src/generators/button.ts b/packages/kumo-figma/src/generators/button.ts
index 98a259d1a3..d7e8f9387c 100644
--- a/packages/kumo-figma/src/generators/button.ts
+++ b/packages/kumo-figma/src/generators/button.ts
@@ -168,7 +168,7 @@ export function getButtonParsedShapeStyles(shape: string) {
*
* Source: button.tsx KUMO_BUTTON_VARIANTS.compactSize
* - xs: size-3.5 = 14px
- * - sm: size-6.5 = 26px
+ * - sm: size-7.5 = 30px
* - base: size-9 = 36px
* - lg: size-10 = 40px
*
@@ -179,7 +179,7 @@ export function getCompactSizeMap(): Record {
// Compact size classes from KUMO_BUTTON_VARIANTS.compactSize in button.tsx
const compactSizeClasses: Record = {
xs: "size-3.5",
- sm: "size-6.5",
+ sm: "size-7.5",
base: "size-9",
lg: "size-10",
};
diff --git a/packages/kumo-figma/src/generators/drift-detection.test.ts b/packages/kumo-figma/src/generators/drift-detection.test.ts
index 4875e5fcf7..49a9f908d5 100644
--- a/packages/kumo-figma/src/generators/drift-detection.test.ts
+++ b/packages/kumo-figma/src/generators/drift-detection.test.ts
@@ -404,7 +404,7 @@ describe("Figma Plugin - Registry Sync Validation", () => {
// Expected compact sizes from Button COMPACT_SIZE_MAP (derived from registry)
const expectedSizes: Record = {
xs: 14, // size-3.5 = 3.5 * 4 = 14px
- sm: 26, // size-6.5 = 6.5 * 4 = 26px
+ sm: 30, // size-7.5 = 7.5 * 4 = 30px
base: 36, // size-9 = 9 * 4 = 36px
lg: 40, // size-10 = 10 * 4 = 40px
};
@@ -817,7 +817,7 @@ describe("Figma Plugin - Phase 6 Magic Number Enforcement", () => {
content,
);
- // Check for explicit hardcoded COMPACT_SIZE_MAP definition: { xs: 14, sm: 26, base: 36, lg: 40 }
+ // Check for explicit hardcoded COMPACT_SIZE_MAP definition: { xs: 14, sm: 30, base: 36, lg: 40 }
// This is the most drift-prone pattern - explicit recreation of button compact sizes
const hasHardcodedCompactMap =
/(?:const|let|var)\s+COMPACT_SIZE_MAP[^=]*=\s*\{[^}]*xs:\s*14[^}]*sm:\s*26/.test(
@@ -841,7 +841,7 @@ describe("Figma Plugin - Phase 6 Magic Number Enforcement", () => {
` - const COMPACT_SIZE_MAP = FALLBACK_VALUES.buttonCompactSize;\n` +
` Or reference values directly:\n` +
` - FALLBACK_VALUES.buttonCompactSize.xs (14px)\n` +
- ` - FALLBACK_VALUES.buttonCompactSize.sm (26px)\n` +
+ ` - FALLBACK_VALUES.buttonCompactSize.sm (30px)\n` +
` - FALLBACK_VALUES.buttonCompactSize.base (36px)\n` +
` - FALLBACK_VALUES.buttonCompactSize.lg (40px)\n`,
);
@@ -1223,7 +1223,7 @@ describe("Figma Plugin - CSS Theme Sync Validation", () => {
// Verify expected values
expect(themeData.kumo.buttonCompactSize.xs).toBe(14); // size-3.5 = 14px
- expect(themeData.kumo.buttonCompactSize.sm).toBe(26); // size-6.5 = 26px
+ expect(themeData.kumo.buttonCompactSize.sm).toBe(30); // size-7.5 = 30px
expect(themeData.kumo.buttonCompactSize.base).toBe(36); // size-9 = 36px
expect(themeData.kumo.buttonCompactSize.lg).toBe(40); // size-10 = 40px
});
diff --git a/packages/kumo-figma/src/generators/input.ts b/packages/kumo-figma/src/generators/input.ts
index 7313dcb418..198632c39c 100644
--- a/packages/kumo-figma/src/generators/input.ts
+++ b/packages/kumo-figma/src/generators/input.ts
@@ -85,7 +85,7 @@ function getSizeConfigFromRegistry(size: string) {
{ height: number; paddingX: number; fontSize: number; borderRadius: number }
> = {
xs: { height: 20, paddingX: 6, fontSize: 12, borderRadius: 2 },
- sm: { height: 26, paddingX: 8, fontSize: 12, borderRadius: 6 },
+ sm: { height: 30, paddingX: 8, fontSize: 14, borderRadius: 6 },
base: { height: 36, paddingX: 12, fontSize: 16, borderRadius: 8 },
lg: { height: 40, paddingX: 16, fontSize: 16, borderRadius: 8 },
};
diff --git a/packages/kumo-figma/src/generators/refresh-button.test.ts b/packages/kumo-figma/src/generators/refresh-button.test.ts
index 836d55e7e9..e3f28e40b6 100644
--- a/packages/kumo-figma/src/generators/refresh-button.test.ts
+++ b/packages/kumo-figma/src/generators/refresh-button.test.ts
@@ -176,15 +176,12 @@ describe("RefreshButton Generator - Icon Size Configuration", () => {
lg: 20,
};
- const COMPACT_SIZE_MAP: Record = {
- xs: 14,
- sm: 26,
- base: 36,
- lg: 40,
- };
+ const COMPACT_SIZE_MAP = FALLBACK_VALUES.buttonCompactSize;
for (const size of sizeProp.values) {
- expect(REFRESH_ICON_SIZE[size]).toBeLessThan(COMPACT_SIZE_MAP[size]);
+ expect(REFRESH_ICON_SIZE[size]).toBeLessThan(
+ COMPACT_SIZE_MAP[size as keyof typeof COMPACT_SIZE_MAP],
+ );
}
});
@@ -318,12 +315,7 @@ describe("RefreshButton Generator - Complete Variant Data", () => {
});
it("should have all required configuration maps", () => {
- const COMPACT_SIZE_MAP: Record = {
- xs: 14,
- sm: 26,
- base: 36,
- lg: 40,
- };
+ const COMPACT_SIZE_MAP = FALLBACK_VALUES.buttonCompactSize;
const REFRESH_ICON_SIZE: Record = {
xs: 12,
@@ -337,7 +329,9 @@ describe("RefreshButton Generator - Complete Variant Data", () => {
// Verify all size values have mappings
for (const size of sizeProp.values) {
- expect(COMPACT_SIZE_MAP[size]).toBeDefined();
+ expect(
+ COMPACT_SIZE_MAP[size as keyof typeof COMPACT_SIZE_MAP],
+ ).toBeDefined();
expect(REFRESH_ICON_SIZE[size]).toBeDefined();
}
});
diff --git a/packages/kumo-figma/src/generators/sensitive-input.ts b/packages/kumo-figma/src/generators/sensitive-input.ts
index 568e0a16f6..fa782a0a00 100644
--- a/packages/kumo-figma/src/generators/sensitive-input.ts
+++ b/packages/kumo-figma/src/generators/sensitive-input.ts
@@ -127,9 +127,9 @@ function getSizeConfigFromRegistry(size: string): {
borderRadius: BORDER_RADIUS.xs,
},
sm: {
- height: 26,
+ height: 30,
paddingX: 8,
- fontSize: 12,
+ fontSize: 14,
borderRadius: BORDER_RADIUS.md,
},
base: {
diff --git a/packages/kumo-figma/src/generators/shared.ts b/packages/kumo-figma/src/generators/shared.ts
index 29c0cf52da..0d1be0b5ea 100644
--- a/packages/kumo-figma/src/generators/shared.ts
+++ b/packages/kumo-figma/src/generators/shared.ts
@@ -437,7 +437,7 @@ export const FALLBACK_VALUES = {
buttonCompactSize: {
/** Extra small compact button (size-3.5) */
xs: themeData.computed.buttonCompactSize.xs,
- /** Small compact button (size-6.5) */
+ /** Small compact button (size-7.5) */
sm: themeData.computed.buttonCompactSize.sm,
/** Base compact button (size-9) */
base: themeData.computed.buttonCompactSize.base,
diff --git a/packages/kumo-figma/src/parsers/tailwind-to-figma.ts b/packages/kumo-figma/src/parsers/tailwind-to-figma.ts
index 42d713ed34..70d5f048a1 100644
--- a/packages/kumo-figma/src/parsers/tailwind-to-figma.ts
+++ b/packages/kumo-figma/src/parsers/tailwind-to-figma.ts
@@ -255,7 +255,7 @@ export function parseTailwindClasses(classes: string): ParsedStyles {
continue;
}
- // Height: h-5, h-6.5, h-9, h-10
+ // Height: h-5, h-7.5, h-9, h-10
const heightMatch = cls.match(/^h-(\d+\.?\d*)$/);
if (heightMatch) {
result.height = getOrDefault(
@@ -266,7 +266,7 @@ export function parseTailwindClasses(classes: string): ParsedStyles {
continue;
}
- // Size (width and height): size-3.5, size-6.5, size-9, size-10
+ // Size (width and height): size-3.5, size-7.5, size-9, size-10
const sizeMatch = cls.match(/^size-(\d+\.?\d*)$/);
if (sizeMatch) {
const size = getOrDefault(
diff --git a/packages/kumo/scripts/component-registry/metadata.ts b/packages/kumo/scripts/component-registry/metadata.ts
index c78928eb92..38af7b2fab 100644
--- a/packages/kumo/scripts/component-registry/metadata.ts
+++ b/packages/kumo/scripts/component-registry/metadata.ts
@@ -630,21 +630,21 @@ export const COMPONENT_STYLING_METADATA: Record = {
base: "bg-kumo-control text-kumo-default ring ring-kumo-line",
sizes: {
xs: "h-5 gap-1 rounded-sm px-1.5 text-xs",
- sm: "h-6.5 gap-1 rounded-md px-2 text-xs",
+ sm: "h-7.5 gap-1 rounded-md px-2 text-base",
base: "h-9 gap-1.5 rounded-lg px-3 text-base",
lg: "h-10 gap-2 rounded-lg px-4 text-base",
},
},
sizeVariants: {
sm: {
- height: 26,
- classes: "text-xs",
+ height: 30,
+ classes: "text-base",
buttonSize: "sm",
dimensions: {
paddingX: 8,
gap: 1,
borderRadius: 6,
- fontSize: 12,
+ fontSize: 14,
},
},
base: {
@@ -722,11 +722,11 @@ export const COMPONENT_STYLING_METADATA: Record = {
},
},
sm: {
- height: 26,
- classes: "h-6.5 gap-1 rounded-md px-2 text-xs",
+ height: 30,
+ classes: "h-7.5 gap-1 rounded-md px-2 text-base",
dimensions: {
paddingX: 8,
- fontSize: 12,
+ fontSize: 14,
borderRadius: 6,
},
},
diff --git a/packages/kumo/src/components/autocomplete/autocomplete.tsx b/packages/kumo/src/components/autocomplete/autocomplete.tsx
index c93facbe66..c69dec2550 100644
--- a/packages/kumo/src/components/autocomplete/autocomplete.tsx
+++ b/packages/kumo/src/components/autocomplete/autocomplete.tsx
@@ -26,7 +26,7 @@ export interface KumoAutocompleteVariantsProps {
/**
* Size of the autocomplete input. Matches Input component sizes.
* - `"xs"` — Extra small for compact UIs (h-5 / 20px)
- * - `"sm"` — Small for secondary fields (h-6.5 / 26px)
+ * - `"sm"` — Small for secondary fields (h-7.5 / 30px)
* - `"base"` — Default size (h-9 / 36px)
* - `"lg"` — Large for prominent fields (h-10 / 40px)
* @default "base"
diff --git a/packages/kumo/src/components/banner/banner.test.tsx b/packages/kumo/src/components/banner/banner.test.tsx
index 0faa017a28..30ec66d9b7 100644
--- a/packages/kumo/src/components/banner/banner.test.tsx
+++ b/packages/kumo/src/components/banner/banner.test.tsx
@@ -112,7 +112,7 @@ describe("Banner", () => {
);
const cta = screen.getByTestId("cta");
- expect(cta.className).toContain("h-6.5");
+ expect(cta.className).toContain("h-7.5");
expect(cta.className).toContain("px-2");
expect(cta.getAttribute("aria-label")).toBe("Dismiss");
expect(screen.getByTestId("icon")).toBeTruthy();
@@ -128,9 +128,9 @@ describe("Banner", () => {
);
const cta = screen.getByTestId("cta");
- expect(cta.className).toContain("h-6.5");
+ expect(cta.className).toContain("h-7.5");
expect(cta.className).toContain("px-2");
- expect(cta.className).toContain("text-xs");
+ expect(cta.className).toContain("text-base");
});
it("applies compact spacing for the sm banner size", () => {
@@ -157,7 +157,7 @@ describe("Banner", () => {
);
const cta = screen.getByTestId("cta");
- // Inherits the banner's size => xs (h-5), not the standalone sm default (h-6.5).
+ // Inherits the banner's size => xs (h-5), not the standalone sm default (h-7.5).
expect(cta.className).toContain("h-5");
expect(cta.className).toContain("px-1.5");
});
diff --git a/packages/kumo/src/components/button/button.test.tsx b/packages/kumo/src/components/button/button.test.tsx
index ed2cf490df..d791ad3e29 100644
--- a/packages/kumo/src/components/button/button.test.tsx
+++ b/packages/kumo/src/components/button/button.test.tsx
@@ -66,6 +66,15 @@ describe("Button", () => {
expect(button.classList.contains("select-text")).toBe(false);
});
+ it("uses the standardized small control size", () => {
+ const classes = buttonVariants({ size: "sm" });
+ const compactClasses = buttonVariants({ size: "sm", shape: "square" });
+
+ expect(classes).toContain("h-7.5");
+ expect(classes).toContain("text-base");
+ expect(compactClasses).toContain("size-7.5");
+ });
+
it("forwards ref to the DOM node", () => {
const ref = React.createRef();
render(Click );
diff --git a/packages/kumo/src/components/button/button.tsx b/packages/kumo/src/components/button/button.tsx
index a8e50b53d0..18b26e5768 100644
--- a/packages/kumo/src/components/button/button.tsx
+++ b/packages/kumo/src/components/button/button.tsx
@@ -28,7 +28,7 @@ export const KUMO_BUTTON_VARIANTS = {
description: "Extra small button for compact UIs",
},
sm: {
- classes: "h-6.5 gap-1 rounded-md px-2 text-xs",
+ classes: "h-7.5 gap-1 rounded-md px-2 text-base",
description: "Small button for secondary actions",
},
base: {
@@ -42,7 +42,7 @@ export const KUMO_BUTTON_VARIANTS = {
},
compactSize: {
xs: { classes: "size-3.5" },
- sm: { classes: "size-6.5" },
+ sm: { classes: "size-7.5" },
base: { classes: "size-9" },
lg: { classes: "size-10" },
},
diff --git a/packages/kumo/src/components/clipboard-text/clipboard-text.test.tsx b/packages/kumo/src/components/clipboard-text/clipboard-text.test.tsx
index 7ba08e8c2d..c8a0e0f3b4 100644
--- a/packages/kumo/src/components/clipboard-text/clipboard-text.test.tsx
+++ b/packages/kumo/src/components/clipboard-text/clipboard-text.test.tsx
@@ -46,6 +46,14 @@ describe("ClipboardText", () => {
).toBeTruthy();
});
+ it("uses the standardized small control size", () => {
+ render( );
+ const clipboardText = screen.getByText("sk_live_abc123").parentElement;
+
+ expect(clipboardText?.className).toContain("h-7.5");
+ expect(clipboardText?.className).toContain("text-base");
+ });
+
it("copies text and announces copied state without tooltip", async () => {
render( );
diff --git a/packages/kumo/src/components/clipboard-text/clipboard-text.tsx b/packages/kumo/src/components/clipboard-text/clipboard-text.tsx
index 1ca98539c2..59e496fdb2 100644
--- a/packages/kumo/src/components/clipboard-text/clipboard-text.tsx
+++ b/packages/kumo/src/components/clipboard-text/clipboard-text.tsx
@@ -16,7 +16,7 @@ const COPIED_FEEDBACK_MS = 1500;
export const KUMO_CLIPBOARD_TEXT_VARIANTS = {
size: {
sm: {
- classes: "text-xs",
+ classes: "text-base",
buttonSize: "sm" as const,
description: "Small clipboard text for compact UIs",
},
diff --git a/packages/kumo/src/components/combobox/combobox.tsx b/packages/kumo/src/components/combobox/combobox.tsx
index 2a46ebdaa9..04c023885d 100644
--- a/packages/kumo/src/components/combobox/combobox.tsx
+++ b/packages/kumo/src/components/combobox/combobox.tsx
@@ -55,7 +55,7 @@ export interface KumoComboboxVariantsProps {
/**
* Size of the combobox trigger. Matches Input component sizes.
* - `"xs"` — Extra small for compact UIs (h-5 / 20px)
- * - `"sm"` — Small for secondary fields (h-6.5 / 26px)
+ * - `"sm"` — Small for secondary fields (h-7.5 / 30px)
* - `"base"` — Default size (h-9 / 36px)
* - `"lg"` — Large for prominent fields (h-10 / 40px)
* @default "base"
@@ -544,7 +544,7 @@ function Chip({
// Map size to min-height class for TriggerMultipleWithInput
const sizeToMinHeight: Record = {
xs: "min-h-5",
- sm: "min-h-6.5",
+ sm: "min-h-7.5",
base: "min-h-9",
lg: "min-h-10",
};
diff --git a/packages/kumo/src/components/input-group/context.ts b/packages/kumo/src/components/input-group/context.ts
index 8612854f71..4de259f1d7 100644
--- a/packages/kumo/src/components/input-group/context.ts
+++ b/packages/kumo/src/components/input-group/context.ts
@@ -67,7 +67,7 @@ export const INPUT_GROUP_SIZE: Record = {
addonButtonOuterStart: "pl-1",
addonButtonOuterEnd: "pr-1",
suffixPad: "pr-2",
- fontSize: "text-xs",
+ fontSize: "text-base",
iconSize: 13,
},
base: {
diff --git a/packages/kumo/src/components/input-group/input-group.test.tsx b/packages/kumo/src/components/input-group/input-group.test.tsx
index c40aa4f16f..702390cc33 100644
--- a/packages/kumo/src/components/input-group/input-group.test.tsx
+++ b/packages/kumo/src/components/input-group/input-group.test.tsx
@@ -3,7 +3,7 @@ import type { Icon, IconProps } from "@phosphor-icons/react";
import { describe, expect, it, vi } from "vite-plus/test";
import { fireEvent, render, screen, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
-import { InputGroup } from "./input-group";
+import { InputGroup, KUMO_INPUT_GROUP_VARIANTS } from "./input-group";
import { INPUT_GROUP_SIZE, detectFocusMode } from "./context";
import type { KumoInputSize } from "../input/input";
@@ -322,6 +322,12 @@ describe("InputGroup", () => {
});
describe("size variants", () => {
+ it("uses the standardized small control size", () => {
+ expect(KUMO_INPUT_GROUP_VARIANTS.size.sm.classes).toContain("h-7.5");
+ expect(KUMO_INPUT_GROUP_VARIANTS.size.sm.classes).toContain("text-base");
+ expect(INPUT_GROUP_SIZE.sm.fontSize).toBe("text-base");
+ });
+
it("applies size to input", () => {
const { rerender } = render(
diff --git a/packages/kumo/src/components/input-group/input-group.tsx b/packages/kumo/src/components/input-group/input-group.tsx
index 8471897c2d..cee462bad5 100644
--- a/packages/kumo/src/components/input-group/input-group.tsx
+++ b/packages/kumo/src/components/input-group/input-group.tsx
@@ -33,7 +33,7 @@ export const KUMO_INPUT_GROUP_VARIANTS = {
description: "Extra small size.",
},
sm: {
- classes: "h-7 text-xs",
+ classes: "h-7.5 text-base",
description: "Small size.",
},
base: {
diff --git a/packages/kumo/src/components/input/input.test.tsx b/packages/kumo/src/components/input/input.test.tsx
index 0662b6cd5d..6383cba4db 100644
--- a/packages/kumo/src/components/input/input.test.tsx
+++ b/packages/kumo/src/components/input/input.test.tsx
@@ -69,7 +69,10 @@ describe("Input", () => {
it("renders with size 'sm'", () => {
render( );
- expect(screen.getByRole("textbox").className).toContain("h-6.5");
+ const input = screen.getByRole("textbox");
+
+ expect(input.className).toContain("h-7.5");
+ expect(input.className).toContain("text-base");
});
it("renders with size 'lg'", () => {
diff --git a/packages/kumo/src/components/input/input.tsx b/packages/kumo/src/components/input/input.tsx
index 9d4cf52acf..627473320d 100644
--- a/packages/kumo/src/components/input/input.tsx
+++ b/packages/kumo/src/components/input/input.tsx
@@ -20,7 +20,7 @@ export const KUMO_INPUT_VARIANTS = {
description: "Extra small input for compact UIs",
},
sm: {
- classes: "h-6.5 gap-1 rounded-md px-2 text-xs",
+ classes: "h-7.5 gap-1 rounded-md px-2 text-base",
description: "Small input for secondary fields",
},
base: {
@@ -52,7 +52,7 @@ export const KUMO_INPUT_DEFAULT_VARIANTS = {
export const KUMO_INPUT_STYLING = {
dimensions: {
xs: { height: 20, paddingX: 6, fontSize: 12, borderRadius: 2, width: 160 },
- sm: { height: 26, paddingX: 8, fontSize: 12, borderRadius: 6, width: 200 },
+ sm: { height: 30, paddingX: 8, fontSize: 14, borderRadius: 6, width: 200 },
base: {
height: 36,
paddingX: 12,
diff --git a/packages/kumo/src/components/select/select.tsx b/packages/kumo/src/components/select/select.tsx
index 1291cb7fc7..b8d165dc42 100644
--- a/packages/kumo/src/components/select/select.tsx
+++ b/packages/kumo/src/components/select/select.tsx
@@ -67,7 +67,7 @@ export interface KumoSelectVariantsProps {
/**
* Size of the select trigger. Matches Input component sizes.
* - `"xs"` — Extra small for compact UIs (h-5 / 20px)
- * - `"sm"` — Small for secondary fields (h-6.5 / 26px)
+ * - `"sm"` — Small for secondary fields (h-7.5 / 30px)
* - `"base"` — Default size (h-9 / 36px)
* - `"lg"` — Large for prominent fields (h-10 / 40px)
* @default "base"
diff --git a/packages/kumo/src/components/tabs/tabs.test.tsx b/packages/kumo/src/components/tabs/tabs.test.tsx
index 27f72c5326..1490a3976d 100644
--- a/packages/kumo/src/components/tabs/tabs.test.tsx
+++ b/packages/kumo/src/components/tabs/tabs.test.tsx
@@ -19,6 +19,15 @@ const extraTabs = [
];
describe("Tabs", () => {
+ it("uses the standardized small control size", () => {
+ render( );
+
+ expect(screen.getByRole("tablist").className).toContain("h-7.5");
+ expect(screen.getByRole("tab", { name: "Overview" }).className).toContain(
+ "text-base",
+ );
+ });
+
it("forwards nativeButton=false for link-rendered tabs", () => {
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
diff --git a/packages/kumo/src/components/tabs/tabs.tsx b/packages/kumo/src/components/tabs/tabs.tsx
index f76480d7eb..04560f301a 100644
--- a/packages/kumo/src/components/tabs/tabs.tsx
+++ b/packages/kumo/src/components/tabs/tabs.tsx
@@ -71,7 +71,7 @@ export interface KumoTabsVariantsProps {
/**
* Tab size.
* - `"base"` — Default size (h-9, text-base)
- * - `"sm"` — Compact size (h-6.5, text-xs) — matches Input size="sm"
+ * - `"sm"` — Compact size (h-7.5, text-base) — matches Input size="sm"
* @default "base"
*/
size?: (typeof KUMO_TABS_VARIANTS.size)[number];
@@ -208,7 +208,7 @@ export function Tabs({
)}
@@ -222,10 +222,9 @@ export function Tabs({
className={cn(
"kumo-tabs-list relative flex min-w-0 shrink scroll-px-(--scroll-fade-width) items-stretch overflow-x-auto overflow-y-hidden [--scroll-fade-width:3rem]",
isSegmented && "rounded-lg bg-kumo-recessed px-0.5",
- isSegmented && (isSm ? "h-6.5 rounded-md" : "h-9"),
+ isSegmented && (isSm ? "h-7.5 rounded-md" : "h-9"),
isOverflowing && "cursor-grab active:cursor-grabbing",
- isUnderline && "gap-4 border-b border-kumo-hairline pb-2",
- isUnderline && (isSm ? "h-6.5" : "h-7.5"),
+ isUnderline && "h-7.5 gap-4 border-b border-kumo-hairline pb-2",
listClassName,
)}
>
@@ -245,11 +244,10 @@ export function Tabs({
});
}}
className={cn(
- "relative z-2 flex items-center rounded bg-transparent whitespace-nowrap focus:ring-kumo-focus/50 focus:outline-none focus-visible:ring-2 focus-visible:ring-kumo-brand",
+ "relative z-2 flex items-center rounded bg-transparent text-base whitespace-nowrap focus:ring-kumo-focus/50 focus:outline-none focus-visible:ring-2 focus-visible:ring-kumo-brand",
isOverflowing
? "cursor-grab active:cursor-grabbing"
: "cursor-pointer",
- isSm ? "text-xs" : "text-base",
isSegmented &&
"my-0.5 text-kumo-subtle hover:text-kumo-default focus-visible:ring-inset aria-selected:text-kumo-default",
isSegmented && (isSm ? "rounded-sm px-2" : "rounded-md px-2.5"),
diff --git a/packages/kumo/src/components/toolbar/toolbar.tsx b/packages/kumo/src/components/toolbar/toolbar.tsx
index 64fe651a57..c24645c6f6 100644
--- a/packages/kumo/src/components/toolbar/toolbar.tsx
+++ b/packages/kumo/src/components/toolbar/toolbar.tsx
@@ -11,42 +11,49 @@ import { Button as KumoButton, type ButtonProps } from "../button/button";
import { Input as KumoInput, type InputProps } from "../input/input";
import { InputGroup } from "../input-group/input-group";
-/** @deprecated Toolbar size customization is deprecated. Omit `size` to use the default base size. */
+/** Toolbar size variant definitions. */
export const KUMO_TOOLBAR_VARIANTS = {
size: {
+ /** @deprecated Use `"sm"` for compact toolbars. */
xs: {
classes: "text-xs",
- description: "Extra small toolbar for compact UIs",
+ description: "Deprecated extra small toolbar size",
},
sm: {
- classes: "text-xs",
+ classes: "rounded-md text-base",
description: "Small toolbar for secondary controls",
},
base: {
classes: "text-base",
description: "Default toolbar size",
},
+ /** @deprecated Use `"base"` for the default toolbar size. */
lg: {
classes: "text-base",
- description: "Large toolbar for prominent controls",
+ description: "Deprecated large toolbar size",
},
},
} as const;
-/** @deprecated Toolbar size customization is deprecated. Omit `size` to use the default base size. */
+/** Default Toolbar variants. */
export const KUMO_TOOLBAR_DEFAULT_VARIANTS = {
size: "base",
} as const;
-/** @deprecated Toolbar size customization is deprecated. Omit `size` to use the default base size. */
+/**
+ * Toolbar size. `"sm"` and `"base"` are supported; `"xs"` and `"lg"` are
+ * deprecated compatibility values.
+ */
export type ToolbarSize = keyof typeof KUMO_TOOLBAR_VARIANTS.size;
export interface ToolbarProps extends Omit {
/** Toolbar controls rendered as one grouped card. */
children: React.ReactNode;
/**
- * Locks every toolbar item to this size.
- * @deprecated Omit this prop to use the default base size. Toolbar size customization will be removed in a future major release.
+ * Locks every toolbar item to this size. Use `"sm"` for compact toolbars or
+ * `"base"` for the default size. `"xs"` and `"lg"` are deprecated and
+ * remain available only for backwards compatibility.
+ * @default "base"
*/
size?: ToolbarSize;
}
@@ -105,7 +112,7 @@ const Root = React.forwardRef(
data-kumo-component="Toolbar"
className={cn(
"inline-flex w-fit items-stretch rounded-lg bg-kumo-control shadow-xs ring ring-kumo-line",
- "[&>*:first-child]:rounded-l-lg [&>*:not([aria-hidden='true']):not([type='hidden']):not(:has(~_:not([aria-hidden='true']):not([type='hidden'])))]:rounded-r-lg",
+ "[&>*:first-child]:rounded-l-[inherit] [&>*:not([aria-hidden='true']):not([type='hidden']):not(:has(~_:not([aria-hidden='true']):not([type='hidden'])))]:rounded-r-[inherit]",
"[&>*_[data-kumo-toolbar-input]:focus]:rounded-[inherit]",
"[&>*:not([aria-hidden='true']):not(:first-child)]:border-l [&>*:not([aria-hidden='true']):not(:first-child)]:border-kumo-line",
KUMO_TOOLBAR_VARIANTS.size[size].classes,