mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(components): added aria-level attributes for dialog and drawer headers; Fixed input-number's aria-valuenow being null (#13822)
* feat(components): [dialog] added dialog header aria-level attribute To pass accessibility tests elements with role="heading" require aria-level * feat(components): [drawer] added drawer header aria-level attribute To pass accessibility tests elements with role="heading" require aria-level * fix(components): [input-number] prevent aria-valuenow from being null To pass accessibility tests aria-valuenow cannot be null * fix(components): [input-number] fix number input when 0 and update test Fixes a bug where number input's aria-valuenow will be set to '' when input's value is 0. Also updates a failing test * refactor(components): [dialog] change default aria-level to 2 * docs(components): dialog and drawer header aria-level docs update * docs(components): change headerAriaLevel type to string * docs(components): kebab-case for docs
This commit is contained in:
committed by
GitHub
parent
b9f703094f
commit
268457135e
@@ -139,6 +139,7 @@ When using `modal` = false, please make sure that `append-to-body` was set to **
|
||||
| destroy-on-close | destroy elements in Dialog when closed | ^[boolean] | false |
|
||||
| close-icon | custom close icon, default is Close | ^[string] / ^[Component] | — |
|
||||
| z-index | same as z-index in native CSS, z-order of dialog | ^[number] | — |
|
||||
| header-aria-level ^(a11y) | header's `aria-level` attribute | ^[string] | 2 |
|
||||
|
||||
:::warning
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ Drawer provides an API called `destroyOnClose`, which is a flag variable that in
|
||||
| withHeader | Flag that controls the header section's existance, default to true, when withHeader set to false, both `title attribute` and `title slot` won't work | ^[boolean] | true |
|
||||
| modal-class | Extra class names for shadowing layer | ^[string] | — |
|
||||
| z-index | set z-index | ^[number] | — |
|
||||
| header-aria-level ^(a11y) | header's `aria-level` attribute | ^[string] | 2 |
|
||||
|
||||
:::warning
|
||||
|
||||
|
||||
@@ -44,6 +44,13 @@ export const dialogContentProps = buildProps({
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/**
|
||||
* @description header's aria-level attribute
|
||||
*/
|
||||
ariaLevel: {
|
||||
type: String,
|
||||
default: '2',
|
||||
},
|
||||
} as const)
|
||||
|
||||
export const dialogContentEmits = {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div :ref="composedDialogRef" :class="dialogKls" :style="style" tabindex="-1">
|
||||
<header ref="headerRef" :class="ns.e('header')">
|
||||
<slot name="header">
|
||||
<span role="heading" :class="ns.e('title')">
|
||||
<span role="heading" :aria-level="ariaLevel" :class="ns.e('title')">
|
||||
{{ title }}
|
||||
</span>
|
||||
</slot>
|
||||
|
||||
@@ -95,6 +95,13 @@ export const dialogProps = buildProps({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* @description header's aria-level attribute
|
||||
*/
|
||||
headerAriaLevel: {
|
||||
type: String,
|
||||
default: '2',
|
||||
},
|
||||
} as const)
|
||||
|
||||
export type DialogProps = ExtractPropTypes<typeof dialogProps>
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
:fullscreen="fullscreen"
|
||||
:show-close="showClose"
|
||||
:title="title"
|
||||
:aria-level="headerAriaLevel"
|
||||
@close="handleClose"
|
||||
>
|
||||
<template #header>
|
||||
|
||||
@@ -21,6 +21,10 @@ export const drawerProps = buildProps({
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
headerAriaLevel: {
|
||||
type: String,
|
||||
default: '2',
|
||||
},
|
||||
} as const)
|
||||
|
||||
export type DrawerProps = ExtractPropTypes<typeof drawerProps>
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
v-if="!$slots.title"
|
||||
:id="titleId"
|
||||
role="heading"
|
||||
:aria-level="headerAriaLevel"
|
||||
:class="ns.e('title')"
|
||||
>
|
||||
{{ title }}
|
||||
|
||||
@@ -44,7 +44,7 @@ describe('InputNumber.vue', () => {
|
||||
await nextTick()
|
||||
expect(wrapper.find('input').element.value).toEqual('')
|
||||
expect(wrapper.find('input').element.getAttribute('aria-valuenow')).toEqual(
|
||||
'null'
|
||||
''
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -305,7 +305,12 @@ onMounted(() => {
|
||||
} else {
|
||||
innerInput.removeAttribute('aria-valuemin')
|
||||
}
|
||||
innerInput.setAttribute('aria-valuenow', String(data.currentValue))
|
||||
innerInput.setAttribute(
|
||||
'aria-valuenow',
|
||||
data.currentValue || data.currentValue === 0
|
||||
? String(data.currentValue)
|
||||
: ''
|
||||
)
|
||||
innerInput.setAttribute('aria-disabled', String(inputNumberDisabled.value))
|
||||
if (!isNumber(modelValue) && modelValue != null) {
|
||||
let val: number | null = Number(modelValue)
|
||||
@@ -317,7 +322,7 @@ onMounted(() => {
|
||||
})
|
||||
onUpdated(() => {
|
||||
const innerInput = input.value?.input
|
||||
innerInput?.setAttribute('aria-valuenow', `${data.currentValue}`)
|
||||
innerInput?.setAttribute('aria-valuenow', `${data.currentValue ?? ''}`)
|
||||
})
|
||||
defineExpose({
|
||||
/** @description get focus the input component */
|
||||
|
||||
Reference in New Issue
Block a user