1- import React , { RefObject , useRef } from 'react'
1+ import React , { useRef } from 'react'
22import Button , { SegmentedControlButtonProps } from './SegmentedControlButton'
33import SegmentedControlIconButton , { SegmentedControlIconButtonProps } from './SegmentedControlIconButton'
4- import { ActionList , ActionMenu , Box , useTheme } from '..'
5- import { merge , SxProp } from '../sx'
4+ import { ActionList , ActionMenu , useTheme } from '..'
5+ import sx , { merge , SxProp } from '../sx'
66import { ResponsiveValue , useResponsiveValue } from '../hooks/useResponsiveValue'
77import { ViewportRangeKeys } from '../utils/types/ViewportRangeKeys'
8- import { FocusKeys , FocusZoneHookSettings , useFocusZone } from '../hooks/useFocusZone '
8+ import styled from 'styled-components '
99
1010type WidthOnlyViewportRangeKeys = Exclude < ViewportRangeKeys , 'narrowLandscape' | 'portrait' | 'landscape' >
1111
12+ // Needed because passing a ref to `Box` causes a type error
13+ const SegmentedControlList = styled . ul `
14+ ${ sx } ;
15+ `
16+
1217type SegmentedControlProps = {
1318 'aria-label' ?: string
1419 'aria-labelledby' ?: string
@@ -28,7 +33,10 @@ const getSegmentedControlStyles = (isFullWidth?: boolean) => ({
2833 borderStyle : 'solid' ,
2934 borderWidth : 1 ,
3035 display : isFullWidth ? 'flex' : 'inline-flex' ,
31- height : '32px' // TODO: use primitive `control.medium.size` when it is available
36+ height : '32px' , // TODO: use primitive `control.medium.size` when it is available
37+ margin : 0 ,
38+ padding : 0 ,
39+ width : isFullWidth ? '100%' : undefined
3240} )
3341
3442const Root : React . FC < React . PropsWithChildren < SegmentedControlProps > > = ( {
@@ -41,7 +49,7 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
4149 variant,
4250 ...rest
4351} ) => {
44- const segmentedControlContainerRef = useRef < HTMLSpanElement > ( null )
52+ const segmentedControlContainerRef = useRef < HTMLUListElement > ( null )
4553 const { theme} = useTheme ( )
4654 const responsiveVariant = useResponsiveValue ( variant , 'default' )
4755 const isFullWidth = useResponsiveValue ( fullWidth , false )
@@ -74,26 +82,7 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
7482
7583 return React . isValidElement < SegmentedControlIconButtonProps > ( childArg ) ? childArg . props [ 'aria-label' ] : null
7684 }
77- const sx = merge ( getSegmentedControlStyles ( isFullWidth ) , sxProp as SxProp )
78-
79- const focusInStrategy : FocusZoneHookSettings [ 'focusInStrategy' ] = ( ) => {
80- if ( segmentedControlContainerRef . current ) {
81- // we need to use type assertion because querySelector returns "Element", not "HTMLElement"
82- type SelectedButton = HTMLButtonElement | undefined
83-
84- const selectedButton = segmentedControlContainerRef . current . querySelector (
85- 'button[aria-current="true"]'
86- ) as SelectedButton
87-
88- return selectedButton
89- }
90- }
91-
92- useFocusZone ( {
93- containerRef : segmentedControlContainerRef ,
94- bindKeys : FocusKeys . ArrowHorizontal | FocusKeys . HomeAndEnd ,
95- focusInStrategy
96- } )
85+ const listSx = merge ( getSegmentedControlStyles ( isFullWidth ) , sxProp as SxProp )
9786
9887 if ( ! ariaLabel && ! ariaLabelledby ) {
9988 // eslint-disable-next-line no-console
@@ -141,12 +130,11 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
141130 </ ActionMenu >
142131 ) : (
143132 // Render a segmented control
144- < Box
145- role = "toolbar"
146- sx = { sx }
133+ < SegmentedControlList
134+ sx = { listSx }
147135 aria-label = { ariaLabel }
148136 aria-labelledby = { ariaLabelledby }
149- ref = { segmentedControlContainerRef as RefObject < HTMLDivElement > }
137+ ref = { segmentedControlContainerRef }
150138 { ...rest }
151139 >
152140 { React . Children . map ( children , ( child , index ) => {
@@ -180,6 +168,7 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
180168 children : childPropsChildren ,
181169 ...restChildProps
182170 } = child . props
171+ const { sx : sharedSxProp , ...restSharedChildProps } = sharedChildProps
183172 if ( ! leadingIcon ) {
184173 // eslint-disable-next-line no-console
185174 console . warn ( 'A `leadingIcon` prop is required when hiding visible labels' )
@@ -190,12 +179,12 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
190179 icon = { leadingIcon }
191180 sx = {
192181 {
193- '--separator-color' :
194- index === selectedIndex || index === selectedIndex - 1
195- ? 'transparent'
196- : theme ?. colors . border . default
182+ ...sharedSxProp ,
183+ // setting width here avoids having to pass `isFullWidth` directly to child components
184+ width : ! isFullWidth ? '32px' : '100%' // TODO: use primitive `control.medium.size` when it is available instead of '32px'
197185 } as React . CSSProperties
198186 }
187+ { ...restSharedChildProps }
199188 { ...restChildProps }
200189 />
201190 )
@@ -205,7 +194,7 @@ const Root: React.FC<React.PropsWithChildren<SegmentedControlProps>> = ({
205194 // Render the children as-is and add the shared child props
206195 return React . cloneElement ( child , sharedChildProps )
207196 } ) }
208- </ Box >
197+ </ SegmentedControlList >
209198 )
210199}
211200
0 commit comments