Skip to content

Commit 4896ef1

Browse files
authored
Remove sx from the SegmentedControl component (#6741)
1 parent aab9d8f commit 4896ef1

File tree

12 files changed

+89
-135
lines changed

12 files changed

+89
-135
lines changed

.changeset/witty-chicken-leave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@primer/react': major
3+
---
4+
5+
Remove sx prop support from the SegmentedControl component.

e2e/components/SegmentedControl.test.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,6 @@ const stories = [
6060
title: 'Dev: With Css',
6161
id: 'components-segmentedcontrol-dev--with-css',
6262
},
63-
{
64-
title: 'Dev: With Sx',
65-
id: 'components-segmentedcontrol-dev--with-sx',
66-
},
67-
{
68-
title: 'Dev: With Sx And Css',
69-
id: 'components-segmentedcontrol-dev--with-sx-and-css',
70-
},
7163
] as const
7264

7365
test.describe('SegmentedControl', () => {

packages/react/src/SegmentedControl/SegmentedControl.dev.stories.tsx

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -31,47 +31,3 @@ export const WithCss = () => (
3131
</SegmentedControl.Button>
3232
</SegmentedControl>
3333
)
34-
35-
export const WithSx = () => (
36-
<SegmentedControl aria-label="File view" sx={{fontFamily: 'monospace'}}>
37-
<SegmentedControl.Button defaultSelected aria-label={'Preview'} leadingIcon={EyeIcon} sx={{color: 'success.fg'}}>
38-
Preview
39-
</SegmentedControl.Button>
40-
<SegmentedControl.Button aria-label={'Raw'} leadingIcon={FileCodeIcon} sx={{color: 'success.fg'}}>
41-
Raw
42-
</SegmentedControl.Button>
43-
<SegmentedControl.Button aria-label={'Blame'} leadingIcon={PeopleIcon} sx={{color: 'success.fg'}}>
44-
Blame
45-
</SegmentedControl.Button>
46-
</SegmentedControl>
47-
)
48-
49-
export const WithSxAndCss = () => (
50-
<SegmentedControl aria-label="File view" sx={{fontFamily: 'monospace'}} className="testCustomClassnameMono">
51-
<SegmentedControl.Button
52-
defaultSelected
53-
aria-label={'Preview'}
54-
leadingIcon={EyeIcon}
55-
sx={{color: 'success.fg'}}
56-
className="testCustomClassnameColor"
57-
>
58-
Preview
59-
</SegmentedControl.Button>
60-
<SegmentedControl.Button
61-
aria-label={'Raw'}
62-
leadingIcon={FileCodeIcon}
63-
sx={{color: 'success.fg'}}
64-
className="testCustomClassnameColor"
65-
>
66-
Raw
67-
</SegmentedControl.Button>
68-
<SegmentedControl.Button
69-
aria-label={'Blame'}
70-
leadingIcon={PeopleIcon}
71-
sx={{color: 'success.fg'}}
72-
className="testCustomClassnameColor"
73-
>
74-
Blame
75-
</SegmentedControl.Button>
76-
</SegmentedControl>
77-
)

packages/react/src/SegmentedControl/SegmentedControl.docs.json

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,7 @@
7878
"type": "'small' | 'medium'",
7979
"description": "The size of the buttons",
8080
"defaultValue": ""
81-
},
82-
{
83-
"name": "sx",
84-
"type": "SystemStyleObject",
85-
"deprecated": true
86-
},
81+
},
8782
{
8883
"name": "ref",
8984
"type": "React.RefObject<HTMLDivElement>"
@@ -110,12 +105,7 @@
110105
"type": "boolean",
111106
"defaultValue": "",
112107
"description": "Whether the segment is selected. This is used for uncontrolled SegmentedControls to pick one SegmentedControlButton that is selected on the initial render."
113-
},
114-
{
115-
"name": "sx",
116-
"type": "SystemStyleObject",
117-
"deprecated": true
118-
},
108+
},
119109
{
120110
"name": "ref",
121111
"type": "React.RefObject<HTMLButtonElement>"
@@ -156,12 +146,7 @@
156146
"type": "boolean",
157147
"defaultValue": "",
158148
"description": "Whether the segment is selected. This is used for uncontrolled SegmentedControls to pick one SegmentedControlButton that is selected on the initial render."
159-
},
160-
{
161-
"name": "sx",
162-
"type": "SystemStyleObject",
163-
"deprecated": true
164-
},
149+
},
165150
{
166151
"name": "ref",
167152
"type": "React.RefObject<HTMLButtonElement>"

packages/react/src/SegmentedControl/SegmentedControl.tsx

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,14 @@ import SegmentedControlIconButton from './SegmentedControlIconButton'
66
import {ActionList} from '../ActionList'
77
import {ActionMenu} from '../ActionMenu'
88
import {useTheme} from '../ThemeProvider'
9-
import type {SxProp} from '../sx'
109
import type {ResponsiveValue} from '../hooks/useResponsiveValue'
1110
import {useResponsiveValue} from '../hooks/useResponsiveValue'
1211
import type {WidthOnlyViewportRangeKeys} from '../utils/types/ViewportRangeKeys'
1312
import {isElement} from 'react-is'
14-
1513
import classes from './SegmentedControl.module.css'
16-
1714
import {clsx} from 'clsx'
18-
import {BoxWithFallback} from '../internal/components/BoxWithFallback'
1915

20-
type SegmentedControlProps = {
16+
export type SegmentedControlProps = {
2117
'aria-label'?: string
2218
'aria-labelledby'?: string
2319
'aria-describedby'?: string
@@ -30,7 +26,7 @@ type SegmentedControlProps = {
3026
/** Configure alternative ways to render the control when it gets rendered in tight spaces */
3127
variant?: 'default' | Partial<Record<WidthOnlyViewportRangeKeys, 'hideLabels' | 'dropdown' | 'default'>>
3228
className?: string
33-
} & SxProp
29+
}
3430

3531
const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
3632
'aria-label': ariaLabel,
@@ -39,7 +35,6 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
3935
fullWidth,
4036
onChange,
4137
size,
42-
sx: sxProp,
4338
variant = 'default',
4439
className,
4540
...rest
@@ -153,9 +148,7 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
153148
</>
154149
) : (
155150
// Render a segmented control
156-
<BoxWithFallback
157-
as="ul"
158-
sx={sxProp}
151+
<ul
159152
aria-label={ariaLabel}
160153
aria-labelledby={ariaLabelledby}
161154
ref={segmentedControlContainerRef}
@@ -186,7 +179,6 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
186179
index === selectedIndex || index === selectedIndex - 1 ? 'transparent' : theme?.colors.border.default,
187180
...child.props.style,
188181
},
189-
sx: child.props.sx,
190182
}
191183

