@@ -137,6 +137,7 @@ type Context = {
137
137
type State = {
138
138
search : string
139
139
value : string
140
+ selectedItemId ?: string
140
141
filtered : { count : number ; items : Map < string , number > ; groups : Set < string > }
141
142
}
142
143
type Store = {
@@ -184,6 +185,8 @@ const Command = React.forwardRef<HTMLDivElement, CommandProps>((props, forwarded
184
185
search : '' ,
185
186
/** Currently selected item value. */
186
187
value : props . value ?? props . defaultValue ?? '' ,
188
+ /** Currently selected item id. */
189
+ selectedItemId : undefined ,
187
190
filtered : {
188
191
/** The count of all visible items. */
189
192
count : 0 ,
@@ -251,6 +254,18 @@ const Command = React.forwardRef<HTMLDivElement, CommandProps>((props, forwarded
251
254
sort ( )
252
255
schedule ( 1 , selectFirstItem )
253
256
} else if ( key === 'value' ) {
257
+ // Force focus input or root so accessibility works
258
+ if ( document . activeElement . hasAttribute ( 'cmdk-input' ) || document . activeElement . hasAttribute ( 'cmdk-root' ) ) {
259
+ const input = document . getElementById ( inputId )
260
+ if ( input ) input . focus ( )
261
+ else document . getElementById ( listId ) ?. focus ( )
262
+ }
263
+
264
+ schedule ( 7 , ( ) => {
265
+ state . current . selectedItemId = getSelectedItem ( ) ?. id
266
+ store . emit ( )
267
+ } )
268
+
254
269
// opts is a boolean referring to whether it should NOT be scrolled into view
255
270
if ( ! opts ) {
256
271
// Scroll the selected item into view
@@ -785,16 +800,9 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>((props, forwardedRe
785
800
const isControlled = props . value != null
786
801
const store = useStore ( )
787
802
const search = useCmdk ( ( state ) => state . search )
788
- const value = useCmdk ( ( state ) => state . value )
803
+ const selectedItemId = useCmdk ( ( state ) => state . selectedItemId )
789
804
const context = useCommand ( )
790
805
791
- const selectedItemId = React . useMemo ( ( ) => {
792
- const item = context . listInnerRef . current ?. querySelector (
793
- `${ ITEM_SELECTOR } [${ VALUE_ATTR } ="${ encodeURIComponent ( value ) } "]` ,
794
- )
795
- return item ?. getAttribute ( 'id' )
796
- } , [ ] )
797
-
798
806
React . useEffect ( ( ) => {
799
807
if ( props . value != null ) {
800
808
store . setState ( 'search' , props . value )
@@ -837,6 +845,7 @@ const List = React.forwardRef<HTMLDivElement, ListProps>((props, forwardedRef) =
837
845
const { children, label = 'Suggestions' , ...etc } = props
838
846
const ref = React . useRef < HTMLDivElement > ( null )
839
847
const height = React . useRef < HTMLDivElement > ( null )
848
+ const selectedItemId = useCmdk ( ( state ) => state . selectedItemId )
840
849
const context = useCommand ( )
841
850
842
851
React . useEffect ( ( ) => {
@@ -864,6 +873,8 @@ const List = React.forwardRef<HTMLDivElement, ListProps>((props, forwardedRef) =
864
873
{ ...etc }
865
874
cmdk-list = ""
866
875
role = "listbox"
876
+ tabIndex = { - 1 }
877
+ aria-activedescendant = { selectedItemId }
867
878
aria-label = { label }
868
879
id = { context . listId }
869
880
>
0 commit comments