复杂自定义组件的可访问性

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 等...

如果您需要对我上面提到的任何事情进行更多解释,请告诉我。很乐意提供帮助!!