192184
// Render the 'hideLabels' variant of the SegmentedControlButton
@@ -201,7 +193,6 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
201193
children: childPropsChildren,
202194
...restChildProps
203195
} = child.props
204-
const {sx: sharedSxProp, ...restSharedChildProps} = sharedChildProps
205196
if (!leadingIcon) {
206197
// eslint-disable-next-line no-console
207198
console.warn('A `leadingIcon` prop is required when hiding visible labels')
@@ -210,14 +201,9 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
210201
<SegmentedControlIconButton
211202
aria-label={childAriaLabel || childPropsChildren}
212203
icon={leadingIcon}
213-
sx={
214-
{
215-
...sharedSxProp,
216-
// setting width here avoids having to pass `isFullWidth` directly to child components
217-
width: !isFullWidth ? '32px' : '100%', // TODO: use primitive `control.medium.size` when it is available instead of '32px'
218-
} as React.CSSProperties
219-
}
220-
{...restSharedChildProps}
204+
// Width is now handled by CSS: 32px default, 100% when data-full-width is set on parent
205+
className={classes.IconButton}
206+
{...sharedChildProps}
221207
{...restChildProps}
222208
/>
223209
)
@@ -227,7 +213,7 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
227213
// Render the children as-is and add the shared child props
228214
return React.cloneElement(child, sharedChildProps)
229215
})}
230-
</BoxWithFallback>
216+
</ul>
231217
)
232218
}
233219

