---
name: html-template
description: This skill should be used when writing or reviewing HTML templates to ensure proper E2E testing attributes (data-what, data-which) and ARIA accessibility attributes are included. Use when creating interactive elements like buttons, inputs, links, forms, dialogs, or any HTML markup requiring testing and accessibility compliance. Works seamlessly with the angular-template skill.
---

# HTML Template - Testing & Accessibility Attributes

This skill should be used when writing or reviewing HTML templates to ensure proper testing and accessibility attributes are included.

## When to Use This Skill

Use this skill when:
- Writing or modifying Angular component templates
- Creating any HTML templates or markup
- Reviewing code for testing and accessibility compliance
- Adding interactive elements (buttons, inputs, links, etc.)
- Implementing forms, lists, navigation, or dialogs

**Works seamlessly with:**
- **[angular-template](../angular-template/SKILL.md)** - Angular template syntax, control flow, and modern patterns
- **[tailwind](../tailwind/SKILL.md)** - ISA design system styling for visual design
- **[logging](../logging/SKILL.md)** - MANDATORY logging in all Angular components using `@isa/core/logging`

## Overview

This skill provides comprehensive guidance for two critical HTML attribute categories:

### 1. E2E Testing Attributes
Enable automated end-to-end testing by providing stable selectors for QA automation:
- **`data-what`**: Semantic description of element's purpose
- **`data-which`**: Unique identifier for specific instances
- **`data-*`**: Additional contextual information

### 2. ARIA Accessibility Attributes
Ensure web applications are accessible to all users, including those using assistive technologies:
- **Roles**: Define element purpose (button, navigation, dialog, etc.)
- **Properties**: Provide additional context (aria-label, aria-describedby)
- **States**: Indicate dynamic states (aria-expanded, aria-disabled)
- **Live Regions**: Announce dynamic content changes

## Why Both Are Essential

- **E2E Attributes**: Enable reliable automated testing without brittle CSS or XPath selectors
- **ARIA Attributes**: Ensure compliance with WCAG standards and improve user experience for people with disabilities
- **Together**: Create robust, testable, and accessible web applications

## Quick Reference

### Button Example
```html
<button
  type="button"
  (click)="onSubmit()"
  data-what="submit-button"
  data-which="registration-form"
  aria-label="Submit registration form">
  Submit
</button>
```

### Input Example
```html
<input
  type="text"
  [(ngModel)]="email"
  data-what="email-input"
  data-which="registration-form"
  aria-label="Email address"
  aria-describedby="email-hint"
  aria-required="true" />
<span id="email-hint">We'll never share your email</span>
```

### Dynamic List Example
```html
@for (item of items; track item.id) {
  <li
    (click)="selectItem(item)"
    data-what="list-item"
    [attr.data-which]="item.id"
    [attr.data-status]="item.status"
    [attr.aria-label]="'Select ' + item.name"
    role="button"
    tabindex="0">
    {{ item.name }}
  </li>
}
```

### Link Example
```html
<a
  [routerLink]="['/orders', orderId]"
  data-what="order-link"
  [attr.data-which]="orderId"
  [attr.aria-label]="'View order ' + orderNumber">
  View Order #{{ orderNumber }}
</a>
```

### Dialog Example
```html
<div
  class="dialog"
  data-what="confirmation-dialog"
  data-which="delete-item"
  role="dialog"
  aria-modal="true"
  aria-labelledby="dialog-title"
  aria-describedby="dialog-description">

  <h2 id="dialog-title">Confirm Deletion</h2>
  <p id="dialog-description">Are you sure you want to delete this item?</p>

  <button
    (click)="confirm()"
    data-what="confirm-button"
    data-which="delete-dialog"
    aria-label="Confirm deletion">
    Delete
  </button>

  <button
    (click)="cancel()"
    data-what="cancel-button"
    data-which="delete-dialog"
    aria-label="Cancel deletion">
    Cancel
  </button>
</div>
```

## Common Patterns by Element Type

### Interactive Elements That Need Attributes

**Required attributes for:**
- Buttons (`<button>`, `<ui-button>`, custom button components)
- Form inputs (`<input>`, `<textarea>`, `<select>`)
- Links (`<a>`, `[routerLink]`)
- Clickable elements (elements with `(click)` handlers)
- Custom interactive components
- List items in dynamic lists
- Navigation items
- Dialog/modal controls

### Naming Conventions

**E2E `data-what` patterns:**
- `*-button` (submit-button, cancel-button, delete-button)
- `*-input` (email-input, search-input, quantity-input)
- `*-link` (product-link, order-link, customer-link)
- `*-item` (list-item, menu-item, card-item)
- `*-dialog` (confirm-dialog, error-dialog, info-dialog)
- `*-dropdown` (status-dropdown, category-dropdown)

**E2E `data-which` guidelines:**
- Use unique identifiers: `data-which="primary"`, `data-which="customer-list"`
- Bind dynamically for lists: `[attr.data-which]="item.id"`
- Combine with context: `data-which="customer-{{ customerId }}-edit"`

**ARIA role patterns:**
- Interactive elements: `button`, `link`, `menuitem`
- Structural: `navigation`, `main`, `complementary`, `contentinfo`
- Widget: `dialog`, `alertdialog`, `tooltip`, `tablist`, `tab`
- Landmark: `banner`, `search`, `form`, `region`

## Best Practices

### E2E Attributes
1. ✅ Add to ALL interactive elements
2. ✅ Use kebab-case for `data-what` values
3. ✅ Ensure `data-which` is unique within the view
4. ✅ Use Angular binding for dynamic values: `[attr.data-*]`
5. ✅ Avoid including sensitive data in attributes
6. ✅ Document complex attribute patterns in template comments

### ARIA Attributes
1. ✅ Use semantic HTML first (use `<button>` instead of `<div role="button">`)
2. ✅ Provide text alternatives for all interactive elements
3. ✅ Ensure proper keyboard navigation (tabindex, focus management)
4. ✅ Use `aria-label` when visual label is missing
5. ✅ Use `aria-labelledby` to reference existing visible labels
6. ✅ Keep ARIA attributes in sync with visual states
7. ✅ Test with screen readers (NVDA, JAWS, VoiceOver)

### Combined Best Practices
1. ✅ Add both E2E and ARIA attributes to every interactive element
2. ✅ Keep attributes close together in the HTML for readability
3. ✅ Update tests to use `data-what` and `data-which` selectors
4. ✅ Validate coverage: all interactive elements should have both types
5. ✅ Review with QA and accessibility teams

## Detailed References

For comprehensive guides, examples, and patterns, see:

- **[E2E Testing Attributes](references/e2e-attributes.md)** - Complete E2E attribute patterns and conventions
- **[ARIA Accessibility Attributes](references/aria-attributes.md)** - Comprehensive ARIA guidance and WCAG compliance
- **[Combined Patterns](references/combined-patterns.md)** - Real-world examples with both attribute types

## Project-Specific Links

- **Testing Guidelines**: `docs/guidelines/testing.md` - Project testing standards including E2E attributes
- **CLAUDE.md**: Project conventions and requirements
- **Angular Template Skill**: `.claude/skills/angular-template` - For Angular-specific syntax

## Validation Checklist

Before considering template complete:
- [ ] All buttons have `data-what`, `data-which`, and `aria-label`
- [ ] All inputs have `data-what`, `data-which`, and appropriate ARIA attributes
- [ ] All links have `data-what`, `data-which`, and descriptive ARIA labels
- [ ] Dynamic lists use `[attr.data-*]` bindings with unique identifiers
- [ ] Dialogs have proper ARIA roles and relationships
- [ ] Forms have proper field associations and error announcements
- [ ] Interactive elements are keyboard accessible (tabindex where needed)
- [ ] No duplicate `data-which` values within the same view
- [ ] Screen reader testing completed (if applicable)

## Example: Complete Form

```html
<form
  data-what="registration-form"
  data-which="user-signup"
  role="form"
  aria-labelledby="form-title">

  <h2 id="form-title">User Registration</h2>

  <div class="form-field">
    <label for="username-input">Username</label>
    <input
      id="username-input"
      type="text"
      [(ngModel)]="username"
      data-what="username-input"
      data-which="registration-form"
      aria-required="true"
      aria-describedby="username-hint" />
    <span id="username-hint">Must be at least 3 characters</span>
  </div>

  <div class="form-field">
    <label for="email-input">Email</label>
    <input
      id="email-input"
      type="email"
      [(ngModel)]="email"
      data-what="email-input"
      data-which="registration-form"
      aria-required="true"
      [attr.aria-invalid]="emailError ? 'true' : null"
      aria-describedby="email-error" />
    @if (emailError) {
      <span
        id="email-error"
        role="alert"
        aria-live="polite">
        {{ emailError }}
      </span>
    }
  </div>

  <div class="form-actions">
    <button
      type="submit"
      (click)="onSubmit()"
      data-what="submit-button"
      data-which="registration-form"
      [attr.aria-disabled]="!isValid"
      aria-label="Submit registration form">
      Register
    </button>

    <button
      type="button"
      (click)="onCancel()"
      data-what="cancel-button"
      data-which="registration-form"
      aria-label="Cancel registration">
      Cancel
    </button>
  </div>
</form>
```

## Remember

- **Always use both E2E and ARIA attributes together**
- **E2E attributes enable automated testing** - your QA team relies on them
- **ARIA attributes enable accessibility** - legal requirement and right thing to do
- **Test with real users and assistive technologies** - automated checks aren't enough
- **Keep attributes up-to-date** - maintain as code changes

---

**This skill works automatically with Angular templates. Both E2E and ARIA attributes should be added to every interactive element.**
