web 3d图形渲染器
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
4.5 KiB

  1. # label-has-associated-control
  2. Enforce that a label tag has a text label and an associated control.
  3. There are two supported ways to associate a label with a control:
  4. - Wrapping a control in a label tag.
  5. - Adding `htmlFor` to a label and assigning it a DOM ID string that indicates an input on the page.
  6. This rule checks that any `label` tag (or an indicated custom component that will output a `label` tag) either (1) wraps an `input` element (or an indicated custom component that will output an `input` tag) or (2) has an `htmlFor` attribute and that the `label` tag has text content.
  7. ## How do I resolve this error?
  8. ### Case: I just want a text label associated with an input.
  9. The simplest way to achieve an association between a label and an input is to wrap the input in the label.
  10. ```jsx
  11. <label>
  12. Surname
  13. <input type="text" />
  14. </label>
  15. ```
  16. All modern browsers and assistive technology will associate the label with the control.
  17. ### Case: The label is a sibling of the control.
  18. In this case, use `htmlFor` and an ID to associate the controls.
  19. ```jsx
  20. <label htmlFor={domId}>Surname</label>
  21. <input type="text" id={domId} />
  22. ```
  23. ### Case: My label and input components are custom components.
  24. You can configure the rule to be aware of your custom components.
  25. ```jsx
  26. <CustomInputLabel label="Surname">
  27. <CustomInput type="text" value={value} />
  28. </CustomInputLabel>
  29. ```
  30. And the configuration:
  31. ```json
  32. {
  33. "rules": {
  34. "jsx-a11y/label-has-associated-control": [ 2, {
  35. "labelComponents": ["CustomInputLabel"],
  36. "labelAttributes": ["label"],
  37. "controlComponents": ["CustomInput"],
  38. "depth": 3,
  39. }],
  40. }
  41. }
  42. ```
  43. ### Case: I have two labels for the same input
  44. If the second `label` is in a different part of the HTML, then the second one can only contain `htmlFor` but not nesting. You will probably need eslint override comment on the second label.
  45. ```jsx
  46. {/* eslint jsx-a11y/label-has-associated-control: ["error", { assert: "either" } ] */}
  47. <label htmlFor="a">
  48. Username:
  49. </label>
  50. ...
  51. <label htmlFor="a">
  52. <input id="a" />
  53. </label>
  54. ```
  55. ## How to manage IDs of `input`
  56. A common way to think of `id` with libraries like React is, `id`s should be avoided since it must be unique on the page, and components need to be reusable. Hence it is tempted to generate `id` during render-time if `id` is required. *However:*
  57. IDs shouldn't be generated in the browser, so that server and client rendering are deterministic. Render-time uuids aren't just a hack, they're actually broken and should never be used.
  58. To restate, **every ID needs to be deterministic**, on the server and the client, and guaranteed to be unique on the page. EG: For each input, a required ID prop can be passed down from as far up the tree as possible to guarantee uniqueness.
  59. ## Rule details
  60. This rule takes one optional object argument of type object:
  61. ```json
  62. {
  63. "rules": {
  64. "jsx-a11y/label-has-associated-control": [ 2, {
  65. "labelComponents": ["CustomLabel"],
  66. "labelAttributes": ["inputLabel"],
  67. "controlComponents": ["CustomInput"],
  68. "assert": "both",
  69. "depth": 3,
  70. }],
  71. }
  72. }
  73. ```
  74. `labelComponents` is a list of custom React Component names that should be checked for an associated control.
  75. `labelAttributes` is a list of attributes to check on the label component and its children for a label. Use this if you have a custom component that uses a string passed on a prop to render an HTML `label`, for example.
  76. `controlComponents` is a list of custom React Components names that will output an input element.
  77. `assert` asserts that the label has htmlFor, a nested label, both or either. Available options: `'htmlFor', 'nesting', 'both', 'either'`.
  78. `depth` (default 2, max 25) is an integer that determines how deep within a `JSXElement` label the rule should look for text content or an element with a label to determine if the `label` element will have an accessible label.
  79. ### Fail
  80. ```jsx
  81. function Foo(props) {
  82. return <label {...props} />
  83. }
  84. ```
  85. ### Succeed
  86. ```jsx
  87. function Foo(props) {
  88. const {
  89. htmlFor,
  90. ...otherProps
  91. } = props;
  92. return <label htmlFor={htmlFor} {...otherProps} />
  93. }
  94. ```
  95. ### Fail
  96. ```jsx
  97. <input type="text" />
  98. <label>Surname</label>
  99. ```
  100. ### Succeed
  101. ```jsx
  102. <label>
  103. <input type="text" />
  104. Surname
  105. </label>
  106. ```
  107. ## Accessibility guidelines
  108. - [WCAG 1.3.1](https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships)
  109. - [WCAG 3.3.2](https://www.w3.org/WAI/WCAG21/Understanding/labels-or-instructions)
  110. - [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)