复杂自定义组件的可访问性
Accessibility with complex custom components
辅助功能指南是在组件发布之前发明的,所以他们总是说标签用于标识表单控件,如 <input>
或 <textarea>
等。当我有一个复杂的时候会发生什么Angular / React / ... 充当表单控件的组件?
想象一个 <custom-select>
呈现输入并将项目添加到列表中。结果 html 看起来像:
<custom-select ....>
<input ...>
</custom-select>
当我在输入中输入内容并按下回车键时,它会将该条目添加到列表中并再次呈现输入,例如:
<custom-select ....>
<span>What I typed</span>
<input ...>
</custom-select>
当然,如果我在输入中键入其他内容并按回车键,它会添加到列表中:
<custom-select ....>
<span>What I typed</span>
<span>Something else</span>
<input ...>
</custom-select>
如果我们想在表单中使用这个自定义组件,我们想像任何其他表单项一样为其添加标签,p.e:
<label for="foo">Foo</label>
<input id="foo" type="text">
<label for="select">Select a country</label>
<custom-select id="select"></custom-select>
这是否有效 a11y? Wave 工具会抱怨一个孤立的标签,而 ax 什么也没说。那么,我们可以使用普通的旧 label
来标记自定义组件以实现可访问性目的吗?我们需要将标签放在那里以保持一致性,但需要易于访问。
如果我能做到这一点,那 custom-select
也会呈现输入。该输入需要自己的标签或 aria-label,对吗?
是的,输入需要被标记。
组件不管理这个有什么原因吗?接受标签文本,然后为标签和输入对呈现正确的可访问 HTML?
所以在 React 中:
<CustomSelect labelText="Enter your destination" />
组件执行:
const id = generatedUniqueId() // This will need to be memoized in the real implementation to avoid creating new id's with every render.
...
<>
<label for={id}>{labelText}</label>
<input id={id} />
</>
至少 angular:您可以像下面这样保存 a11y:
// Custom Input HTML (Using Angular Material for eg);
// You can import the label inside the custom component and bind it to the
input field so that you can always have a new ID to every custom input
<mat-form-field [attr.aria-labelledby]="customAriaLabelledByIDs">
<mat-label *ngIf="label" [for]="customId">{{ label }}</mat-label>
<input matInput [id]="customId" />
</mat-form-field>
// In your component.ts file,
@Input() customId: string;
@Input() customAriaLabelledByIDs: string[];
combinedAriaLabelledByIDs: string;
ngOnInit() {
if (this.customAriaLabelledByIDs) {
this.combinedAriaLabelledByIDs =
this.customAriaLabelledByIDs.length === 1
? this.customAriaLabelledByIDs[0]
: this.customAriaLabelledByIDs.join(' ');
}
}
/// Wherever you use, now you will have something like this:
<your-custom-selector
[customAriaLabelledByIDs]="['id-1', 'id-2', 'id-3']"
[customId]="first-name-ID"
></your-custom-selector>
<your-custom-selector
[customAriaLabelledByIDs]="['id-4', 'id-5', 'id-6']"
[customId]="second-name-ID"
></your-custom-selector>
etc.,
您可以将多个 aria-attributes 添加到 @Input() 并从自定义组件中使用它,例如 aria-label、role、aria-expanded 等...
如果您需要对我上面提到的任何事情进行更多解释,请告诉我。很乐意提供帮助!!
辅助功能指南是在组件发布之前发明的,所以他们总是说标签用于标识表单控件,如 <input>
或 <textarea>
等。当我有一个复杂的时候会发生什么Angular / React / ... 充当表单控件的组件?
想象一个 <custom-select>
呈现输入并将项目添加到列表中。结果 html 看起来像:
<custom-select ....>
<input ...>
</custom-select>
当我在输入中输入内容并按下回车键时,它会将该条目添加到列表中并再次呈现输入,例如:
<custom-select ....>
<span>What I typed</span>
<input ...>
</custom-select>
当然,如果我在输入中键入其他内容并按回车键,它会添加到列表中:
<custom-select ....>
<span>What I typed</span>
<span>Something else</span>
<input ...>
</custom-select>
如果我们想在表单中使用这个自定义组件,我们想像任何其他表单项一样为其添加标签,p.e:
<label for="foo">Foo</label>
<input id="foo" type="text">
<label for="select">Select a country</label>
<custom-select id="select"></custom-select>
这是否有效 a11y? Wave 工具会抱怨一个孤立的标签,而 ax 什么也没说。那么,我们可以使用普通的旧 label
来标记自定义组件以实现可访问性目的吗?我们需要将标签放在那里以保持一致性,但需要易于访问。
如果我能做到这一点,那 custom-select
也会呈现输入。该输入需要自己的标签或 aria-label,对吗?
是的,输入需要被标记。
组件不管理这个有什么原因吗?接受标签文本,然后为标签和输入对呈现正确的可访问 HTML?
所以在 React 中:
<CustomSelect labelText="Enter your destination" />
组件执行:
const id = generatedUniqueId() // This will need to be memoized in the real implementation to avoid creating new id's with every render.
...
<>
<label for={id}>{labelText}</label>
<input id={id} />
</>
至少 angular:您可以像下面这样保存 a11y:
// Custom Input HTML (Using Angular Material for eg);
// You can import the label inside the custom component and bind it to the
input field so that you can always have a new ID to every custom input
<mat-form-field [attr.aria-labelledby]="customAriaLabelledByIDs">
<mat-label *ngIf="label" [for]="customId">{{ label }}</mat-label>
<input matInput [id]="customId" />
</mat-form-field>
// In your component.ts file,
@Input() customId: string;
@Input() customAriaLabelledByIDs: string[];
combinedAriaLabelledByIDs: string;
ngOnInit() {
if (this.customAriaLabelledByIDs) {
this.combinedAriaLabelledByIDs =
this.customAriaLabelledByIDs.length === 1
? this.customAriaLabelledByIDs[0]
: this.customAriaLabelledByIDs.join(' ');
}
}
/// Wherever you use, now you will have something like this:
<your-custom-selector
[customAriaLabelledByIDs]="['id-1', 'id-2', 'id-3']"
[customId]="first-name-ID"
></your-custom-selector>
<your-custom-selector
[customAriaLabelledByIDs]="['id-4', 'id-5', 'id-6']"
[customId]="second-name-ID"
></your-custom-selector>
etc.,
您可以将多个 aria-attributes 添加到 @Input() 并从自定义组件中使用它,例如 aria-label、role、aria-expanded 等...
如果您需要对我上面提到的任何事情进行更多解释,请告诉我。很乐意提供帮助!!