@@ -3,6 +3,7 @@ import { useRef, useState } from 'react'
3
3
import { classNames } from '../../utils/class-names'
4
4
5
5
import { Button } from '../../components/button'
6
+ import { flushSync } from 'react-dom'
6
7
7
8
type Option = {
8
9
name : string
@@ -67,6 +68,17 @@ export default function Home() {
67
68
setQuery ( '' )
68
69
} }
69
70
as = "div"
71
+
72
+ // Don't do this lol — it's not supported
73
+ // It's just so we can tab to the "Add" button for the demo
74
+ // The combobox doesn't actually support this behavior
75
+ onKeyDownCapture = { ( event : KeyboardEvent ) => {
76
+ let addButton = document . querySelector ( '#add_person' )
77
+ if ( event . key === 'Tab' && addButton && filtered . length === 0 ) {
78
+ event . preventDefault ( )
79
+ setTimeout ( ( ) => addButton . focus ( ) , 0 )
80
+ }
81
+ } }
70
82
>
71
83
< Combobox . Label className = "block text-sm font-medium leading-5 text-gray-700" >
72
84
Person
@@ -100,6 +112,11 @@ export default function Home() {
100
112
101
113
< div className = "absolute mt-1 w-full rounded-md bg-white shadow-lg" >
102
114
< Combobox . Options
115
+ // This is a hack to make keep the options list around when it's empty
116
+ // It comes with some caveats:
117
+ // like the option callback being called with a null option (which is probably a bug)
118
+ static = { filtered . length === 0 }
119
+
103
120
ref = { optionsRef }
104
121
className = { classNames (
105
122
"shadow-xs max-h-60 rounded-md py-1 text-base leading-6 focus:outline-none sm:text-sm sm:leading-5" ,
@@ -108,13 +125,13 @@ export default function Home() {
108
125
>
109
126
{
110
127
( { option } : { option : Option } ) => {
111
- if ( option . empty ) {
128
+ if ( ! option || option . empty ) {
112
129
return (
113
130
< Combobox . Option
114
131
// TODO: `disabled` being required is a bug
115
132
disabled
116
133
// Note: Do NOT use `null` for the `value`
117
- value = { option }
134
+ value = { option ?? emptyOption . current }
118
135
className = "relative w-full cursor-default select-none py-2 px-3 focus:outline-none text-center"
119
136
>
120
137
< div className = "grid grid-cols-1 grid-rows-1 h-full relative" >
@@ -124,7 +141,19 @@ export default function Home() {
124
141
</ svg >
125
142
</ div >
126
143
< div className = "z-20 col-start-1 row-start-1 col-span-full row-span-full p-8 flex flex-col justify-center items-center" >
127
- < h3 className = "mx-2 text-xl text-gray-400 font-semibold" > No people found</ h3 >
144
+ < h3 className = "mx-2 text-xl mb-4 text-gray-400 font-semibold" > No people found</ h3 >
145
+ < button
146
+ id = "add_person"
147
+ type = "button"
148
+ className = "bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded font-semibold focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 focus:outline-none"
149
+ onClick = { ( ) => {
150
+ let person = { name : query , disabled : false }
151
+ setList ( list => [ ...list , person ] )
152
+ setSelectedPerson ( person )
153
+ } }
154
+ >
155
+ Add "{ query } "
156
+ </ button >
128
157
</ div >
129
158
</ div >
130
159
</ Combobox . Option >
0 commit comments