Skip to content

feat: improve Input and Field components with dynamic sizing#234

Open
leahwangcloudflare wants to merge 3 commits intocloudflare:mainfrom
leahwangcloudflare:leah/input-field-improvements
Open

feat: improve Input and Field components with dynamic sizing#234
leahwangcloudflare wants to merge 3 commits intocloudflare:mainfrom
leahwangcloudflare:leah/input-field-improvements

Conversation

@leahwangcloudflare
Copy link

  • Add size prop to Field component (xs, sm, base, lg)
  • Dynamic gap spacing: lg uses gap-2, others use gap-1
  • Dynamic label text size: xs=text-xs, sm=text-sm, base/lg=text-base
  • Restructure label layout to show Optional text on right side
  • Input passes size prop to Field for consistent sizing
  • Update base input gap from gap-1.5 to gap-1

- Add size prop to Field component (xs, sm, base, lg)
- Dynamic gap spacing: lg uses gap-2, others use gap-1
- Dynamic label text size: xs=text-xs, sm=text-sm, base/lg=text-base
- Restructure label layout to show Optional text on right side
- Input passes size prop to Field for consistent sizing
- Update base input gap from gap-1.5 to gap-1
@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 16, 2026

npm i https://pkg.pr.new/@cloudflare/kumo@234

commit: 60aef7a

@github-actions
Copy link
Contributor

github-actions bot commented Mar 16, 2026

Docs Preview

View docs preview

Commit: 60aef7a

@github-actions
Copy link
Contributor

github-actions bot commented Mar 16, 2026

Visual Regression Report

10 screenshot(s) with visual changes:

Input / With Label and Description

110,316 px (2.68%) changed

Before After Diff
Before After Diff

Input / With Error (String)

109,733 px (2.67%) changed

Before After Diff
Before After Diff

Input / With Error (Validation Object)

103,676 px (2.52%) changed

Before After Diff
Before After Diff

Input / Input Sizes

109,990 px (2.67%) changed

Before After Diff
Before After Diff

Input / Disabled

115,081 px (2.8%) changed

Before After Diff
Before After Diff

Input / Optional Field

112,293 px (2.73%) changed

Before After Diff
Before After Diff

Input / With Label Tooltip

112,293 px (2.73%) changed

Before After Diff
Before After Diff

Input / ReactNode Label

112,293 px (2.73%) changed

Before After Diff
Before After Diff

Input / Bare Input (No Label)

106,914 px (2.6%) changed

Before After Diff
Before After Diff

Input / Input Types

113,812 px (2.76%) changed

Before After Diff
Before After Diff

Generated by Kumo Visual Regression

Copy link
Collaborator

@mattrothenberg mattrothenberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, Leah! The dynamic sizing feature is a solid improvement — having the Field automatically match the Input size makes the API much more intuitive.

A few suggestions:


Gap sizing (field.tsx:31-32)

Instead of the ternary chain, an object lookup is clearer and easier to extend if more sizes are added later:

const gapBySize = {
  xs: "gap-1",
  sm: "gap-1", 
  base: "gap-1",
  lg: "gap-2",
} as const;

const gapClass = gapBySize[size];

"Optional" text sizing (field.tsx:152)

The label text scales with size (text-xs, text-sm, text-base), but "Optional" is always text-sm. When size="xs", the label will be smaller than "Optional" which might look a bit off. Could use the same labelTextSize variable here for consistency.


Layout change for "(optional)"

Just flagging — this moves "(optional)" from inline (right after the label text) to right-aligned. That's a visual change for existing consumers. Totally fine if that's the intended design direction, just wanted to confirm it's intentional!


CodeBlock examples cleared

The CodeBlock examples array got emptied in the registry JSON — was that intentional or maybe an artifact from codegen?


Overall this is in good shape!

@mattrothenberg
Copy link
Collaborator

A few more small things I noticed:


Empty string in Label (field.tsx around line 147-150)

<Label tooltip={labelTooltip} asContent>
  {""}
</Label>

This works but is a bit unusual — you're passing an empty string just to get the tooltip icon. Consider inlining the tooltip directly:

{labelTooltip && (
  <Tooltip content={labelTooltip} asChild>
    <Button
      variant="ghost"
      size="xs"
      shape="square"
      aria-label="More information"
    >
      <Info className="size-4" />
    </Button>
  </Tooltip>
)}

Input gap change (input.tsx line 22)

Just curious — what motivated the change from gap-1.5 to gap-1 for the base size? Totally fine if intentional, just want to understand the reasoning!


Bonus: Meter example fix

Nice catch fixing from-green-500from-kumo-success in the Meter example — that aligns with the semantic token conventions 👍

- Refactor gap spacing to use object lookup instead of ternary chain
- Make Optional text scale with input size for consistency
- Replace Label component with direct Tooltip implementation to avoid empty string children
- Update base input gap from gap-1 to gap-1.5 for better spacing
@leahwangcloudflare
Copy link
Author

@mattrothenberg hey Matt, thank you so much for taking a look! I've made the changes based on your suggestions.

In terms of the input gap change:
Original state:
Field (vertical): gap-2 (8px) for all sizes
Input (horizontal): gap-1.5 (6px) for base size

Initially I changed base to gap-1 to match conventional spacing (4px or 8px instead of 6px)
But I actually prefer the slightly larger 6px spacing, it gives better breathing room without feeling too loose.

In terms of the Optional text
Having the optional field show on the right is intentional. It looks cleaner and matches how it looks on Workers creation page. I just made the "Optional" text scale with the input size. Thanks for catching it!!

@leahwangcloudflare
Copy link
Author

CodeBlock examples cleared: It was from codegen.. Should I avoid including it in the commit next time?

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.

2 participants