@@ -84,6 +84,11 @@ const InternalSegmentedOption: React.FC<{
8484 e : React . ChangeEvent < HTMLInputElement > ,
8585 value : SegmentedRawOption ,
8686 ) => void ;
87+ onFocus : ( e : React . FocusEvent < HTMLInputElement > ) => void ;
88+ onBlur : ( e ?: React . FocusEvent < HTMLInputElement > ) => void ;
89+ onKeyDown : ( e : React . KeyboardEvent ) => void ;
90+ onKeyUp : ( e : React . KeyboardEvent ) => void ;
91+ onMouseDown : ( ) => void ;
8792} > = ( {
8893 prefixCls,
8994 className,
@@ -94,6 +99,11 @@ const InternalSegmentedOption: React.FC<{
9499 value,
95100 name,
96101 onChange,
102+ onFocus,
103+ onBlur,
104+ onKeyDown,
105+ onKeyUp,
106+ onMouseDown,
97107} ) => {
98108 const handleChange = ( event : React . ChangeEvent < HTMLInputElement > ) => {
99109 if ( disabled ) {
@@ -107,20 +117,23 @@ const InternalSegmentedOption: React.FC<{
107117 className = { classNames ( className , {
108118 [ `${ prefixCls } -item-disabled` ] : disabled ,
109119 } ) }
120+ onMouseDown = { onMouseDown }
110121 >
111122 < input
112123 name = { name }
113124 className = { `${ prefixCls } -item-input` }
114- aria-hidden = "true"
115125 type = "radio"
116126 disabled = { disabled }
117127 checked = { checked }
118128 onChange = { handleChange }
129+ onFocus = { onFocus }
130+ onBlur = { onBlur }
131+ onKeyDown = { onKeyDown }
132+ onKeyUp = { onKeyUp }
119133 />
120134 < div
121135 className = { `${ prefixCls } -item-label` }
122136 title = { title }
123- role = "option"
124137 aria-selected = { checked }
125138 >
126139 { label }
@@ -176,10 +189,63 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
176189
177190 const divProps = omit ( restProps , [ 'children' ] ) ;
178191
192+ // ======================= Focus ========================
193+ const [ isKeyboard , setIsKeyboard ] = React . useState ( false ) ;
194+ const [ isFocused , setIsFocused ] = React . useState ( false ) ;
195+
196+ const handleFocus = ( ) => {
197+ setIsFocused ( true ) ;
198+ } ;
199+
200+ const handleBlur = ( ) => {
201+ setIsFocused ( false ) ;
202+ } ;
203+
204+ const handleMouseDown = ( ) => {
205+ setIsKeyboard ( false ) ;
206+ } ;
207+
208+ // capture keyboard tab interaction for correct focus style
209+ const handleKeyUp = ( event : React . KeyboardEvent ) => {
210+ if ( event . key === 'Tab' ) {
211+ setIsKeyboard ( true ) ;
212+ }
213+ } ;
214+
215+ // ======================= Keyboard ========================
216+ const onOffset = ( offset : number ) => {
217+ const currentIndex = segmentedOptions . findIndex (
218+ ( option ) => option . value === rawValue ,
219+ ) ;
220+
221+ const total = segmentedOptions . length ;
222+ const nextIndex = ( currentIndex + offset + total ) % total ;
223+
224+ const nextOption = segmentedOptions [ nextIndex ] ;
225+ if ( nextOption ) {
226+ setRawValue ( nextOption . value ) ;
227+ onChange ?.( nextOption . value ) ;
228+ }
229+ } ;
230+
231+ const handleKeyDown = ( event : React . KeyboardEvent ) => {
232+ switch ( event . key ) {
233+ case 'ArrowLeft' :
234+ case 'ArrowUp' :
235+ onOffset ( - 1 ) ;
236+ break ;
237+ case 'ArrowRight' :
238+ case 'ArrowDown' :
239+ onOffset ( 1 ) ;
240+ break ;
241+ }
242+ } ;
243+
179244 return (
180245 < div
181- role = "listbox "
246+ role = "radiogroup "
182247 aria-label = "segmented control"
248+ tabIndex = { disabled ? undefined : 0 }
183249 { ...divProps }
184250 className = { classNames (
185251 prefixCls ,
@@ -222,10 +288,19 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
222288 {
223289 [ `${ prefixCls } -item-selected` ] :
224290 segmentedOption . value === rawValue && ! thumbShow ,
291+ [ `${ prefixCls } -item-focused` ] :
292+ isFocused &&
293+ isKeyboard &&
294+ segmentedOption . value === rawValue ,
225295 } ,
226296 ) }
227297 checked = { segmentedOption . value === rawValue }
228298 onChange = { handleChange }
299+ onFocus = { handleFocus }
300+ onBlur = { handleBlur }
301+ onKeyDown = { handleKeyDown }
302+ onKeyUp = { handleKeyUp }
303+ onMouseDown = { handleMouseDown }
229304 disabled = { ! ! disabled || ! ! segmentedOption . disabled }
230305 />
231306 ) ) }
0 commit comments