fix: publish modal a11y -- dialog-scoped Tab guard + correct first-focus in OutcomeModal
This commit is contained in:
parent
9603d421b6
commit
f92ac7a509
2 changed files with 6 additions and 2 deletions
|
|
@ -33,6 +33,7 @@
|
||||||
<legend class="form-label">What kind of story is this?</legend>
|
<legend class="form-label">What kind of story is this?</legend>
|
||||||
<div class="type-toggle flex gap-sm">
|
<div class="type-toggle flex gap-sm">
|
||||||
<button
|
<button
|
||||||
|
ref="firstFocusRef"
|
||||||
:class="['btn', 'type-btn', postType === 'recipe_success' ? 'type-btn-active' : 'btn-secondary']"
|
:class="['btn', 'type-btn', postType === 'recipe_success' ? 'type-btn-active' : 'btn-secondary']"
|
||||||
:aria-pressed="postType === 'recipe_success'"
|
:aria-pressed="postType === 'recipe_success'"
|
||||||
@click="postType = 'recipe_success'"
|
@click="postType = 'recipe_success'"
|
||||||
|
|
@ -57,7 +58,6 @@
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="outcome-title"
|
id="outcome-title"
|
||||||
ref="firstFocusRef"
|
|
||||||
v-model="title"
|
v-model="title"
|
||||||
class="form-input"
|
class="form-input"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -163,7 +163,7 @@ const submitError = ref<string | null>(null)
|
||||||
const submitSuccess = ref<string | null>(null)
|
const submitSuccess = ref<string | null>(null)
|
||||||
|
|
||||||
const dialogRef = ref<HTMLElement | null>(null)
|
const dialogRef = ref<HTMLElement | null>(null)
|
||||||
const firstFocusRef = ref<HTMLInputElement | null>(null)
|
const firstFocusRef = ref<HTMLButtonElement | null>(null)
|
||||||
let previousFocus: HTMLElement | null = null
|
let previousFocus: HTMLElement | null = null
|
||||||
|
|
||||||
function getFocusables(): HTMLElement[] {
|
function getFocusables(): HTMLElement[] {
|
||||||
|
|
@ -181,6 +181,8 @@ function handleKeydown(e: KeyboardEvent) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (e.key !== 'Tab') return
|
if (e.key !== 'Tab') return
|
||||||
|
// Only intercept Tab when focus is inside this dialog
|
||||||
|
if (!dialogRef.value?.contains(document.activeElement)) return
|
||||||
|
|
||||||
const focusables = getFocusables()
|
const focusables = getFocusables()
|
||||||
if (focusables.length === 0) return
|
if (focusables.length === 0) return
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,8 @@ function handleKeydown(e: KeyboardEvent) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (e.key !== 'Tab') return
|
if (e.key !== 'Tab') return
|
||||||
|
// Only intercept Tab when focus is inside this dialog
|
||||||
|
if (!dialogRef.value?.contains(document.activeElement)) return
|
||||||
|
|
||||||
const focusables = getFocusables()
|
const focusables = getFocusables()
|
||||||
if (focusables.length === 0) return
|
if (focusables.length === 0) return
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue