Skip to content

Commit 2682265

Browse files
pawelgrimmclaude
andcommitted
refactor: rename FieldChromeContainer to OutlinedControlContainer; tighten ControlPresentation type
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d06b923 commit 2682265

5 files changed

Lines changed: 100 additions & 125 deletions

src/control-presentation/control-presentation.stories.tsx

Lines changed: 67 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from 'react'
22

3+
import { Box } from '../box'
34
import { selectWithNone } from '../utils/storybook-helper'
45

56
import { ControlActionButton } from './control-action-button'
@@ -38,20 +39,21 @@ export function PlaygroundStory({
3839
}: PlaygroundArgs) {
3940
return (
4041
<section className="story playground">
41-
<ControlPresentation
42-
maxWidth={maxWidth}
43-
startSlot={startSlot ? <InfoIcon /> : undefined}
44-
endSlot={endSlot ? <ChevronDownIcon /> : undefined}
45-
>
46-
<input
47-
aria-label="Demo input"
48-
placeholder={placeholder}
49-
readOnly={readOnly}
50-
disabled={disabled}
51-
aria-invalid={invalid || undefined}
52-
defaultValue={defaultValue}
53-
/>
54-
</ControlPresentation>
42+
<Box maxWidth={maxWidth}>
43+
<ControlPresentation
44+
startSlot={startSlot ? <InfoIcon /> : undefined}
45+
endSlot={endSlot ? <ChevronDownIcon /> : undefined}
46+
>
47+
<input
48+
aria-label="Demo input"
49+
placeholder={placeholder}
50+
readOnly={readOnly}
51+
disabled={disabled}
52+
aria-invalid={invalid || undefined}
53+
defaultValue={defaultValue}
54+
/>
55+
</ControlPresentation>
56+
</Box>
5557
</section>
5658
)
5759
}
@@ -83,13 +85,11 @@ PlaygroundStory.parameters = {
8385
export function PlaceholderStory() {
8486
return (
8587
<section className="story">
86-
<ControlPresentation
87-
maxWidth="small"
88-
startSlot={<InfoIcon />}
89-
endSlot={<ChevronDownIcon />}
90-
>
91-
<input aria-label="Placeholder" placeholder="Select a value" />
92-
</ControlPresentation>
88+
<Box maxWidth="small">
89+
<ControlPresentation startSlot={<InfoIcon />} endSlot={<ChevronDownIcon />}>
90+
<input aria-label="Placeholder" placeholder="Select a value" />
91+
</ControlPresentation>
92+
</Box>
9393
</section>
9494
)
9595
}
@@ -102,13 +102,11 @@ PlaceholderStory.parameters = {
102102
export function WithValueStory() {
103103
return (
104104
<section className="story">
105-
<ControlPresentation
106-
maxWidth="small"
107-
startSlot={<InfoIcon />}
108-
endSlot={<ChevronDownIcon />}
109-
>
110-
<input aria-label="With value" defaultValue="Sample value" />
111-
</ControlPresentation>
105+
<Box maxWidth="small">
106+
<ControlPresentation startSlot={<InfoIcon />} endSlot={<ChevronDownIcon />}>
107+
<input aria-label="With value" defaultValue="Sample value" />
108+
</ControlPresentation>
109+
</Box>
112110
</section>
113111
)
114112
}
@@ -121,13 +119,11 @@ WithValueStory.parameters = {
121119
export function ReadOnlyStory() {
122120
return (
123121
<section className="story">
124-
<ControlPresentation
125-
maxWidth="small"
126-
startSlot={<InfoIcon />}
127-
endSlot={<ChevronDownIcon />}
128-
>
129-
<input aria-label="Read-only" defaultValue="Sample value" readOnly />
130-
</ControlPresentation>
122+
<Box maxWidth="small">
123+
<ControlPresentation startSlot={<InfoIcon />} endSlot={<ChevronDownIcon />}>
124+
<input aria-label="Read-only" defaultValue="Sample value" readOnly />
125+
</ControlPresentation>
126+
</Box>
131127
</section>
132128
)
133129
}
@@ -140,13 +136,11 @@ ReadOnlyStory.parameters = {
140136
export function DisabledStory() {
141137
return (
142138
<section className="story">
143-
<ControlPresentation
144-
maxWidth="small"
145-
startSlot={<InfoIcon />}
146-
endSlot={<ChevronDownIcon />}
147-
>
148-
<input aria-label="Disabled" defaultValue="Sample value" disabled />
149-
</ControlPresentation>
139+
<Box maxWidth="small">
140+
<ControlPresentation startSlot={<InfoIcon />} endSlot={<ChevronDownIcon />}>
141+
<input aria-label="Disabled" defaultValue="Sample value" disabled />
142+
</ControlPresentation>
143+
</Box>
150144
</section>
151145
)
152146
}
@@ -159,13 +153,11 @@ DisabledStory.parameters = {
159153
export function ErrorStory() {
160154
return (
161155
<section className="story">
162-
<ControlPresentation
163-
maxWidth="small"
164-
startSlot={<InfoIcon />}
165-
endSlot={<ChevronDownIcon />}
166-
>
167-
<input aria-label="Error" defaultValue="Invalid value" aria-invalid />
168-
</ControlPresentation>
156+
<Box maxWidth="small">
157+
<ControlPresentation startSlot={<InfoIcon />} endSlot={<ChevronDownIcon />}>
158+
<input aria-label="Error" defaultValue="Invalid value" aria-invalid />
159+
</ControlPresentation>
160+
</Box>
169161
</section>
170162
)
171163
}
@@ -178,9 +170,11 @@ ErrorStory.parameters = {
178170
export function EndSlotAsUnitStory() {
179171
return (
180172
<section className="story">
181-
<ControlPresentation maxWidth="small" startSlot={<InfoIcon />} endSlot="kg">
182-
<input aria-label="Weight" type="number" defaultValue="72" />
183-
</ControlPresentation>
173+
<Box maxWidth="small">
174+
<ControlPresentation startSlot={<InfoIcon />} endSlot="kg">
175+
<input aria-label="Weight" type="number" defaultValue="72" />
176+
</ControlPresentation>
177+
</Box>
184178
</section>
185179
)
186180
}
@@ -193,13 +187,14 @@ EndSlotAsUnitStory.parameters = {
193187
export function EndSlotAsClearButtonStory() {
194188
return (
195189
<section className="story">
196-
<ControlPresentation
197-
maxWidth="small"
198-
startSlot={<InfoIcon />}
199-
endSlot={<ControlActionButton icon={<XIcon />} aria-label="Clear" />}
200-
>
201-
<input aria-label="Search" defaultValue="sample query" />
202-
</ControlPresentation>
190+
<Box maxWidth="small">
191+
<ControlPresentation
192+
startSlot={<InfoIcon />}
193+
endSlot={<ControlActionButton icon={<XIcon />} aria-label="Clear" />}
194+
>
195+
<input aria-label="Search" defaultValue="sample query" />
196+
</ControlPresentation>
197+
</Box>
203198
</section>
204199
)
205200
}
@@ -212,21 +207,19 @@ EndSlotAsClearButtonStory.parameters = {
212207
export function WrappingSelectStory() {
213208
return (
214209
<section className="story">
215-
<ControlPresentation
216-
maxWidth="small"
217-
startSlot={<InfoIcon />}
218-
endSlot={<ChevronDownIcon />}
219-
>
220-
<select
221-
aria-label="Favourite fruit"
222-
defaultValue="banana"
223-
style={{ appearance: 'none' }}
224-
>
225-
<option value="apple">Apple</option>
226-
<option value="banana">Banana</option>
227-
<option value="cherry">Cherry</option>
228-
</select>
229-
</ControlPresentation>
210+
<Box maxWidth="small">
211+
<ControlPresentation startSlot={<InfoIcon />} endSlot={<ChevronDownIcon />}>
212+
<select
213+
aria-label="Favourite fruit"
214+
defaultValue="banana"
215+
style={{ appearance: 'none' }}
216+
>
217+
<option value="apple">Apple</option>
218+
<option value="banana">Banana</option>
219+
<option value="cherry">Cherry</option>
220+
</select>
221+
</ControlPresentation>
222+
</Box>
230223
</section>
231224
)
232225
}

src/control-presentation/control-presentation.tsx

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ import classNames from 'classnames'
55

66
import { Box } from '../box'
77

8-
import { FieldChromeContainer } from './field-chrome-container'
8+
import { OutlinedControlContainer } from './outlined-control-container'
99

1010
import styles from './control-presentation.module.css'
1111

12-
import type { ObfuscatedClassName } from '../utils/common-types'
13-
1412
type SlotContent = React.ReactElement | string | number
1513

1614
export type ControlPresentationProps = {
@@ -26,20 +24,7 @@ export type ControlPresentationProps = {
2624
* or dropdown-trigger chevron).
2725
*/
2826
endSlot?: SlotContent
29-
30-
/**
31-
* The control element (an `<input>`, an Ariakit Select trigger,
32-
* `<select>`, etc.). Attributes belonging to the control — `type`,
33-
* `value`, `onChange`, `readOnly`, `disabled`, `aria-invalid`, and so on —
34-
* are set on this element directly. The wrapper chrome derives from those
35-
* attributes.
36-
*
37-
* Click handlers belong on the control itself, not on this wrapper.
38-
* Clicking the wrapper focuses the control.
39-
*/
40-
children: React.ReactNode
41-
} & ObfuscatedClassName &
42-
Omit<ComponentProps<typeof Box>, 'className'>
27+
} & Omit<ComponentProps<typeof OutlinedControlContainer>, 'borderRadius'>
4328

4429
/**
4530
* The visual chrome of an inline, single-row, text-field-style input: a
@@ -52,14 +37,11 @@ export type ControlPresentationProps = {
5237
*/
5338
export const ControlPresentation = forwardRef<HTMLDivElement, ControlPresentationProps>(
5439
function ControlPresentation(
55-
{ startSlot, endSlot, exceptionallySetClassName, children, ...rest },
40+
{ startSlot, endSlot, exceptionallySetClassName, onClick, children },
5641
ref,
5742
) {
58-
// Only `onClick` is meaningful to forward to FCC; other Box props are
59-
// silently dropped pending CP API tightening in a follow-up.
60-
const { onClick } = rest as { onClick?: React.MouseEventHandler<HTMLDivElement> }
6143
return (
62-
<FieldChromeContainer
44+
<OutlinedControlContainer
6345
ref={ref}
6446
borderRadius="small"
6547
onClick={onClick}
@@ -70,7 +52,7 @@ export const ControlPresentation = forwardRef<HTMLDivElement, ControlPresentatio
7052
) : null}
7153
<div className={styles.control}>{children}</div>
7254
{endSlot ? <Slot className={[styles.slot, styles.endSlot]}>{endSlot}</Slot> : null}
73-
</FieldChromeContainer>
55+
</OutlinedControlContainer>
7456
)
7557
},
7658
)

src/control-presentation/field-chrome-container.module.css renamed to src/control-presentation/outlined-control-container.module.css

File renamed without changes.

0 commit comments

Comments
 (0)