Leave controls disabled by a fieldset out of the Sheet focus trap
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -137,6 +137,31 @@ describe('Sheet', () => {
|
|||||||
expect(last).toHaveFocus()
|
expect(last).toHaveFocus()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('does not stop the Tab trap on a control disabled by its fieldset', () => {
|
||||||
|
render(
|
||||||
|
<Sheet aria-label="Quest log" open onClose={() => {}}>
|
||||||
|
<fieldset disabled>
|
||||||
|
<button type="button">Disabled first</button>
|
||||||
|
</fieldset>
|
||||||
|
<button type="button">Try it</button>
|
||||||
|
<button type="button">Pass</button>
|
||||||
|
<fieldset disabled>
|
||||||
|
<button type="button">Disabled last</button>
|
||||||
|
</fieldset>
|
||||||
|
</Sheet>,
|
||||||
|
)
|
||||||
|
const first = screen.getByRole('button', { name: 'Try it' })
|
||||||
|
const last = screen.getByRole('button', { name: 'Pass' })
|
||||||
|
expect(first).toHaveFocus()
|
||||||
|
|
||||||
|
last.focus()
|
||||||
|
fireEvent.keyDown(last, { key: 'Tab' })
|
||||||
|
expect(first).toHaveFocus()
|
||||||
|
|
||||||
|
fireEvent.keyDown(first, { key: 'Tab', shiftKey: true })
|
||||||
|
expect(last).toHaveFocus()
|
||||||
|
})
|
||||||
|
|
||||||
it('wraps Tab and Shift+Tab inside the sheet', () => {
|
it('wraps Tab and Shift+Tab inside the sheet', () => {
|
||||||
render(<Harness />)
|
render(<Harness />)
|
||||||
openSheet()
|
openSheet()
|
||||||
|
|||||||
@@ -15,17 +15,19 @@ export type SheetProps = SheetName & {
|
|||||||
|
|
||||||
const focusableSelector = [
|
const focusableSelector = [
|
||||||
'a[href]',
|
'a[href]',
|
||||||
'button:not([disabled])',
|
'button',
|
||||||
'input:not([disabled])',
|
'input',
|
||||||
'select:not([disabled])',
|
'select',
|
||||||
'textarea:not([disabled])',
|
'textarea',
|
||||||
'[tabindex]',
|
'[tabindex]',
|
||||||
].join(',')
|
].join(',')
|
||||||
|
|
||||||
// Whether an element can take keyboard focus: a negative tabIndex, a hidden,
|
// Whether an element can take keyboard focus: being disabled (by its own
|
||||||
// aria-hidden or inert ancestor (or self), display: none on the way up to the
|
// attribute or a disabled fieldset), a negative tabIndex, a hidden, aria-hidden
|
||||||
// panel, or visibility: hidden all rule it out.
|
// or inert ancestor (or self), display: none on the way up to the panel, or
|
||||||
|
// visibility: hidden all rule it out.
|
||||||
function isKeyboardFocusable(element: HTMLElement, panel: HTMLElement): boolean {
|
function isKeyboardFocusable(element: HTMLElement, panel: HTMLElement): boolean {
|
||||||
|
if (element.matches(':disabled')) return false
|
||||||
if (element.tabIndex < 0) return false
|
if (element.tabIndex < 0) return false
|
||||||
if (element.closest('[hidden], [aria-hidden="true"], [inert]')) return false
|
if (element.closest('[hidden], [aria-hidden="true"], [inert]')) return false
|
||||||
if (getComputedStyle(element).visibility === 'hidden') return false
|
if (getComputedStyle(element).visibility === 'hidden') return false
|
||||||
|
|||||||
Reference in New Issue
Block a user