@workday/canvas-kit-docs 16.0.14 → 16.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13367,6 +13367,26 @@ export const docs = (typeof window !== 'undefined' && window.__docs) ||
13367
13367
  "kind": "string",
13368
13368
  "value": "tables"
13369
13369
  },
13370
+ {
13371
+ "kind": "string",
13372
+ "value": "expandable-rows"
13373
+ },
13374
+ {
13375
+ "kind": "string",
13376
+ "value": "nested-rows"
13377
+ },
13378
+ {
13379
+ "kind": "string",
13380
+ "value": "selectable-rows"
13381
+ },
13382
+ {
13383
+ "kind": "string",
13384
+ "value": "filterable-column-headers"
13385
+ },
13386
+ {
13387
+ "kind": "string",
13388
+ "value": "sortable-column-headers"
13389
+ },
13370
13390
  {
13371
13391
  "kind": "string",
13372
13392
  "value": "popups"
@@ -13431,6 +13451,26 @@ export const docs = (typeof window !== 'undefined' && window.__docs) ||
13431
13451
  "kind": "string",
13432
13452
  "value": "tables"
13433
13453
  },
13454
+ {
13455
+ "kind": "string",
13456
+ "value": "expandable-rows"
13457
+ },
13458
+ {
13459
+ "kind": "string",
13460
+ "value": "nested-rows"
13461
+ },
13462
+ {
13463
+ "kind": "string",
13464
+ "value": "selectable-rows"
13465
+ },
13466
+ {
13467
+ "kind": "string",
13468
+ "value": "filterable-column-headers"
13469
+ },
13470
+ {
13471
+ "kind": "string",
13472
+ "value": "sortable-column-headers"
13473
+ },
13434
13474
  {
13435
13475
  "kind": "string",
13436
13476
  "value": "popups"
@@ -13459,6 +13499,23 @@ export const docs = (typeof window !== 'undefined' && window.__docs) ||
13459
13499
  }
13460
13500
  }
13461
13501
  },
13502
+ {
13503
+ "name": "TABLE_PATTERN_SCENARIOS",
13504
+ "fileName": "/home/runner/work/canvas-kit/canvas-kit/modules/mcp/lib/accessibility-enums.ts",
13505
+ "description": "Pattern pages under Guides/Accessibility/Table Patterns, including the overview index.",
13506
+ "declarations": [
13507
+ {
13508
+ "name": "TABLE_PATTERN_SCENARIOS",
13509
+ "filePath": "/home/runner/work/canvas-kit/canvas-kit/modules/mcp/lib/accessibility-enums.ts"
13510
+ }
13511
+ ],
13512
+ "tags": {},
13513
+ "type": {
13514
+ "kind": "unknown",
13515
+ "value": "unknown",
13516
+ "text": "readonly AccessibilityScenario[]"
13517
+ }
13518
+ },
13462
13519
  {
13463
13520
  "name": "ACCESSIBILITY_COMPONENTS",
13464
13521
  "fileName": "/home/runner/work/canvas-kit/canvas-kit/modules/mcp/lib/accessibility-enums.ts",
@@ -13960,7 +14017,7 @@ export const docs = (typeof window !== 'undefined' && window.__docs) ||
13960
14017
  "value": {
13961
14018
  "kind": "symbol",
13962
14019
  "name": "AccessibilityScenario",
13963
- "value": "\"aria-live\" | \"overview\" | \"page-structure\" | \"tables\" | \"popups\" | \"headers\" | \"side-panel\" | \"windows-high-contrast\" | \"forms\" | \"color-contrast\""
14020
+ "value": "\"aria-live\" | \"overview\" | \"page-structure\" | \"tables\" | \"expandable-rows\" | \"nested-rows\" | \"selectable-rows\" | \"filterable-column-headers\" | \"sortable-column-headers\" | ... 5 more ... | \"color-contrast\""
13964
14021
  }
13965
14022
  }
13966
14023
  }
@@ -14009,7 +14066,7 @@ export const docs = (typeof window !== 'undefined' && window.__docs) ||
14009
14066
  "type": {
14010
14067
  "kind": "symbol",
14011
14068
  "name": "AccessibilityScenario",
14012
- "value": "\"aria-live\" | \"overview\" | \"page-structure\" | \"tables\" | \"popups\" | \"headers\" | \"side-panel\" | \"windows-high-contrast\" | \"forms\" | \"color-contrast\""
14069
+ "value": "\"aria-live\" | \"overview\" | \"page-structure\" | \"tables\" | \"expandable-rows\" | \"nested-rows\" | \"selectable-rows\" | \"filterable-column-headers\" | \"sortable-column-headers\" | ... 5 more ... | \"color-contrast\""
14013
14070
  },
