Skip to content

feat: Add size to various components, deprecating compact - #809

Open
cb-ekuersch wants to merge 22 commits into
masterfrom
tshirts2
Open

feat: Add size to various components, deprecating compact#809
cb-ekuersch wants to merge 22 commits into
masterfrom
tshirts2

Conversation

@cb-ekuersch

@cb-ekuersch cb-ekuersch commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

What changed? Why?

Summary

Rolls out the cross-platform t-shirt size prop across CDS components, deprecating the legacy compact boolean in favor of the new sizing API. Each component's per-size styles are derived from its Figma component set and applied consistently across web and mobile. Backward compatibility is preserved throughout: compact keeps working exactly as before (size wins when both are set), no fixed heights are introduced (except Slide Button, which is inherently fixed-height by design sign-off), and no public exports are renamed or dropped. compact is deprecated with @deprecationExpectedRemoval v10.

Component(s) Issue
Button CDS-2168
Icon Button CDS-2445
Search Input CDS-2450
Select (alpha) CDS-2449
Slide Button CDS-2448
Date Picker (+ DateInput) CDS-2451
Input Chip · Select Chip · TabbedChips CDS-2223 · CDS-2224 · CDS-2173

Linear Issues

Next steps

Intentionally deferred from this PR to keep scope focused on the size API + component/stories work:

  • Docs site (apps/docs): Update component examples to document the new size prop and remove/replace deprecated compact examples for each rolled-out component.
  • Figma Code Connect (__figma__ templates): Refresh Code Connect mappings to include the new size variant property for each rolled-out component.

UI changes

iOS Old iOS New
old screenshot new screenshot
Android Old Android New
old screenshot new screenshot
Web Old Web New
old screenshot new screenshot

Testing

How has it been tested?

  • Unit tests
  • Interaction tests
  • Pseudo State tests
  • Manual - Web
  • Manual - Android (Emulator / Device)
  • Manual - iOS (Emulator / Device)

Testing instructions

Illustrations/Icons Checklist

