Context
fs-dialog (@script-development/fs-dialog) renders the host <dialog> element with no attribute-forwarding hook:
// node_modules/@script-development/fs-dialog/dist/index.mjs:51-64
h("dialog", {style, onClick, onCancel, onVnodeMounted}, h(Suspense, ...))
dialog.open(component, props) forwards props only to the inner component, never to the <dialog> host. As a result, screen readers announce these dialogs as a generic "dialog" with no accessible name or description until the consumer manually walks closest('dialog') from a template ref and calls setAttribute(...) itself.
Repro / why it matters
Surfaced in ublgenie PR #167 (UBL-0027, Dialog a11y): both ConfirmDialog and FormDialog had to wire aria-labelledby (Phase 1) and aria-describedby on ConfirmDialog (Phase 2) consumer-side, like this:
onMounted(() => {
const hostDialog = root.value?.closest('dialog');
hostDialog?.setAttribute('aria-labelledby', titleId);
hostDialog?.setAttribute('aria-describedby', messageId);
});
Every fs-packages-adopting territory will hit the same pattern — at least 6 territories on the war-room map will need the same workaround. Goosterhof flagged this as a non-blocking ask on PR #167 (review observation 3): "the wiring genuinely belongs in fs-dialog as an aria-labelledby option on dialog.open()".
Proposed shape
Extend dialog.open() (and any sibling open-shape APIs) to accept ARIA host options that get applied to the <dialog> element itself, not the inner component. Sketch:
dialog.open(MyDialog, props, {
ariaLabelledBy: 'my-title-id',
ariaDescribedBy: 'my-message-id',
});
Inside fs-dialog, set these on the <dialog> vnode in the same h("dialog", {...}) call. Optional shape variant: accept ariaLabel directly for label-only cases that don't need a title element.
Acceptance
dialog.open() accepts host-level ARIA attributes alongside component props.
- Existing call sites that don't pass the new options continue to work unchanged.
- Once shipped, ublgenie's
closest('dialog')?.setAttribute(...) calls in ConfirmDialog.vue / FormDialog.vue can be deleted in favor of passing ids through the open API.
References
- Back-to-code/ublgenie-app PR #167 (Dialog a11y wiring) — consumer-side workaround that this issue would obsolete.
- WAI-ARIA Authoring Practices — Dialog (Modal) Pattern:
aria-labelledby + aria-describedby are the canonical pairing for native <dialog> elements.
Context
fs-dialog(@script-development/fs-dialog) renders the host<dialog>element with no attribute-forwarding hook:dialog.open(component, props)forwardspropsonly to the inner component, never to the<dialog>host. As a result, screen readers announce these dialogs as a generic "dialog" with no accessible name or description until the consumer manually walksclosest('dialog')from a template ref and callssetAttribute(...)itself.Repro / why it matters
Surfaced in ublgenie PR #167 (UBL-0027, Dialog a11y): both
ConfirmDialogandFormDialoghad to wirearia-labelledby(Phase 1) andaria-describedbyonConfirmDialog(Phase 2) consumer-side, like this:onMounted(() => { const hostDialog = root.value?.closest('dialog'); hostDialog?.setAttribute('aria-labelledby', titleId); hostDialog?.setAttribute('aria-describedby', messageId); });Every fs-packages-adopting territory will hit the same pattern — at least 6 territories on the war-room map will need the same workaround. Goosterhof flagged this as a non-blocking ask on PR #167 (review observation 3): "the wiring genuinely belongs in fs-dialog as an
aria-labelledbyoption ondialog.open()".Proposed shape
Extend
dialog.open()(and any sibling open-shape APIs) to accept ARIA host options that get applied to the<dialog>element itself, not the inner component. Sketch:Inside fs-dialog, set these on the
<dialog>vnode in the sameh("dialog", {...})call. Optional shape variant: acceptariaLabeldirectly for label-only cases that don't need a title element.Acceptance
dialog.open()accepts host-level ARIA attributes alongside component props.closest('dialog')?.setAttribute(...)calls inConfirmDialog.vue/FormDialog.vuecan be deleted in favor of passing ids through the open API.References
aria-labelledby+aria-describedbyare the canonical pairing for native<dialog>elements.