14014
14071
  "description": "",
14015
14072
  "declarations": [
@@ -14040,7 +14097,7 @@ export const docs = (typeof window !== 'undefined' && window.__docs) ||
14040
14097
  "value": {
14041
14098
  "kind": "symbol",
14042
14099
  "name": "AccessibilityScenario",
14043
- "value": "\"aria-live\" | \"overview\" | \"page-structure\" | \"tables\" | \"popups\" | \"headers\" | \"side-panel\" | \"windows-high-contrast\" | \"forms\" | \"color-contrast\""
14100
+ "value": "\"aria-live\" | \"overview\" | \"page-structure\" | \"tables\" | \"expandable-rows\" | \"nested-rows\" | \"selectable-rows\" | \"filterable-column-headers\" | \"sortable-column-headers\" | ... 5 more ... | \"color-contrast\""
14044
14101
  }
14045
14102
  }
14046
14103
  }
@@ -18,11 +18,11 @@ export const packageJSONFile = `{
18
18
  "@emotion/react": "11.11.4",
19
19
  "@types/react": "18.2.60",
20
20
  "@types/react-dom": "18.2.19",
21
- "@workday/canvas-kit-labs-react": "16.0.14",
22
- "@workday/canvas-kit-preview-react": "16.0.14",
23
- "@workday/canvas-kit-react": "16.0.14",
24
- "@workday/canvas-kit-react-fonts": "^16.0.14",
25
- "@workday/canvas-kit-styling": "16.0.14",
21
+ "@workday/canvas-kit-labs-react": "16.0.16",
22
+ "@workday/canvas-kit-preview-react": "16.0.16",
23
+ "@workday/canvas-kit-react": "16.0.16",
24
+ "@workday/canvas-kit-react-fonts": "^16.0.16",
25
+ "@workday/canvas-kit-styling": "16.0.16",
26
26
  "@workday/canvas-system-icons-web": "^5.0.3",
27
27
  "@workday/canvas-expressive-icons-web": "1.0.1",
28
28
  "@workday/canvas-tokens-web": "4.4.0-beta.11"
@@ -19,11 +19,11 @@ export const packageJSONFile = `{
19
19
  "@emotion/react": "11.11.4",
20
20
  "@types/react": "18.2.60",
21
21
  "@types/react-dom": "18.2.19",
22
- "@workday/canvas-kit-labs-react": "16.0.14",
23
- "@workday/canvas-kit-preview-react": "16.0.14",
24
- "@workday/canvas-kit-react": "16.0.14",
25
- "@workday/canvas-kit-react-fonts": "^16.0.14",
26
- "@workday/canvas-kit-styling": "16.0.14",
22
+ "@workday/canvas-kit-labs-react": "16.0.16",
23
+ "@workday/canvas-kit-preview-react": "16.0.16",
24
+ "@workday/canvas-kit-react": "16.0.16",
25
+ "@workday/canvas-kit-react-fonts": "^16.0.16",
26
+ "@workday/canvas-kit-styling": "16.0.16",
27
27
  "@workday/canvas-system-icons-web": "^5.0.3",
28
28
  "@workday/canvas-expressive-icons-web": "1.0.1",
29
29
  "@workday/canvas-tokens-web": "4.4.0-beta.11"
@@ -44,10 +44,6 @@ hooks. **Tradeoff:** the popup is constrained by ancestor `overflow` and positio
44
44
 
45
45
  <ExampleCodeBlock code={InlinePopupNoPortal} />
46
46
 
47
- For the same reading-order goal using a **portaled** popup mounted into a sentinel next to the
48
- trigger (with `PopupStack.pushStackContext`), see
49
- [**Testing > Inline Portals**](?path=/docs/guides-accessibility-testing-inline-portals--docs).
50
-
51
47
  ## 2. Reading order with `aria-owns`
52
48
 
53
49
  You can keep the default portal (content at the bottom of `body`) and still try to **re-parent** the
@@ -67,6 +63,6 @@ that card as “owned” by the trigger for browsing and announcements.
67
63
  The Canvas Kit [**Dialog**](?path=/docs/components-popups-dialog--docs) builds this pattern in.
68
64
 
69
65
  Another `aria-owns` example:
70
- [Advanced Tables > Table With Filterable Column Headers](?path=/docs/guides-accessibility-examples-advanced-tables--docs#filterable-column-headers).
66
+ [Table Patterns > Filterable Column Headers](?path=/docs/guides-accessibility-table-patterns-filterable-column-headers--docs).
71
67
 
72
68
  <ExampleCodeBlock code={PopupAriaOwns} />
@@ -0,0 +1,27 @@
1
+ import {ExampleCodeBlock} from '@workday/canvas-kit-docs';
2
+
3
+ import {ExpandableRows} from '../examples/Table/WithExpandableRows';
4
+
5
+
6
+ ## Expandable Rows
7
+
8
+ Expandable Rows combines the likes of an accordion with tabular data tables. Column 1 renders icon
9
+ buttons with 2 states, a collapsed and expanded state. A new row that spans the entire width of the
10
+ table is added to the table just after the expanded row.
11
+
12
+ - The `aria-expanded` property is added to the chevron button to communicate this state to screen
13
+ reader users.
14
+ - A Canvas accessible `Tooltip` component is used to assign names to each icon button based on the
15
+ most useful value in the row. In this example, we combined the car make (in column 1) and model
16
+ (in column 2) together. This allows everyone to view the name of the icon buttons by hovering the
17
+ mouse or focusing with the keyboard.
18
+ - The expanded row uses `colspan` to span the entire width of the table and support screen readers.
19
+ This space provides flexibility to show headings, lists, and other structured content for the
20
+ table row above.
21
+ - There is no explicit relationship between a row of cells and the spanned content below it. The
22
+ spanned content is assumed to belong to the row of cells above it, based on established accordion
23
+ patterns and logical reading order of content rendered to the screen.
24
+ - Outlining hierarchy with additional nested rows in the table is not supported for screen readers
25
+ in this example.
26
+
27
+ <ExampleCodeBlock code={ExpandableRows} />
@@ -0,0 +1,37 @@
1
+ import {ExampleCodeBlock} from '@workday/canvas-kit-docs';
2
+
3
+ import {FilterableColumnHeaders} from '../examples/Table/WithColumnHeaderFilters';
4
+
5
+
6
+ ## Filterable Column Headers
7
+
8
+ In this example, we demonstrate using the `Popup` component in each column header allowing users to
9
+ search and filter the data on the table. The `Popup` component relies on React Portals to render the
10
+ popup elements at the bottom of the browser's DOM presenting 2 key challenges for accessibility:
11
+
12
+ 1. Keyboard focus order of the elements in the popup,
13
+ 2. Screen readers' reading order of the content rendered in the browser.
14
+
15
+ Here's what we did about it:
16
+
17
+ - Canvas Kit includes a `usePopupModel` hook, with quite a few additional hooks developers can add
18
+ to their models. In particular, the `useFocusRedirect` hook manages keyboard focus between the
19
+ `<Popup.Target>` button and the popup content.
20
+ - The `useInitialFocus` hook allows developers to specify which element receives keyboard focus when
21
+ the popup appears. In this example, we auto-focused the search input field.
22
+ - To address the reading order of content, we set the `aria-owns` property onto the parent
23
+ `<Table.Header>` component (`<th>` DOM element) with 2 unique `id` values. The first `id` refers
24
+ to the `<Popup.Target>` button and the second refers to the `<Popup.Card>` container element. This
25
+ manually reassigns the column header's `<Popup.Target>` button and the `Popup` contents as
26
+ siblings in the browser's accessibility tree hierarchy. Screen readers **should** read the column
27
+ header buttons and the popup content in sequential order even though they are not siblings in the
28
+ DOM.
29
+ - The `type='description'` variant of the Canvas `Tooltip` is used to communicate the filtered state
30
+ of the column header, and assigned to the accessible description of the column header
31
+ `<TertiaryButton>` component.
32
+ - The `AriaLiveRegion` component is used to render the "X of Y items" status inside the table
33
+ caption. This enables screen readers to automatically describe the filter state changes of the
34
+ table content to users in real time. We recommend validating whether this use of a live region is
35
+ well supported for your screen reader and browser combinations first.
36
+
37
+ <ExampleCodeBlock code={FilterableColumnHeaders} />
@@ -0,0 +1,38 @@
1
+ import {ExampleCodeBlock} from '@workday/canvas-kit-docs';
2
+
3
+ import {NestedRows} from '../examples/Table/WithNestedRows';
4
+
5
+
6
+ ## Nested Rows
7
+
8
+ Nested Rows shows a hierarchy of related records in **one table**, using additional `<tr>` elements
9
+ for child rows. Expanding a project reveals its phases; expanding a phase reveals its tasks. The
10
+ chevron and name share the Name cell so they indent together. Collapsing a parent hides its
11
+ descendants even if a child was previously expanded.
12
+
13
+ This is a different pattern from
14
+ [Expandable Rows](?path=/docs/guides-accessibility-table-patterns-expandable-rows--docs). That
15
+ example inserts a `colspan` panel with extra content for a single parent row. It does **not** add
16
+ nested table rows. Use Nested Rows when the children are themselves tabular records (same columns at
17
+ every level). Use Expandable Rows when the extra content is not a row of the same table.
18
+
19
+ - Child rows are siblings in the same `<tbody>`, not a nested `<table>` and not extra `<tbody>`
20
+ elements used to fake a tree.
21
+ - The Name cell is the tree column: it holds the chevron `TertiaryButton` and the row name together
22
+ so the control stays next to the label it expands. Leaf rows keep an empty slot the same width as
23
+ the button so names line up with their siblings.
24
+ - The `aria-expanded` property is added to the chevron button to communicate this state to screen
25
+ reader users.
26
+ - A Canvas Kit `Tooltip` names each chevron **Project**, **Phase**, or **Task** based on the row's
27
+ depth. The visible name stays in the row header, so the button name describes the _kind_ of row
28
+ rather than repeating the label.
29
+ - Since those button names are not unique, we added `aria-describedby` to each chevron, referencing
30
+ the unique `id` on the name text in the same cell. That gives screen readers the specific project
31
+ or phase the control belongs to, similar to the
32
+ [Selectable Rows](?path=/docs/guides-accessibility-table-patterns-selectable-rows--docs)
33
+ checkboxes.
34
+ - `aria-level` is set on each `Table.Row` (`1` = project, `2` = phase, `3` = task) to describe
35
+ depth. Support for `aria-level` on HTML table rows is uneven across screen readers and browsers.
36
+ Validate the combinations you support. This is a research example, not a Canvas Kit primitive.
37
+
38
+ <ExampleCodeBlock code={NestedRows} />
@@ -0,0 +1,28 @@
1
+ ## Advanced Table Examples
2
+
3
+ Tables should only be used to organize data that has a clear relationship between rows and columns,
4
+ like a calendar or a schedule. Never use a table just for page layout.
5
+
6
+ When you use the proper HTML table markup, a screen reader can help a user navigate the table. It
7
+ will automatically read the column and row headers as they move through the data, so they always
8
+ know what information they're looking at.
9
+
10
+ - All tables should have a clear header and a descriptive title.
11
+ - Keep your tables simple. If a table is too complex, it might be better to break it up into several
12
+ smaller tables or use a different format.
13
+
14
+ Out of the box, `Table` is a lightweight compound component with a high degree of flexibility, but
15
+ not much functionality outside of providing a basic table layout. This flexibility lets developers
16
+ implement common features, such as selecting rows and sorting columns, on top of `Table` to meet
17
+ their specific application needs.
18
+
19
+ The Workday Accessibility Team has researched and developed the following examples to demonstrate
20
+ how to build these accessible table patterns. We've listed the specific considerations and decisions
21
+ we've made for each of the examples.
22
+
23
+ - [Expandable Rows](?path=/docs/guides-accessibility-table-patterns-expandable-rows--docs)
24
+ - [Nested Rows](?path=/docs/guides-accessibility-table-patterns-nested-rows--docs)
25
+ - [Selectable Rows](?path=/docs/guides-accessibility-table-patterns-selectable-rows--docs)
26
+ - [Filterable Column Headers](?path=/docs/guides-accessibility-table-patterns-filterable-column-headers--docs)
27
+ - [Sortable Column Headers](?path=/docs/guides-accessibility-table-patterns-sortable-column-headers--docs)
28
+ - [With Form Fields](?path=/docs/guides-accessibility-table-patterns-with-form-fields--docs)
@@ -0,0 +1,27 @@
1
+ import {ExampleCodeBlock} from '@workday/canvas-kit-docs';
2
+
3
+ import {SelectableRows} from '../examples/Table/WithSelectableRows';
4
+
5
+
6
+ ## Selectable Rows
7
+
8
+ Using a `Checkbox` labeled "Select All" inside of a column header can be a confusing experience for
9
+ screen reader users. Screen readers will automatically announce the "Select All" label in the column
10
+ header each time users are reading any of the Check boxes in the first column. For instance, the
11
+ `Checkbox` in row 4 is definitely not going to select all of the rows. Here is what we did about it:
12
+
13
+ - We intentionally rendered row 1, column 1 as a standard `<td>` element so screen readers won't
14
+ automatically announce the "Select All" label while reading cells in column 1.
15
+ - Our research found that VoiceOver (MacOS v12.7, Safari v17.1) persistently announce "Select All"
16
+ despite using the `<td>` element because of the optional `<thead>` element in the table. We
17
+ omitted the optional `<thead>` and `<tbody>` elements from this example for that reason.
18
+ - We used Canvas Kit's `Tooltip` component to assign concise names to each Checkbox, describing
19
+ their purpose of selecting rows. This allows everyone to view the name of the checkboxes by
20
+ hovering the mouse or focusing with the keyboard.
21
+ - Since each checkbox is not uniquely labeled, we added `aria-describedby` to the checkbox,
22
+ referencing the unique `id` of the row header cell. This practice gives screen readers more
23
+ context about which value each checkbox is refering to.
24
+ - We rendered the cells in column 2 as the row headers for the table, enabling screen readers to
25
+ automatically announce the topping name even while reading down the Amounts in column 3.
26
+
27
+ <ExampleCodeBlock code={SelectableRows} />
@@ -0,0 +1,23 @@
1
+ import {ExampleCodeBlock} from '@workday/canvas-kit-docs';
2
+
3
+ import {SortableColumnHeaders} from '../examples/Table/WithSortableColumnHeaders';
4
+
5
+
6
+ ## Sortable Column Headers
7
+
8
+ The challenge in this example is to provide all of the necessary information about the interactive
9
+ column headers, the sort state of the column, and instructions about how the table will be sorted
10
+ without giving too much information to users while reading the data cells below.
11
+
12
+ - The `aria-sort` property has been added to each of the `<Table.Header>` components (`<th>` DOM
13
+ element) and updated to `ascending` or `descending` to reflect the current sort state. We
14
+ recommend validating whether this property is well supported for your screen reader and browser
15
+ combinations first.
16
+ - A `<TertiaryButton>` describing the column name is used inside of the `<Table.Header>` component.
17
+ - The `description` variant of the Canvas `Tooltip` component is applied to the button in the column
18
+ header and applied to the accessible description of the button with the `aria-description`
19
+ property. This is used to describe how the column will be sorted when pressed and screen readers
20
+ will only read this description while focusing on the column headers, not while reading the data
21
+ cells below.
22
+
23
+ <ExampleCodeBlock code={SortableColumnHeaders} />
@@ -1,5 +1,6 @@
1
1
  import {ExampleCodeBlock} from '@workday/canvas-kit-docs';
2
- import WithFormFields from './examples/Table/WithFormFields';
2
+
3
+ import {WithFormFields} from '../examples/Table/WithFormFields';
3
4
 
4
5
 
5
6
  ## Table with form field components
@@ -1,8 +1,4 @@
1
- import {
2
- ExampleCodeBlock,
3
- Specifications,
4
- SymbolDoc,
5
- } from '@workday/canvas-kit-docs';
1
+ import {ExampleCodeBlock, Specifications, SymbolDoc} from '@workday/canvas-kit-docs';
6
2
 
7
3
  import Basic from './examples/Basic';
8
4
  import Caution from './examples/Caution';
@@ -34,7 +30,9 @@ yarn add @workday/canvas-kit-react
34
30
 
35
31
  Checkbox may be used on its own without [Form Field](/components/inputs/form-field/) since it
36
32
  includes a `<label>` with a `for` attribute referencing the underlying `<input type="checkbox">`
37
- element.
33
+ element. For checkboxes grouped with **`FormFieldGroup`**, see
34
+ [FormField accessibility](/components/inputs/form-field/#accessibility) for hint, error, caution,
35
+ and required state wiring.
38
36
 
39
37
  <ExampleCodeBlock code={Basic} />
40
38
 
@@ -61,6 +59,9 @@ not all) of its children are checked.
61
59
 
62
60
  <ExampleCodeBlock code={Indeterminate} />
63
61
 
62
+ > **Accessibility Note**: Use semantic unordered list markup so that screen readers can communicate
63
+ > the nested hierarchy of the components to users.
64
+
64
65
  ### Ref Forwarding
65
66
 
66
67
  Checkbox supports [ref forwarding](https://reactjs.org/docs/forwarding-refs.html). It will forward
@@ -70,27 +71,32 @@ Checkbox supports [ref forwarding](https://reactjs.org/docs/forwarding-refs.html
70
71
 
71
72
  ### Label Position Horizontal
72
73
 
73
- Set the `orientation` prop of the Form Field to designate the position of the label relative to the
74
- input component. By default, the orientation will be set to `vertical`.
74
+ Set the `orientation` prop of the wrapping FormFieldGroup to designate the position of the group
75
+ label relative to the checkboxes. By default, the orientation will be set to `vertical`.
75
76
 
76
77
  <ExampleCodeBlock code={LabelPosition} />
77
78
 
78
79
  ### Required
79
80
 
80
- Set the `required` prop of a wrapping Form Field to `true` to indicate that the field is required.
81
- Labels for required fields are suffixed by a red asterisk.
81
+ Set the `isRequired` prop of a wrapping FormFieldGroup to `true` to indicate that the field is
82
+ required. Labels for required fields are suffixed by a red asterisk.
83
+
84
+ A standalone checkbox does not need **`FormFieldGroup`**. This example wraps a single checkbox so
85
+ `isRequired` can show the required asterisk on **`FormFieldGroup.Label`**. Use that wrapper only
86
+ when the spec includes a required state (or a group name, hint, error, or caution). See
87
+ [Accessibility](#accessibility).
82
88
 
83
89
  <ExampleCodeBlock code={Required} />
84
90
 
85
91
  ### Error States
86
92
 
87
- Set the `error` prop of the wrapping Form Field to `"caution"` or `"error"` to set the Checkbox to
88
- the Alert or Error state, respectively. You will also need to set the `hintId` and `hintText` props
89
- on the Form Field to meet accessibility standards. You may wish to omit the `label` prop on the Form
90
- Field given that Checkbox already includes a label.
93
+ Set the `error` prop of the wrapping FormFieldGroup to `"caution"` or `"error"` to set the Checkbox
94
+ to the Alert or Error state, respectively. Render `FormFieldGroup.Hint` with the message text so
95
+ assistive technology can associate the hint with the group. Keep the Checkbox `label` so each
96
+ control retains its own accessible name; `FormFieldGroup.Label` only provides the group name.
91
97
 
92
98
  The `error` prop may be applied directly to the Checkbox with a value of `"caution"` or `"error"` if
93
- Form Field is not being used.
99
+ FormFieldGroup is not being used.
94
100
 
95
101
  #### Caution
96
102
 
@@ -105,6 +111,127 @@ Form Field is not being used.
105
111
  Checkbox supports custom styling via the `cs` prop. For more information, check our
106
112
  ["How To Customize Styles"](https://workday.github.io/canvas-kit/?path=/docs/styling-guides-customizing-styles--docs).
107
113
 
114
+ ## Accessibility
115
+
116
+ The primary accessibility goal is a visible, programmatically determinable name and a checked,
117
+ unchecked, or mixed state that assistive technology can expose. Use **Checkbox** when the user can
118
+ select zero, one, or many independent options. For mutually exclusive choices, use
119
+ [**Radio**](https://workday.github.io/canvas-kit/?path=/docs/preview-inputs-radio--docs) instead.
120
+ When checkboxes answer the same question, or need hint, error, caution, or required association, see
121
+ [FormField's accessibility documentation](/components/inputs/form-field/#accessibility).
122
+
123
+ ### Minimum Accessible Structure
124
+
125
+ The following matches the [Basic Example](#basic-example): a **`Checkbox`** with a non-empty
126
+ **`label`**. **`FormFieldGroup`** is not required for a single standalone checkbox with no hint,
127
+ error, caution, or required state.
128
+
129
+ ```tsx
130
+ import {Checkbox} from '@workday/canvas-kit-react/checkbox';
131
+
132
+ <Checkbox label="I agree to the terms" />;
133
+ ```
134
+
135
+ ### Built-in Behaviors
136
+
137
+ Canvas Kit applies these automatically on **`Checkbox`**. When checkboxes that answer the same
138
+ question are composed with **`FormFieldGroup`** subcomponents, that grouping wiring is also applied
139
+ automatically. **Do not duplicate them** in consuming code.
140
+
141
+ **ARIA and DOM** (_applied by Checkbox_):
142
+
143
+ - **`Checkbox`**: Renders a native `<input type="checkbox">`. Canvas Kit assigns an `id` with
144
+ `useUniqueId` unless you pass **`id`**.
145
+ - **`label`**: Renders a visible `<label htmlFor={id}>` so the control has an accessible name and
146
+ clicking the text activates the input.
147
+ - **`indeterminate`**: Sets `aria-checked="mixed"` and the input's native `indeterminate` property.
148
+ Otherwise `aria-checked` follows the **`checked`** prop.
149
+ - **`disabled`**: Maps to the native `disabled` attribute.
150
+ - **`ref`**: Forwards to the underlying `<input type="checkbox">`.
151
+
152
+ **Keyboard** (_native checkbox behavior_):
153
+
154
+ **`Checkbox`** uses native `<input type="checkbox">` keyboard behavior (tab order, Space to toggle,
155
+ and label activation). Do not intercept <kbd>Space</kbd> or otherwise prevent the native toggle.
156
+
157
+ **Screen reader expectations** (_when built-in behaviors are used as intended_):
158
+
159
+ - On focus, assistive technology announces the Checkbox **`label`** and checked, unchecked, or mixed
160
+ state
161
+ - Disabled checkboxes are announced as unavailable
162
+
163
+ For group, hint, error, and required association, see
164
+ [FormField's Built-in Behaviors](/components/inputs/form-field/#built-in-behaviors).
165
+
166
+ ### Accessibility Requirements
167
+
168
+ Required in application code for an accessible Checkbox. Rows marked _(conditional)_ apply only when
169
+ the situation matches—otherwise omit.
170
+
171
+ **If no design spec is provided:** use a visible, non-empty Checkbox **`label`**. Omit
172
+ **`FormFieldGroup`** unless the spec includes a group name, more than one independent option for the
173
+ same question, or hint, error, caution, or required state. Omit **`FormFieldGroup.Hint`**,
174
+ **`isRequired`**, **`error`**, **`indeterminate`**, **`disabled`**, a custom **`id`**, and a
175
+ **`ref`** unless the spec requires them.
176
+
177
+ **Choose a composition:**
178
+
179
+ - Standalone **`Checkbox`** with **`label`** — one control with no hint, error, caution, or required
180
+ state
181
+ - **`FormFieldGroup`** — one question with two or more independent options, or any checkbox that
182
+ needs a group name, hint, error, caution, or required state
183
+ - Nested `<ul>` / `<li>` — parent checkbox with nested children and **`indeterminate`**. Do not use
184
+ **`FormFieldGroup`** for that hierarchy. Checkboxes that answer different questions stay in
185
+ separate compositions.
186
+
187
+ **Programmatic focus** _(conditional — omit by default)_:
188
+
189
+ Attach a `ref` only when the product must move focus to the checkbox after an action (for example,
190
+ **Submit** in [Ref Forwarding](#ref-forwarding)). Do not attach a `ref` or call `focus()` unless the
191
+ design or developer asks for it.
192
+
193
+ | Requirement | How to satisfy |
194
+ | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
195
+ | Accessible name | Non-empty **`label`** on every **`Checkbox`**. **`FormFieldGroup.Label`** names the group only (`div` with an `id`); it is not a `<label>` and does not replace **`label`**. |
196
+ | Group wiring _(conditional)_ | When the spec is one question with two or more independent options, or includes a group name, hint, error, caution, or required state: **`FormFieldGroup`** + **`FormFieldGroup.Label`** + **`FormFieldGroup.Input as={Checkbox}`**. Put hint, error, caution, and required on the group — see [FormField accessibility](/components/inputs/form-field/#accessibility). See [Required](#required) and [Error States](#error-states). |
197
+ | Visual error or caution _(conditional)_ | When **`FormFieldGroup`** has `error="error"` or `error="caution"`, also set **`error`** on **`Checkbox`** to the same state so the visual ring appears. See [Caution](#caution) and [Error](#error). |
198
+ | Indeterminate parent _(conditional)_ | When a parent checkbox's value depends on nested children and some (but not all) children are checked: set **`indeterminate`** on the parent **`Checkbox`**; keep a non-empty **`label`** on the parent and on each child; nest the children in a `<ul>` inside the parent's `<li>`. See [Indeterminate](#indeterminate). |
199
+ | Disabled _(conditional)_ | `disabled` on **`Checkbox`** when the spec marks the option unavailable. See [Disabled](#disabled). |
200
+ | Programmatic focus _(conditional)_ | `ref` on **`Checkbox`** (or **`FormFieldGroup.Input`**) and move focus when the product requires it — omit by default (see **Programmatic focus** above and [Ref Forwarding](#ref-forwarding)). |
201
+
202
+ **Summary for code generation:**
203
+
204
+ - **REQUIRED:** non-empty **`label`**
205
+ - **CONDITIONAL:** **`FormFieldGroup`** for one question with two or more independent options, or
206
+ for hint, error, caution, or required; **`error`** on **`Checkbox`** when the group is in caution
207
+ or error; nested list + **`indeterminate`** for a parent/child tree; disabled; programmatic focus
208
+ via `ref`. See [FormField accessibility](/components/inputs/form-field/#accessibility) for group
209
+ hint, error, caution, and required.
210
+
211
+ ### Anti-Patterns
212
+
213
+ Do **not** generate code that does the following (see **Accessibility Requirements** above for what
214
+ to supply instead):
215
+
216
+ - Manually set `aria-checked` or `htmlFor` on **`Checkbox`**, or pass an **`id`** when the spec does
217
+ not require a known id — Canvas Kit wires `aria-checked` and `htmlFor`, and assigns an `id` with
218
+ `useUniqueId` unless you pass one (see **If no design spec is provided**)
219
+ - Ignore **Choose a composition** — do not wrap a standalone checkbox with no group name, hint,
220
+ error, caution, or required state in **`FormFieldGroup`**; do not put different questions in one
221
+ group; do not use **`FormFieldGroup`** for a parent/child indeterminate tree
222
+ - Wrap **`Checkbox`** with **`FormField.Input`** — **`Checkbox`** already renders its own `<label>`.
223
+ When a group is required, use **`FormFieldGroup.Input as={Checkbox}`** (see **Group wiring**)
224
+ - Omit **`label`** because **`FormFieldGroup.Label`** is present — the group label does not name the
225
+ individual control
226
+ - Set `aria-checked="mixed"` without **`indeterminate`**
227
+ - Use **`aria-disabled`** instead of **`disabled`** — **`Checkbox`** maps unavailability to the
228
+ native **`disabled`** prop
229
+ - Use **`disabled`** when the spec says users must still focus the control to hear why it is
230
+ unavailable. Only in that case keep the checkbox enabled and put the explanation in
231
+ **`FormFieldGroup.Hint`** or on an adjacent focusable control
232
+ - Use **Checkbox** for mutually exclusive choices — use
233
+ [**Radio**](https://workday.github.io/canvas-kit/?path=/docs/preview-inputs-radio--docs) instead
234
+
108
235
  ## Component API
109
236
 
110
237
  <SymbolDoc name="Checkbox" fileName="/react/" />
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
 
3
3
  import {Checkbox} from '@workday/canvas-kit-react/checkbox';
4
- import {FormField} from '@workday/canvas-kit-react/form-field';
5
4
 
6
5
  export default () => {
7
6
  const [checked, setChecked] = React.useState(false);
@@ -10,17 +9,5 @@ export default () => {
10
9
  setChecked(event.target.checked);
11
10
  };
12
11
 
13
- return (
14
- <FormField>
15
- <FormField.Label>Confirm</FormField.Label>
16
- <FormField.Field>
17
- <FormField.Input
18
- as={Checkbox}
19
- checked={checked}
20
- label="I agree to the terms"
21
- onChange={handleChange}
22
- />
23
- </FormField.Field>
24
- </FormField>
25
- );
12
+ return <Checkbox checked={checked} label="I agree to the terms" onChange={handleChange} />;
26
13
  };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
 
3
3
  import {Checkbox} from '@workday/canvas-kit-react/checkbox';
4
- import {FormField} from '@workday/canvas-kit-react/form-field';
4
+ import {FormFieldGroup} from '@workday/canvas-kit-react/form-field';
5
5
 
6
6
  export default () => {
7
7
  const [checked, setChecked] = React.useState(false);
@@ -11,17 +11,18 @@ export default () => {
11
11
  };
12
12
 
13
13
  return (
14
- <FormField error="caution">
15
- <FormField.Label>Confirm</FormField.Label>
16
- <FormField.Field>
17
- <FormField.Input
14
+ <FormFieldGroup error="caution">
15
+ <FormFieldGroup.Label>Confirm</FormFieldGroup.Label>
16
+ <FormFieldGroup.Field>
17
+ <FormFieldGroup.Input
18
18
  as={Checkbox}
19
19
  checked={checked}
20
+ error={Checkbox.ErrorType.Caution}
20
21
  label="I agree to the terms"
21
22
  onChange={handleChange}
22
23
  />
23
- <FormField.Hint>You must agree to the terms before proceeding</FormField.Hint>
24
- </FormField.Field>
25
- </FormField>
24
+ <FormFieldGroup.Hint>You must agree to the terms before proceeding</FormFieldGroup.Hint>
25
+ </FormFieldGroup.Field>
26
+ </FormFieldGroup>
26
27
  );
27
28
  };