Required if this PR changes files under packages/illustrations/** or packages/icons/**

  • verified visreg changes with Terran (include link to visreg run/approval)
  • all illustration/icons names have been reviewed by Dom and/or Terran

Change management

type=routine
risk=low
impact=sev5

automerge=false

@cb-heimdall

Copy link
Copy Markdown
Collaborator

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 1
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1
CODEOWNERS 🟡 See below

🟡 CODEOWNERS

Code Owner Status Calculation
ui-systems-eng-team 🟡 0/1
Denominator calculation
Additional CODEOWNERS Requirement
Show calculation
Sum 0
0
From CODEOWNERS 1
Sum 1

@cb-ekuersch cb-ekuersch changed the title Tshirts2 feat: Add size to various components, deprecating compact Jul 27, 2026
@cb-ekuersch
cb-ekuersch marked this pull request as ready for review July 27, 2026 23:19
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

cb-ekuersch and others added 17 commits July 28, 2026 18:42
Add cross-platform `size` (xs/s/m/l, default l) via a local size-config map;
deprecate `compact` in favor of `size` (size wins; compact-only maps to s).

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Add xs/s/m/l size prop (web + mobile), deprecate compact, preserving today's geometry.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Add size prop (s/m/l, default l) deprecating compact via a per-size config map.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Add a size prop (xs | s, default s) to the shared Chip base and deprecate compact, mapping it to size="xs" across web, mobile, and the common media-chip spacing helper.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Forward size (xs|s, default s) through to the base Chip and deprecate compact in favor of size="xs".

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Thread a size prop (xs | s, default s) through to tab chips and deprecate compact.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Add size ('s'|'m'|'l', default 'l') driving vertical density on web and mobile TextInput; deprecate compact in favor of size="s".

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Thread size through to TextInput, deprecate compact (maps to size s), and drop the fixed-height lever.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Add a minimal size (s|m|l) prop to alpha Select on web and mobile, deprecating compact, driving only the field vertical padding on the existing inputStackStyles.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Thread a size ('s'|'m'|'l', default 'l') prop through DateInput and DatePicker to TextInput and deprecate compact in favor of size="s".

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Add SizeComposition stories (web + mobile) demonstrating the t-shirt `size`
prop across inputs, chips, and buttons together (brought back from the
original rollout branch).

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Refinements on top of the t-shirt size rollout for the input family:

- Select: multi-select value chips now use the compact xs size at every size, with
  per-size vertical padding tuned so single- and multi-select heights match (42/50/58).
- Inside labels are decoupled from size: horizontal in the start slot at s/m, and
  vertically stacked only at l (single and multi), all landing on the same field
  height an outside label produces.
- Mobile: floor the native input to `padding + line-height token` via minHeight so
  fields reach their intended height instead of the font's shorter natural metric,
  and vertically center single-line text in the extra space (multiline excluded).

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
- Align mobile SelectChip control-prop spread order with web (chip-level
  props win; drop the unnecessary compact strip)
- Rename Select label-placement flags to mirror TextInput semantics
  (insideVerticalLabel / insideHorizontalLabel / wantsInsideLabel /
  isCompactLabel) and multiSelectValueChipSize, web + mobile
- Limit per-size padding-value unit tests to TextInput and Select (alpha);
  drop them from SearchInput, Chip, MediaChip, and SelectChip (both packages)
- Group simple per-size stories into a single "Sizes" example for TextInput,
  SearchInput, Button, and SlideButton (web + mobile)

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
…mpact

Combobox composes Select, so it already inherits `size` and the deprecated
`compact` via SelectBaseProps and threads them through to the underlying
select control on both platforms. Lock this in and demonstrate it:

- Add a grouped "Sizes" story (s/m/l + deprecated compact) to the web and
  mobile Combobox stories
- Add a wiring test verifying `size` and `compact` reach the select control
  (web + mobile) — no padding-value assertions

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Comment thread packages/common/src/chips/getMediaChipSpacingProps.ts
Comment thread packages/common/src/chips/getMediaChipSpacingProps.ts

export type SlideButtonHandleCheckedProps = Pick<SlideButtonBaseProps, 'variant' | 'compact'> & {
export type SlideButtonHandleCheckedProps = Pick<SlideButtonBaseProps, 'variant'> & {
size: SlideButtonSize;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is it safe to make this prop required?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

probably not since someone may be using a custom slide handle component - if this is the case, we should make it optional for now and just render the default size if undefeind

xs: { padding: 1, iconSize: 's', borderRadius: 1000, feedback: 'light' },
s: { padding: 1.5, iconSize: 's', borderRadius: 1000, feedback: 'light' },
m: { padding: 1.5, iconSize: 'm', borderRadius: 1000, feedback: 'normal' },
l: { padding: 2, iconSize: 'm', borderRadius: 1000, feedback: 'normal' },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: should we keep borderRadius out since it is 1000 all the way

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes, remove borderRadius and apply prop directly in render for all conditions

Comment thread packages/web/src/alpha/select/DefaultSelectControl.tsx
import { isSelectOptionGroup } from './Select';
import { defaultSelectSize } from './types';

const selectSizeVerticalSpace: Record<SelectSize, 1 | 1.5 | 2> = { s: 1, m: 1.5, l: 2 };

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

use theme var space type

font={labelFont}
// A horizontal inline label shares its row with the value, so keep it to a single line —
// otherwise a long label wraps and stretches the field past its size.
numberOfLines={insideHorizontalLabel ? 1 : undefined}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

do we want to limit to one line for vetically stacked inside label - it looks like tihs node is used for that case as well

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

for consistency it may be nice to just force a single line label for any inside label regardless if its stacked vertically or horizontally

paddingTop: compact || labelVariant === 'inside' ? theme.space[1] : theme.space[2],
paddingBottom: compact || labelVariant === 'inside' ? theme.space[1] : theme.space[2],
const inputStackStyles: StyleProp<ViewStyle> = useMemo(() => {
let verticalSpace: 0.25 | 0.5 | 0.75 | 1 | 1.5 | 2;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

use theme var space stype


export type SlideButtonHandleCheckedProps = Pick<SlideButtonBaseProps, 'variant' | 'compact'> & {
export type SlideButtonHandleCheckedProps = Pick<SlideButtonBaseProps, 'variant'> & {
size: SlideButtonSize;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

probably not since someone may be using a custom slide handle component - if this is the case, we should make it optional for now and just render the default size if undefeind

xs: { padding: 1, iconSize: 's', borderRadius: 1000, feedback: 'light' },
s: { padding: 1.5, iconSize: 's', borderRadius: 1000, feedback: 'light' },
m: { padding: 1.5, iconSize: 'm', borderRadius: 1000, feedback: 'normal' },
l: { padding: 2, iconSize: 'm', borderRadius: 1000, feedback: 'normal' },

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes, remove borderRadius and apply prop directly in render for all conditions

Comment thread packages/web/src/alpha/select/DefaultSelectControl.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants