hypra

A11Y-015: form control has no label

Error: the page doesn't build until this is fixed.

A label tells everyone what to type, screen readers announce it, and clicking it puts the cursor in the control. A field always writes one; an input, select or textarea written by hand needs its own. A placeholder isn't a label: it's gone as soon as someone types. (WCAG 3.3.2)

Fails

page(title: "Shoes", description: "All our running shoes, from light racers to trail shoes.") {
  h1 "Shoes"
  input(type: "search", name: "q", placeholder: "Search shoes")
  select(name: "sort") {
    option(value: "new") "Newest"
    option(value: "price") "Price"
  }
}
error[A11Y-015]: `input` has no label
 --> page.hypra:3:3
  |
3 |   input(type: "search", name: "q", placeholder: "Search shoes")
  |   ^^^^^
  = help: use field("email", type: Email, label: "Email"), which writes the label; or add aria-label, or a label(for: ...) with the control's id
  = docs: https://hypralang.dev/rules/a11y-015/

error[A11Y-015]: `select` has no label
 --> page.hypra:4:3
  |
4 |   select(name: "sort") {
  |   ^^^^^^
  = help: use field("email", type: Email, label: "Email"), which writes the label; or add aria-label, or a label(for: ...) with the control's id
  = docs: https://hypralang.dev/rules/a11y-015/

2 errors, 0 warnings

Fixed

page(title: "Shoes", description: "All our running shoes, from light racers to trail shoes.") {
  h1 "Shoes"
  label(for: "q") "Search shoes"
  input(id: "q", type: "search", name: "q")
  label {
    "Sort by "
    select(name: "sort") {
      option(value: "new") "Newest"
      option(value: "price") "Price"
    }
  }
}

A control is labelled by a label(for: ...) with its id, by a label around it, or by aria-label. Hidden inputs and buttons like input(type: "submit") don't need one. In a form, field writes the label, the input and the checks in one go.