packages/react/src/SegmentedControl/SegmentedControlButton.tsx

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import type {ButtonHTMLAttributes} from 'react'
22
import type React from 'react'
33
import type {IconProps} from '@primer/octicons-react'
4-
import type {SxProp} from '../sx'
54
import {isElement} from 'react-is'
65

76
import classes from './SegmentedControl.module.css'
87
import {clsx} from 'clsx'
9-
import {BoxWithFallback} from '../internal/components/BoxWithFallback'
108

119
export type SegmentedControlButtonProps = {
1210
/** The visible label rendered in the button */
@@ -17,28 +15,20 @@ export type SegmentedControlButtonProps = {
1715
defaultSelected?: boolean
1816
/** The leading icon comes before item label */
1917
leadingIcon?: React.FunctionComponent<React.PropsWithChildren<IconProps>> | React.ReactElement
20-
} & SxProp &
21-
ButtonHTMLAttributes<HTMLButtonElement | HTMLLIElement>
18+
} & ButtonHTMLAttributes<HTMLButtonElement | HTMLLIElement>
2219

2320
const SegmentedControlButton: React.FC<React.PropsWithChildren<SegmentedControlButtonProps>> = ({
2421
children,
2522
leadingIcon: LeadingIcon,
2623
selected,
27-
sx: sxProp,
2824
className,
2925
// Note: this value is read in the `SegmentedControl` component to determine which button is selected but we do not need to apply it to an underlying element
3026
defaultSelected: _defaultSelected,
3127
...rest
3228
}) => {
3329
return (
34-
<BoxWithFallback as="li" sx={sxProp} className={clsx(classes.Item)} data-selected={selected ? '' : undefined}>
35-
<BoxWithFallback
36-
as="button"
37-
aria-current={selected}
38-
className={clsx(classes.Button, className)}
39-
type="button"
40-
{...rest}
41-
>
30+
<li className={clsx(classes.Item)} data-selected={selected ? '' : undefined}>
31+
<button aria-current={selected} className={clsx(classes.Button, className)} type="button" {...rest}>
4232
<span className={clsx(classes.Content, 'segmentedControl-content')}>
4333
{LeadingIcon && (
4434
<div className={classes.LeadingIcon}>{isElement(LeadingIcon) ? LeadingIcon : <LeadingIcon />}</div>
@@ -47,8 +37,8 @@ const SegmentedControlButton: React.FC<React.PropsWithChildren<SegmentedControlB
4737
{children}
4838
</div>
4939
</span>
50-
</BoxWithFallback>
51-
</BoxWithFallback>
40+
</button>
41+
</li>
5242
)
5343
}
5444

packages/react/src/SegmentedControl/SegmentedControlIconButton.tsx

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
import type {ButtonHTMLAttributes} from 'react'
22
import type React from 'react'
33
import type {IconProps} from '@primer/octicons-react'
4-
import type {SxProp} from '../sx'
54
import {isElement} from 'react-is'
65
import {useFeatureFlag} from '../FeatureFlags'
76
import type {TooltipDirection} from '../TooltipV2'
87
import classes from './SegmentedControl.module.css'
98
import {clsx} from 'clsx'
109
import {Tooltip} from '../TooltipV2'
11-
import {BoxWithFallback} from '../internal/components/BoxWithFallback'
1210

1311
export type SegmentedControlIconButtonProps = {
1412
'aria-label': string
@@ -22,14 +20,12 @@ export type SegmentedControlIconButtonProps = {
2220
description?: string
2321
/** The direction for the tooltip.*/
2422
tooltipDirection?: TooltipDirection
25-
} & SxProp &
26-
ButtonHTMLAttributes<HTMLButtonElement | HTMLLIElement>
23+
} & ButtonHTMLAttributes<HTMLButtonElement | HTMLLIElement>
2724

2825
export const SegmentedControlIconButton: React.FC<React.PropsWithChildren<SegmentedControlIconButtonProps>> = ({
2926
'aria-label': ariaLabel,
3027
icon: Icon,
3128
selected,
32-
sx: sxProp,
3329
className,
3430
description,
3531
tooltipDirection,
@@ -38,19 +34,14 @@ export const SegmentedControlIconButton: React.FC<React.PropsWithChildren<Segmen
3834
const tooltipFlagEnabled = useFeatureFlag('primer_react_segmented_control_tooltip')
3935
if (tooltipFlagEnabled) {
4036
return (
41-
<BoxWithFallback
42-
as="li"
43-
sx={sxProp}
44-
className={clsx(classes.Item, className)}
45-
data-selected={selected || undefined}
46-
>
37+
<li className={clsx(classes.Item, className)} data-selected={selected || undefined}>
4738
<Tooltip
4839
type={description ? undefined : 'label'}
4940
text={description ? description : ariaLabel}
5041
direction={tooltipDirection}
5142
>
52-
<BoxWithFallback
53-
as="button"
43+
<button
44+
type="button"
5445
aria-current={selected}
5546
// If description is provided, we will use the tooltip to describe the button, so we need to keep the aria-label to label the button.
5647
aria-label={description ? ariaLabel : undefined}
@@ -60,29 +51,24 @@ export const SegmentedControlIconButton: React.FC<React.PropsWithChildren<Segmen
6051
<span className={clsx(classes.Content, 'segmentedControl-content')}>
6152
{isElement(Icon) ? Icon : <Icon />}
6253
</span>
63-
</BoxWithFallback>
54+
</button>
6455
</Tooltip>
65-
</BoxWithFallback>
56+
</li>
6657
)
6758
} else {
6859
// This can be removed when primer_react_segmented_control_tooltip feature flag is GA-ed.
6960
return (
70-
<BoxWithFallback
71-
as="li"
72-
sx={sxProp}
73-
className={clsx(classes.Item, className)}
74-
data-selected={selected || undefined}
75-
>
76-
<BoxWithFallback
77-
as="button"
61+
<li className={clsx(classes.Item, className)} data-selected={selected || undefined}>
62+
<button
63+
type="button"
7864
aria-label={ariaLabel}
7965
aria-current={selected}
8066
className={clsx(classes.Button, classes.IconButton)}
8167
{...rest}
8268
>
8369
<span className={clsx(classes.Content, 'segmentedControl-content')}>{isElement(Icon) ? Icon : <Icon />}</span>
84-
</BoxWithFallback>
85-
</BoxWithFallback>
70+
</button>
71+
</li>
8672
)
8773
}
8874
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
export * from './SegmentedControl'
2+
3+
export type {SegmentedControlProps} from './SegmentedControl'
4+
export type {SegmentedControlButtonProps} from './SegmentedControlButton'
5+
export type {SegmentedControlIconButtonProps} from './SegmentedControlIconButton'

packages/react/src/__tests__/__snapshots__/exports.test.ts.snap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ exports[`@primer/react > should not update exports without a semver change 1`] =
130130
"type RelativeTimeProps",
131131
"ResponsiveValue",
132132
"SegmentedControl",
133+
"type SegmentedControlButtonProps",
134+
"type SegmentedControlIconButtonProps",
135+
"type SegmentedControlProps",
133136
"Select",
134137
"SelectPanel",
135138
"type SelectPanelGroupedListProps",

packages/react/src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ export {default as RadioGroup} from './RadioGroup'
134134
export type {RelativeTimeProps} from './RelativeTime'
135135
export {default as RelativeTime} from './RelativeTime'
136136
export {SegmentedControl} from './SegmentedControl'
137+
export type {
138+
SegmentedControlProps,
139+
SegmentedControlButtonProps,
140+
SegmentedControlIconButtonProps,
141+
} from './SegmentedControl'
137142
// Curently there is a duplicate Select component at the root of the dir, so need to be explicit about exporting from the src/Select dir
138143
export {default as Select} from './Select'
139144
export type {SelectProps} from './Select'

0 commit comments

Comments
 (0)