@@ -100,6 +100,13 @@ function useDisclosureContext(component: string) {
100
100
return context
101
101
}
102
102
103
+ let DisclosurePanelContext = createContext < string | null > ( null )
104
+ DisclosurePanelContext . displayName = 'DisclosurePanelContext'
105
+
106
+ function useDisclosurePanelContext ( ) {
107
+ return useContext ( DisclosurePanelContext )
108
+ }
109
+
103
110
function stateReducer ( state : StateDefinition , action : Actions ) {
104
111
return match ( action . type , reducers , state , action )
105
112
}
@@ -176,18 +183,35 @@ let Button = forwardRefWithAs(function Button<TTag extends ElementType = typeof
176
183
let [ state , dispatch ] = useDisclosureContext ( [ Disclosure . name , Button . name ] . join ( '.' ) )
177
184
let buttonRef = useSyncRefs ( ref )
178
185
186
+ let panelContext = useDisclosurePanelContext ( )
187
+ let isWithinPanel = panelContext === null ? false : panelContext === state . panelId
188
+
179
189
let handleKeyDown = useCallback (
180
190
( event : ReactKeyboardEvent < HTMLButtonElement > ) => {
181
- switch ( event . key ) {
182
- case Keys . Space :
183
- case Keys . Enter :
184
- event . preventDefault ( )
185
- event . stopPropagation ( )
186
- dispatch ( { type : ActionTypes . ToggleDisclosure } )
187
- break
191
+ if ( isWithinPanel ) {
192
+ if ( state . disclosureState === DisclosureStates . Closed ) return
193
+
194
+ switch ( event . key ) {
195
+ case Keys . Space :
196
+ case Keys . Enter :
197
+ event . preventDefault ( )
198
+ event . stopPropagation ( )
199
+ dispatch ( { type : ActionTypes . ToggleDisclosure } )
200
+ document . getElementById ( state . buttonId ) ?. focus ( )
201
+ break
202
+ }
203
+ } else {
204
+ switch ( event . key ) {
205
+ case Keys . Space :
206
+ case Keys . Enter :
207
+ event . preventDefault ( )
208
+ event . stopPropagation ( )
209
+ dispatch ( { type : ActionTypes . ToggleDisclosure } )
210
+ break
211
+ }
188
212
}
189
213
} ,
190
- [ dispatch ]
214
+ [ dispatch , isWithinPanel , state . disclosureState ]
191
215
)
192
216
193
217
let handleKeyUp = useCallback ( ( event : ReactKeyboardEvent < HTMLButtonElement > ) => {
@@ -205,9 +229,15 @@ let Button = forwardRefWithAs(function Button<TTag extends ElementType = typeof
205
229
( event : ReactMouseEvent ) => {
206
230
if ( isDisabledReactIssue7711 ( event . currentTarget ) ) return
207
231
if ( props . disabled ) return
208
- dispatch ( { type : ActionTypes . ToggleDisclosure } )
232
+
233
+ if ( isWithinPanel ) {
234
+ dispatch ( { type : ActionTypes . ToggleDisclosure } )
235
+ document . getElementById ( state . buttonId ) ?. focus ( )
236
+ } else {
237
+ dispatch ( { type : ActionTypes . ToggleDisclosure } )
238
+ }
209
239
} ,
210
- [ dispatch , props . disabled ]
240
+ [ dispatch , props . disabled , state . buttonId , isWithinPanel ]
211
241
)
212
242
213
243
let slot = useMemo < ButtonRenderPropArg > (
@@ -216,16 +246,20 @@ let Button = forwardRefWithAs(function Button<TTag extends ElementType = typeof
216
246
)
217
247
218
248
let passthroughProps = props
219
- let propsWeControl = {
220
- ref : buttonRef ,
221
- id : state . buttonId ,
222
- type : 'button' ,
223
- 'aria-expanded' : props . disabled ? undefined : state . disclosureState === DisclosureStates . Open ,
224
- 'aria-controls' : state . linkedPanel ? state . panelId : undefined ,
225
- onKeyDown : handleKeyDown ,
226
- onKeyUp : handleKeyUp ,
227
- onClick : handleClick ,
228
- }
249
+ let propsWeControl = isWithinPanel
250
+ ? { type : 'button' , onKeyDown : handleKeyDown , onClick : handleClick }
251
+ : {
252
+ ref : buttonRef ,
253
+ id : state . buttonId ,
254
+ type : 'button' ,
255
+ 'aria-expanded' : props . disabled
256
+ ? undefined
257
+ : state . disclosureState === DisclosureStates . Open ,
258
+ 'aria-controls' : state . linkedPanel ? state . panelId : undefined ,
259
+ onKeyDown : handleKeyDown ,
260
+ onKeyUp : handleKeyUp ,
261
+ onClick : handleClick ,
262
+ }
229
263
230
264
return render ( {
231
265
props : { ...passthroughProps , ...propsWeControl } ,
@@ -285,14 +319,18 @@ let Panel = forwardRefWithAs(function Panel<TTag extends ElementType = typeof DE
285
319
}
286
320
let passthroughProps = props
287
321
288
- return render ( {
289
- props : { ...passthroughProps , ...propsWeControl } ,
290
- slot,
291
- defaultTag : DEFAULT_PANEL_TAG ,
292
- features : PanelRenderFeatures ,
293
- visible,
294
- name : 'Disclosure.Panel' ,
295
- } )
322
+ return (
323
+ < DisclosurePanelContext . Provider value = { state . panelId } >
324
+ { render ( {
325
+ props : { ...passthroughProps , ...propsWeControl } ,
326
+ slot,
327
+ defaultTag : DEFAULT_PANEL_TAG ,
328
+ features : PanelRenderFeatures ,
329
+ visible,
330
+ name : 'Disclosure.Panel' ,
331
+ } ) }
332
+ </ DisclosurePanelContext . Provider >
333
+ )
296
334
} )
297
335
298
336
// ---
0 commit comments