@@ -84,6 +84,11 @@ const InternalSegmentedOption: React.FC<{
84
84
e : React . ChangeEvent < HTMLInputElement > ,
85
85
value : SegmentedRawOption ,
86
86
) => 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 ;
87
92
} > = ( {
88
93
prefixCls,
89
94
className,
@@ -94,6 +99,11 @@ const InternalSegmentedOption: React.FC<{
94
99
value,
95
100
name,
96
101
onChange,
102
+ onFocus,
103
+ onBlur,
104
+ onKeyDown,
105
+ onKeyUp,
106
+ onMouseDown,
97
107
} ) => {
98
108
const handleChange = ( event : React . ChangeEvent < HTMLInputElement > ) => {
99
109
if ( disabled ) {
@@ -107,20 +117,23 @@ const InternalSegmentedOption: React.FC<{
107
117
className = { classNames ( className , {
108
118
[ `${ prefixCls } -item-disabled` ] : disabled ,
109
119
} ) }
120
+ onMouseDown = { onMouseDown }
110
121
>
111
122
< input
112
123
name = { name }
113
124
className = { `${ prefixCls } -item-input` }
114
- aria-hidden = "true"
115
125
type = "radio"
116
126
disabled = { disabled }
117
127
checked = { checked }
118
128
onChange = { handleChange }
129
+ onFocus = { onFocus }
130
+ onBlur = { onBlur }
131
+ onKeyDown = { onKeyDown }
132
+ onKeyUp = { onKeyUp }
119
133
/>
120
134
< div
121
135
className = { `${ prefixCls } -item-label` }
122
136
title = { title }
123
- role = "option"
124
137
aria-selected = { checked }
125
138
>
126
139
{ label }
@@ -176,10 +189,63 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
176
189
177
190
const divProps = omit ( restProps , [ 'children' ] ) ;
178
191
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
+
179
244
return (
180
245
< div
181
- role = "listbox "
246
+ role = "radiogroup "
182
247
aria-label = "segmented control"
248
+ tabIndex = { disabled ? undefined : 0 }
183
249
{ ...divProps }
184
250
className = { classNames (
185
251
prefixCls ,
@@ -222,10 +288,19 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
222
288
{
223
289
[ `${ prefixCls } -item-selected` ] :
224
290
segmentedOption . value === rawValue && ! thumbShow ,
291
+ [ `${ prefixCls } -item-focused` ] :
292
+ isFocused &&
293
+ isKeyboard &&
294
+ segmentedOption . value === rawValue ,
225
295
} ,
226
296
) }
227
297
checked = { segmentedOption . value === rawValue }
228
298
onChange = { handleChange }
299
+ onFocus = { handleFocus }
300
+ onBlur = { handleBlur }
301
+ onKeyDown = { handleKeyDown }
302
+ onKeyUp = { handleKeyUp }
303
+ onMouseDown = { handleMouseDown }
229
304
disabled = { ! ! disabled || ! ! segmentedOption . disabled }
230
305
/>
231
306
) ) }
0 commit comments