@workday/canvas-kit-docs 6.8.9 → 6.9.0-next.2

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.
Files changed (189) hide show
  1. package/dist/commonjs/index.js +13 -6
  2. package/dist/commonjs/lib/Specifications.d.ts.map +1 -1
  3. package/dist/commonjs/lib/Specifications.js +3 -1
  4. package/dist/commonjs/lib/docs.js +1 -0
  5. package/dist/commonjs/lib/specs.js +229 -6
  6. package/dist/es6/lib/Specifications.d.ts.map +1 -1
  7. package/dist/es6/lib/specs.js +229 -6
  8. package/dist/mdx/{4.0-MIGRATION-GUIDE.mdx → 4.0-UPGRADE-GUIDE.mdx} +1 -1
  9. package/dist/mdx/{5.0-MIGRATION-GUIDE.mdx → 5.0-UPGRADE-GUIDE.mdx} +3 -3
  10. package/dist/mdx/{6.0-MIGRATION-GUIDE.mdx → 6.0-UPGRADE-GUIDE.mdx} +4 -4
  11. package/dist/mdx/7.0-UPGRADE-GUIDE.mdx +1006 -0
  12. package/dist/mdx/COMPOUND_COMPONENTS.mdx +2 -2
  13. package/dist/mdx/CONTRIBUTING.mdx +2 -2
  14. package/dist/mdx/changelog.stories.mdx +1 -0
  15. package/dist/mdx/labs-react/search-form/examples/Basic.tsx +4 -2
  16. package/dist/mdx/labs-react/search-form/examples/CustomTheme.tsx +4 -2
  17. package/dist/mdx/labs-react/search-form/examples/Grow.tsx +4 -2
  18. package/dist/mdx/labs-react/search-form/examples/RTL.tsx +4 -2
  19. package/dist/mdx/labs-react/search-form/examples/Theming.tsx +4 -2
  20. package/dist/mdx/preview-react/_examples/SidePanelWithOverlay.mdx +8 -0
  21. package/dist/mdx/preview-react/_examples/examples/SidePanelWithOverlay.tsx +31 -0
  22. package/dist/mdx/preview-react/_examples/examples/TextInputWithFormik.tsx +3 -3
  23. package/dist/mdx/preview-react/form-field/examples/Custom.tsx +4 -5
  24. package/dist/mdx/preview-react/menu/Menu.mdx +1 -1
  25. package/dist/mdx/preview-react/menu/examples/ContextMenu.tsx +2 -2
  26. package/dist/mdx/preview-react/menu/examples/Icons.tsx +0 -1
  27. package/dist/mdx/preview-react/pill/Pill.mdx +241 -0
  28. package/dist/mdx/preview-react/pill/examples/Basic.tsx +18 -0
  29. package/dist/mdx/preview-react/pill/examples/WithAvatar.tsx +21 -0
  30. package/dist/mdx/preview-react/pill/examples/WithCount.tsx +9 -0
  31. package/dist/mdx/preview-react/pill/examples/WithList.tsx +31 -0
  32. package/dist/mdx/preview-react/pill/examples/WithReadOnly.tsx +15 -0
  33. package/dist/mdx/preview-react/pill/examples/WithRemovable.tsx +25 -0
  34. package/dist/mdx/preview-react/pill/examples/test-avatar.png +0 -0
  35. package/dist/mdx/preview-react/side-panel/SidePanel.mdx +5 -3
  36. package/dist/mdx/preview-react/side-panel/examples/AlwaysOpen.tsx +16 -22
  37. package/dist/mdx/preview-react/side-panel/examples/Basic.tsx +9 -14
  38. package/dist/mdx/preview-react/side-panel/examples/ExternalControl.tsx +9 -13
  39. package/dist/mdx/preview-react/side-panel/examples/HiddenName.tsx +1 -1
  40. package/dist/mdx/preview-react/side-panel/examples/OnExpandedChange.tsx +1 -1
  41. package/dist/mdx/preview-react/side-panel/examples/OnStateTransition.tsx +1 -1
  42. package/dist/mdx/preview-react/side-panel/examples/RightOrigin.tsx +17 -24
  43. package/dist/mdx/preview-react/side-panel/examples/Variant.tsx +9 -14
  44. package/dist/mdx/preview-react/text-area/examples/Alert.tsx +2 -1
  45. package/dist/mdx/preview-react/text-area/examples/HiddenLabel.tsx +6 -4
  46. package/dist/mdx/preview-react/text-area/examples/RefForwarding.tsx +1 -1
  47. package/dist/mdx/preview-react/text-input/examples/Alert.tsx +2 -1
  48. package/dist/mdx/preview-react/text-input/examples/HiddenLabel.tsx +6 -4
  49. package/dist/mdx/preview-react/text-input/examples/RefForwarding.tsx +1 -1
  50. package/dist/mdx/preview-react/text-input/examples/ThemedAlert.tsx +2 -1
  51. package/dist/mdx/react/_examples/SegmentedControlWithText.mdx +12 -0
  52. package/dist/mdx/react/_examples/examples/GlobalHeader.tsx +7 -6
  53. package/dist/mdx/react/_examples/examples/PageHeader.tsx +5 -5
  54. package/dist/mdx/react/_examples/examples/SegmentControlWithText.tsx +119 -0
  55. package/dist/mdx/react/action-bar/ActionBar.mdx +126 -23
  56. package/dist/mdx/react/action-bar/examples/Basic.tsx +7 -4
  57. package/dist/mdx/react/action-bar/examples/DeleteAction.tsx +15 -0
  58. package/dist/mdx/react/action-bar/examples/Icons.tsx +18 -0
  59. package/dist/mdx/react/action-bar/examples/OverflowActionBar.tsx +59 -0
  60. package/dist/mdx/react/banner/Banner.mdx +203 -19
  61. package/dist/mdx/react/banner/PropTables.splitprops.tsx +39 -0
  62. package/dist/mdx/react/banner/examples/ActionText.tsx +8 -1
  63. package/dist/mdx/react/banner/examples/Basic.tsx +8 -1
  64. package/dist/mdx/react/banner/examples/Error.tsx +8 -1
  65. package/dist/mdx/react/banner/examples/RefForwarding.tsx +25 -0
  66. package/dist/mdx/react/banner/examples/Sticky.tsx +12 -7
  67. package/dist/mdx/react/banner/examples/StickyAnimation.tsx +64 -0
  68. package/dist/mdx/react/banner/examples/StickyRTL.tsx +35 -0
  69. package/dist/mdx/react/banner/examples/ThemedAlert.tsx +28 -0
  70. package/dist/mdx/react/banner/examples/ThemedError.tsx +29 -0
  71. package/dist/mdx/react/button/button/Button.mdx +3 -3
  72. package/dist/mdx/react/button/button/Hyperlink.mdx +72 -0
  73. package/dist/mdx/react/button/button/examples/ExternalHyperlink.tsx +7 -0
  74. package/dist/mdx/react/button/button/examples/ExternalHyperlinkInverse.tsx +12 -0
  75. package/dist/mdx/react/button/button/examples/Hyperlink.tsx +5 -0
  76. package/dist/mdx/react/button/button/examples/HyperlinkInverse.tsx +12 -0
  77. package/dist/mdx/react/button/button/examples/Primary.tsx +11 -3
  78. package/dist/mdx/react/button/button/examples/PrimaryInverse.tsx +11 -3
  79. package/dist/mdx/react/button/button/examples/Secondary.tsx +11 -3
  80. package/dist/mdx/react/button/button/examples/SecondaryInverse.tsx +11 -3
  81. package/dist/mdx/react/button/button/examples/Tertiary.tsx +9 -4
  82. package/dist/mdx/react/button/button/examples/TertiaryInverse.tsx +12 -3
  83. package/dist/mdx/react/card/card.mdx +2 -2
  84. package/dist/mdx/react/card/examples/Depth.tsx +1 -1
  85. package/dist/mdx/react/checkbox/Checkbox.mdx +7 -0
  86. package/dist/mdx/react/checkbox/examples/Indeterminate.tsx +1 -1
  87. package/dist/mdx/react/checkbox/examples/Inverse.tsx +22 -0
  88. package/dist/mdx/react/checkbox/examples/RefForwarding.tsx +1 -1
  89. package/dist/mdx/react/collection/Collection.mdx +358 -0
  90. package/dist/mdx/react/collection/Collection.splitprops.tsx +19 -0
  91. package/dist/mdx/react/collection/examples/Basic.tsx +12 -0
  92. package/dist/mdx/react/collection/examples/BasicGrid.tsx +46 -0
  93. package/dist/mdx/react/collection/examples/BasicVirtual.tsx +24 -0
  94. package/dist/mdx/react/collection/examples/DynamicItems.tsx +20 -0
  95. package/dist/mdx/react/collection/examples/IdentifiedItems.tsx +12 -0
  96. package/dist/mdx/react/collection/examples/MultiSelection.tsx +56 -0
  97. package/dist/mdx/react/collection/examples/RovingFocus.tsx +39 -0
  98. package/dist/mdx/react/collection/examples/Selection.tsx +58 -0
  99. package/dist/mdx/react/collection/examples/WrappingGrid.tsx +48 -0
  100. package/dist/mdx/react/color-picker/color-input/ColorInput.mdx +2 -2
  101. package/dist/mdx/react/color-picker/color-preview/ColorPreview.mdx +2 -2
  102. package/dist/mdx/{labs-react/common → react/layout}/Box.mdx +3 -6
  103. package/dist/mdx/{labs-react → react}/layout/Flex.mdx +24 -27
  104. package/dist/mdx/{labs-react → react}/layout/Stack.mdx +98 -146
  105. package/dist/mdx/{labs-react/common → react/layout}/examples/As.tsx +1 -1
  106. package/dist/mdx/{labs-react/common → react/layout}/examples/Border.tsx +1 -1
  107. package/dist/mdx/{labs-react/common → react/layout}/examples/Color.tsx +1 -1
  108. package/dist/mdx/{labs-react/common → react/layout}/examples/Depth.tsx +9 -3
  109. package/dist/mdx/{labs-react → react}/layout/examples/Flex/FlexCard.tsx +2 -3
  110. package/dist/mdx/{labs-react → react}/layout/examples/Flex/FlexLayout.tsx +1 -1
  111. package/dist/mdx/{labs-react → react}/layout/examples/Flex/Usage.tsx +2 -3
  112. package/dist/mdx/{labs-react/common → react/layout}/examples/FlexItem.tsx +1 -2
  113. package/dist/mdx/{labs-react/common → react/layout}/examples/Layout.tsx +1 -1
  114. package/dist/mdx/{labs-react/common → react/layout}/examples/Position.tsx +1 -1
  115. package/dist/mdx/{labs-react → react}/layout/examples/PropTables.splitprops.tsx +1 -1
  116. package/dist/mdx/{labs-react/common → react/layout}/examples/Ref.tsx +1 -1
  117. package/dist/mdx/{labs-react/common → react/layout}/examples/Space.tsx +1 -1
  118. package/dist/mdx/{labs-react → react}/layout/examples/Stack/BasicStack.tsx +1 -1
  119. package/dist/mdx/{labs-react → react}/layout/examples/Stack/HStackCards.tsx +2 -3
  120. package/dist/mdx/{labs-react → react}/layout/examples/Stack/NestedStacks.tsx +1 -1
  121. package/dist/mdx/react/layout/examples/Stack/ShouldWrapChildren.tsx +28 -0
  122. package/dist/mdx/{labs-react → react}/layout/examples/Stack/StackCard.tsx +2 -2
  123. package/dist/mdx/{labs-react → react}/layout/examples/Stack/StackItems.tsx +1 -2
  124. package/dist/mdx/{labs-react → react}/layout/examples/Stack/VStackCards.tsx +2 -2
  125. package/dist/mdx/react/menu/Menu.mdx +123 -0
  126. package/dist/mdx/react/menu/examples/Basic.tsx +26 -0
  127. package/dist/mdx/react/menu/examples/ContextMenu.tsx +25 -0
  128. package/dist/mdx/react/menu/examples/Icons.tsx +41 -0
  129. package/dist/mdx/react/modal/Modal.mdx +34 -11
  130. package/dist/mdx/react/modal/examples/Basic.tsx +4 -2
  131. package/dist/mdx/react/modal/examples/BodyOverflow.tsx +56 -0
  132. package/dist/mdx/react/modal/examples/CustomFocus.tsx +4 -2
  133. package/dist/mdx/react/modal/examples/FullOverflow.tsx +55 -0
  134. package/dist/mdx/react/modal/examples/ReturnFocus.tsx +5 -3
  135. package/dist/mdx/react/modal/examples/WithoutCloseIcon.tsx +4 -2
  136. package/dist/mdx/react/pagination/PropTables.splitprops.tsx +1 -1
  137. package/dist/mdx/react/pagination/pagination.mdx +14 -14
  138. package/dist/mdx/react/popup/Popup.mdx +2 -1
  139. package/dist/mdx/react/popup/examples/Basic.tsx +1 -1
  140. package/dist/mdx/react/popup/examples/FocusRedirect.tsx +1 -1
  141. package/dist/mdx/react/popup/examples/FocusTrap.tsx +1 -1
  142. package/dist/mdx/react/popup/examples/FullScreen.tsx +1 -1
  143. package/dist/mdx/react/popup/examples/InitialFocus.tsx +4 -2
  144. package/dist/mdx/react/popup/examples/MultiplePopups.tsx +1 -1
  145. package/dist/mdx/react/popup/examples/NestedPopups.tsx +18 -18
  146. package/dist/mdx/react/popup/examples/RTL.tsx +6 -3
  147. package/dist/mdx/react/radio/Radio.mdx +7 -0
  148. package/dist/mdx/react/radio/examples/Basic.tsx +11 -2
  149. package/dist/mdx/react/radio/examples/Inverse.tsx +23 -0
  150. package/dist/mdx/react/segmented-control/SegmentedControl.mdx +2 -2
  151. package/dist/mdx/react/segmented-control/examples/Basic.tsx +13 -11
  152. package/dist/mdx/react/skeleton/examples/Basic.tsx +1 -1
  153. package/dist/mdx/react/skeleton/examples/Color.tsx +1 -2
  154. package/dist/mdx/react/skeleton/examples/Simulation.tsx +31 -30
  155. package/dist/mdx/react/status-indicator/StatusIndicator.mdx +12 -0
  156. package/dist/mdx/react/status-indicator/examples/MaxWidth.tsx +30 -0
  157. package/dist/mdx/react/tabs/Tabs.mdx +14 -17
  158. package/dist/mdx/react/tabs/TabsModel.splitprops.tsx +7 -3
  159. package/dist/mdx/react/tabs/examples/DynamicTabs.tsx +6 -13
  160. package/dist/mdx/react/tabs/examples/HoistedModel.tsx +8 -8
  161. package/dist/mdx/react/tabs/examples/Icons.tsx +4 -4
  162. package/dist/mdx/react/tabs/examples/NamedTabs.tsx +10 -10
  163. package/dist/mdx/react/tabs/examples/OverflowTabs.tsx +4 -8
  164. package/dist/mdx/react/tabs/examples/SinglePanel.tsx +3 -3
  165. package/dist/mdx/react/text-input/examples/Basic.tsx +3 -0
  166. package/dist/mdx/react/tooltip/Tooltip.mdx +2 -2
  167. package/dist/mdx/react/tooltip/examples/Default.tsx +2 -2
  168. package/dist/mdx/react/tooltip/examples/UseTooltip.tsx +2 -2
  169. package/package.json +9 -17
  170. package/dist/mdx/labs-react/common/examples/PropTables.splitprops.tsx +0 -91
  171. package/dist/mdx/labs-react/layout/examples/Stack/ShouldWrapChildren.tsx +0 -33
  172. package/dist/mdx/react/button/icon-button/IconButton.mdx +0 -103
  173. package/dist/mdx/react/button/icon-button/examples/Circle.tsx +0 -6
  174. package/dist/mdx/react/button/icon-button/examples/CircleFilled.tsx +0 -8
  175. package/dist/mdx/react/button/icon-button/examples/Inverse.tsx +0 -20
  176. package/dist/mdx/react/button/icon-button/examples/InverseFilled.tsx +0 -20
  177. package/dist/mdx/react/button/icon-button/examples/MirroredIcon.tsx +0 -11
  178. package/dist/mdx/react/button/icon-button/examples/Plain.tsx +0 -8
  179. package/dist/mdx/react/button/icon-button/examples/Square.tsx +0 -8
  180. package/dist/mdx/react/button/icon-button/examples/SquareFilled.tsx +0 -8
  181. package/dist/mdx/react/button/icon-button/examples/Toggleable.tsx +0 -20
  182. package/ts3.5/dist/commonjs/index.d.ts +0 -4
  183. package/ts3.5/dist/commonjs/lib/Specifications.d.ts +0 -6
  184. package/ts3.5/dist/commonjs/lib/docs.d.ts +0 -5
  185. package/ts3.5/dist/commonjs/lib/specs.d.ts +0 -16
  186. package/ts3.5/dist/es6/index.d.ts +0 -4
  187. package/ts3.5/dist/es6/lib/Specifications.d.ts +0 -6
  188. package/ts3.5/dist/es6/lib/docs.d.ts +0 -5
  189. package/ts3.5/dist/es6/lib/specs.d.ts +0 -16
@@ -0,0 +1,358 @@
1
+ import {ListBox} from '@workday/canvas-kit-react/collection';
2
+
3
+ import Basic from './examples/Basic';
4
+ import DynamicItems from './examples/DynamicItems';
5
+ import BasicVirtual from './examples/BasicVirtual';
6
+ import IdentifiedItems from './examples/IdentifiedItems';
7
+ import RovingFocus from './examples/RovingFocus';
8
+ import Selection from './examples/Selection';
9
+ import MultiSelection from './examples/MultiSelection';
10
+ import BasicGrid from './examples/BasicGrid';
11
+ import WrappingGrid from './examples/WrappingGrid';
12
+ import {
13
+ ListModelConfigComponent,
14
+ ListStateComponent,
15
+ ListEventsComponent,
16
+ GridModelConfigComponent,
17
+ GridStateComponent,
18
+ GridEventsComponent,
19
+ NavigationManager,
20
+ } from './Collection.splitprops';
21
+
22
+
23
+ # Canvas Kit Collection API
24
+
25
+ The Collection API is a system of models and behaviors for creating lists and grids. For example,
26
+ `Tabs` uses collection behaviors and so does `Menu`. The UI of each looks very different, but much
27
+ of the behavior is shared. The Collection API should be used if a component doesn't already exist to
28
+ satisfy your needs.
29
+
30
+ ## Installation
31
+
32
+ ```sh
33
+ yarn add @workday/canvas-kit-react
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ ### Basic Example
39
+
40
+ The `ListBox` on its own isn't very useful. It registers each item with the model. The
41
+ `ListBox.Item` only uses the `useListItemRegister` hook which handles registration of static items
42
+ to the model. The `ListBox` uses `useListRenderItems` which handles rendering static items as well
43
+ as [Dynamic List](#dynamic-list) example).
44
+
45
+ <ExampleCodeBlock code={Basic} />
46
+
47
+ ### Identifying Items
48
+
49
+ A list item takes an optional `data-id` property that will be used to identify an item. Without a
50
+ `data-id`, the identifier will be the item's index when first registered. The basic example has a
51
+ `data-id` attribute that is a string representation of the index. Providing a `data-id` will
52
+ override to a value of your choosing. This identifier will be used by other hooks to identify the
53
+ item for selection, maintaining a cursor, or anything else.
54
+
55
+ <ExampleCodeBlock code={IdentifiedItems} />
56
+
57
+ ### Dynamic Items
58
+
59
+ The `ListBox` also handles a dynamic collection of items. Instead of providing each `ListBox.Item`
60
+ statically, provide a render function instead. The function is called with an `items` value that is
61
+ the same was what's provided to the model. By default, providing items will enable virtualization.
62
+ This example adds a `maxHeight` to ensure overflow. Virtualization uses absolute positioning of each
63
+ item, which could cause problems for popup menus. If your item count is low, pass
64
+ `shouldVirtualize={false}` to disable virtualization.
65
+
66
+ <ExampleCodeBlock code={DynamicItems} />
67
+
68
+ #### Roving Tabindex
69
+
70
+ The list system also includes a cursor that extends the list. A cursor is mostly used for focusing
71
+ items. The [roving tabindex](https://w3c.github.io/aria-practices/#kbd_roving_tabindex) is a
72
+ well-supported way to accomplish accessibility requirements for focusing items within a list. This
73
+ example shows how to use `useListRovingFocus`. This example uses the `ListBox` component, but the
74
+ default `ListBox.Item` is very basic. We have two options, we can either pass additional
75
+ functionality via `elemPropsHook` or by creating a new item using our elemProps hook primitives.
76
+ Both will be demonstrated. Creating a custom item is recommended if you create a custom component
77
+ and export it. Using `elemPropsHook` with `ListBox.Item` is recommended only for one-off instances.
78
+
79
+ You can either use the tab key for focus on an item or click on an item and then use the up/down
80
+ keys to navigation the list. By default, the list is set to wrap navigation using the
81
+ `wrappingNavigationManager`. Only a single item in the list is a focus stop that "roves" as the
82
+ up/down arrows are pressed.
83
+
84
+ **Note:** This example doesn't meet accessibility requirements. The list will have to have some type
85
+ of context. Like "navigation list" or "menu list".
86
+
87
+ <ExampleCodeBlock code={RovingFocus} />
88
+
89
+ #### Selection
90
+
91
+ Lists support selection. `useSelectionItem` is applied to an item which adds an `onClick` that adds
92
+ the item to the `state.selectedIds`. The default selection manager is a single select. This example
93
+ uses `ListBox` and creates a custom `SelectableItem` elemProps hook and component.
94
+
95
+ <ExampleCodeBlock code={Selection} />
96
+
97
+ #### Multiple Selection
98
+
99
+ The `selection` manager can be passed directly to the model configuration to handle different
100
+ selection types. This example passes the `multiSelectionManager` to handle selecting multiple items.
101
+
102
+ <ExampleCodeBlock code={MultiSelection} />
103
+
104
+ ### Basic Grid
105
+
106
+ A grid is a two dimensional list. A `columnCount` config is added to inform how to break up an array
107
+ of items. A grid is very similar to a list - it receives items as a single dimension list and uses
108
+ the `columnCount` to determine keyboard navigation. Grids only support a single orientation.
109
+
110
+ <ExampleCodeBlock code={BasicGrid} />
111
+
112
+ #### Wrapping Grid
113
+
114
+ By default, navigating a grid does not wrap around when the user reaches the end of a row or column.
115
+ The grid model supports passing in a navigation manager. The collection system supports two types of
116
+ navigation managers, a non-wrapping `navigationManager` and the `wrappingNavigationManager`. The
117
+ following example passes the `wrappingNavigationManager` manager to the model. Observe how the
118
+ cursor wraps around columns and rows when an edge of a column or row is encountered.
119
+
120
+ <ExampleCodeBlock code={WrappingGrid} />
121
+
122
+ ## Components
123
+
124
+ ### ListBox
125
+
126
+ #### Usage
127
+
128
+ The `ListBox` is a basic component that offers vertical rendering of a collection in the form of a
129
+ 2-dimension list. It understands virtualization, rendering only visible items in the DOM while also
130
+ providing aria attributes to allow screen readers to still navigate virtual lists. The `ListBox`
131
+ contains a basic `ListBox.Item` that renders list items that render correctly with virtualization
132
+ and adds `aria-setsize` and `aria-posinset` for screen readers.
133
+
134
+ The `ListBox` is very basic and only adds enough functionality to render correctly. No additional
135
+ behaviors are added to navigate or select. React Hooks are provided to add this functionality and
136
+ are used by higher level components like `Menu` and `Menu.Item` which utilize `ListBox`.
137
+
138
+ #### Props
139
+
140
+ <ArgsTable of={ListBox} />
141
+
142
+ ### ListBox.Item
143
+
144
+ #### Usage
145
+
146
+ The `ListBox.Item` is a simple placeholder for listbox items. The functionality of a collection item
147
+ varies between components. For example, a `Tabs.Item` and a `Menu.Item` have shared functionality,
148
+ but have different behavior. All collection-based components should implement a custom `Item`
149
+ subcomponent using the collection-based behavior hooks. The [Roving Tabindex](#roving-tabindex)
150
+ example uses the `elemPropsHook` to provide additional functionality. `elemPropsHook` is provided on
151
+ all compound components and is useful in the example to add additional functionality without making
152
+ a new component.
153
+
154
+ #### Props
155
+
156
+ <ArgsTable of={ListBox.Item} />
157
+
158
+ ## Models
159
+
160
+ There are two supported models based on the collection system.
161
+
162
+ ### `useListModel`
163
+
164
+ The List model contains the the state and events necessary to track items, selection, and a cursor.
165
+ Various hooks can be used for a List model to create common behaviors associated with lists, such as
166
+ navigating a list with a keyboard, selection (single and multiple), and virtualization.
167
+
168
+ A list also has a "cursor". A cursor is often represented by focus, but it is not always a 1:1
169
+ mapping. Think of the cursor as the focus item within the list. If the list has browser focus, the
170
+ cursor will map to browser focus. Behaviors such as `useListRovingFocus` will map the cursor to the
171
+ active tab stop of the list. For more information, see
172
+ [Roving Tabindex](https://w3c.github.io/aria-practices/#kbd_roving_tabindex). `useListRovingFocus`
173
+ adds keyboard events that map to navigation events. A [Navigation Manager](#navigation-manager) is
174
+ used to map new cursor ids to these events. The `ListModel` takes an optional `navigation`
175
+ configuration to change the default navigation behavior. The default navigation manager is a
176
+ [wrappingNavigationManager](#wrappingnavigationmanager) meaning the cursor will wrap around the
177
+ beginning and the ends. The cursor also provides a [navigationManager](#navigationmanager) that does
178
+ not wrap. This is the default navigation for grids.
179
+
180
+ The cursor also adds the concept of `orientation` which defaults to `'vertical'`. A Tab list is an
181
+ example of a `'horizontal'` list.
182
+
183
+ #### Config
184
+
185
+ <ArgsTable of={ListModelConfigComponent} />
186
+
187
+ #### State
188
+
189
+ <ArgsTable of={ListStateComponent} />
190
+
191
+ #### Events
192
+
193
+ <ArgsTable of={ListEventsComponent} />
194
+
195
+ ### `useGridModel`
196
+
197
+ The Grid model extends the List model and changes some config. For example, the `columnCount` is
198
+ required on the grid model's configuration and `orientation` is removed.
199
+
200
+ #### Config
201
+
202
+ <ArgsTable of={GridModelConfigComponent} />
203
+
204
+ #### State
205
+
206
+ <ArgsTable of={GridStateComponent} />
207
+
208
+ #### Events
209
+
210
+ <ArgsTable of={GridEventsComponent} />
211
+
212
+ ### Navigation Manager
213
+
214
+ The list and grid models accept a `navigation` config. If one is not provided, a default will be
215
+ chosen. It is possible to create a custom navigation manager to hand to the model if the default
216
+ doesn't work.
217
+
218
+ <ArgsTable of={NavigationManager} />
219
+
220
+ ```ts
221
+ type NavigationRequestor = <T>(id: string, model: Model) => Item<T>;
222
+
223
+ interface Item<T> {
224
+ index: number;
225
+ id: string;
226
+ value: T;
227
+ /**
228
+ * Used by components that allow jumping to an item based on typing
229
+ */
230
+ textValue?: string;
231
+ }
232
+ ```
233
+
234
+ #### `navigationManager`
235
+
236
+ The `navigationManager` implements the [Navigation Manager](#navigation-manager) interface for lists
237
+ and grids, but does not wrap when the user hits a boundary of the collection. This is the default
238
+ navigation manager for grids.
239
+
240
+ #### `wrappingNavigationManager`
241
+
242
+ The `wrappingNavigationManager` implements the [Navigation Manager](#navigation-manager) interface
243
+ for lists and grids, and wraps when the user hits a boundary of the collection. Grids will wrap
244
+ columns, but not rows. This is the default navigation manager for lists.
245
+
246
+ ### Selection Manager
247
+
248
+ The list and grid models accept a `selection` config. If one is not provided, `singleSelectManager`
249
+ is used. You can provide a custom select manager to suite your needs. A selection manager is an
250
+ object with a single `select` method that takes an id and previously selected ids and returns a new
251
+ set of selected ids.
252
+
253
+ The collection system provides two selection managers: `singleSelectManager` and
254
+ `multiSelectionManager`.
255
+
256
+ ```ts
257
+ interface Selection {
258
+ selectedIds: 'all' | string[];
259
+ unselectedIds: string[];
260
+ }
261
+
262
+ interface SelectionManager {
263
+ select(id: string, prevState: Selection): Selection;
264
+ }
265
+ ```
266
+
267
+ ## Hooks
268
+
269
+ ### `useListItemRegister`
270
+
271
+ This elemProps hook is the base of all item component hooks. It registers an item with a collection
272
+ and sets the `data-id` that is used by other hooks. It should always be the last defined hook when
273
+ using `composeHooks` (`composeHooks` executes hooks right to left and merges props left to right).
274
+ It is used by `ListBox.Item` and all `*.Item` subcomponents.
275
+
276
+ ```ts
277
+ const useMyItem = composeHooks(
278
+ useListItemSelect, // additional hooks go here
279
+ useListItemRegister // always last
280
+ );
281
+ ```
282
+
283
+ ### `useListItemRovingFocus`
284
+
285
+ This elemProps hook is used for cursor navigation by using
286
+ [Roving Tabindex](https://w3c.github.io/aria-practices/#kbd_roving_tabindex). Only a single item in
287
+ the collection has a tab stop. Pressing an arrow key moves the tab stop to a different item in the
288
+ corresponding direction. See the [Roving Tabindex](#roving-tabindex) example. This elemProps hook
289
+ should be applied to an `*.Item` component.
290
+
291
+ ```ts
292
+ const useMyItem = composeHooks(
293
+ useListItemRovingFocus, // adds the roving tabindex support
294
+ useListItemRegister
295
+ );
296
+ ```
297
+
298
+ ### `useListItemSelect`
299
+
300
+ This elemProps hook adds selection support to a `*.Item` subcomponent of a collection. It adds a
301
+ click handler that toggles selection status according to the [Selection Manager](#selection-manager)
302
+ used.
303
+
304
+ ```ts
305
+ const useMyItem = composeHooks(
306
+ useListItemSelect, // adds selection support to an item
307
+ useListItemRegister
308
+ );
309
+ ```
310
+
311
+ ### `useListRenderItem`
312
+
313
+ ```ts
314
+ declare function useListRenderItem<T>(
315
+ model: Model,
316
+ children: React.ReactNode | ((item: T, index: number) => React.ReactNode)
317
+ ): React.ReactNode;
318
+ ```
319
+
320
+ This hook is meant to be used inside the render function of `List` style components. It is used by
321
+ `ListBox`. This hook gives list-based components their static and dynamic APIs to handle list items.
322
+ This hook should only be used if you want to implement your own List. For example, `Tabs.List` uses
323
+ this hook, but `Menu.List` uses `ListBox` which uses this hook.
324
+
325
+ ```tsx
326
+ const MyList = createContainer('ul')({
327
+ modelHook: useListModel,
328
+ })((elemProps, Element, model) => {
329
+ return <Element {...elemProps}>{useListRenderItems(model, elemProps.children)}</Element>;
330
+ });
331
+ ```
332
+
333
+ ### `useListResetCursorOnBlur`
334
+
335
+ This elemProps hook resets the cursor when the list looses focus. By default,
336
+ [useListItemRovingFocus](#use-list-item-roving-focus) will leave the last focused item as the
337
+ focusable item in the list. Sometimes it is desireable to reset the cursor to the last selected
338
+ item. For example, `Tabs.Item` uses this hook to reset the tab stop to the currently selected tab.
339
+
340
+ ```ts
341
+ const useMyItem = composeHooks(
342
+ useListResetCursorOnBlur, // adds the cursor reset to selected for roving tabindex
343
+ useListItemRovingFocus,
344
+ useListItemRegister
345
+ );
346
+ ```
347
+
348
+ ### `useOverflowListItemMeasure`
349
+
350
+ Coming Soon
351
+
352
+ ### `useOverflowListMeasure`
353
+
354
+ Coming Soon
355
+
356
+ ### `useOverflowListTarget`
357
+
358
+ Coming Soon
@@ -0,0 +1,19 @@
1
+ import {useListModel, useGridModel} from '@workday/canvas-kit-react/collection';
2
+
3
+ type ListModelConfig = Partial<typeof useListModel.defaultConfig> &
4
+ typeof useListModel.requiredConfig;
5
+ type ListModel = ReturnType<typeof useListModel>;
6
+
7
+ type GridModelConfig = Partial<typeof useGridModel.defaultConfig> &
8
+ typeof useGridModel.requiredConfig;
9
+ type GridModel = ReturnType<typeof useGridModel>;
10
+
11
+ export const ListModelConfigComponent = (_: ListModelConfig) => <div />;
12
+ export const ListStateComponent = (_: ListModel['state']) => <div />;
13
+ export const ListEventsComponent = (_: ListModel['events']) => <div />;
14
+
15
+ export const GridModelConfigComponent = (_: GridModelConfig) => <div />;
16
+ export const GridStateComponent = (_: GridModel['state']) => <div />;
17
+ export const GridEventsComponent = (_: GridModel['events']) => <div />;
18
+
19
+ export const NavigationManager = (_: GridModelConfig['navigation']) => <div />;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+
3
+ import {ListBox} from '@workday/canvas-kit-react/collection';
4
+
5
+ export default () => {
6
+ return (
7
+ <ListBox>
8
+ <ListBox.Item>First</ListBox.Item>
9
+ <ListBox.Item>Second</ListBox.Item>
10
+ </ListBox>
11
+ );
12
+ };
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+
3
+ import {Flex, Box} from '@workday/canvas-kit-react/layout';
4
+ import {
5
+ ListBox,
6
+ useGridModel,
7
+ useListItemSelect,
8
+ useListItemRovingFocus,
9
+ useListItemRegister,
10
+ } from '@workday/canvas-kit-react/collection';
11
+ import {composeHooks, createSubcomponent} from '@workday/canvas-kit-react/common';
12
+
13
+ const useItem = composeHooks(useListItemSelect, useListItemRovingFocus, useListItemRegister);
14
+
15
+ const Item = createSubcomponent('button')({
16
+ modelHook: useGridModel,
17
+ elemPropsHook: useItem,
18
+ })((elemProps, Element, model) => {
19
+ return (
20
+ <Box
21
+ as={Element}
22
+ {...elemProps}
23
+ width={40}
24
+ border="solid 1px black"
25
+ style={{
26
+ background: model.state.selectedIds.includes(elemProps['data-id']) ? 'gray' : 'white',
27
+ }}
28
+ />
29
+ );
30
+ });
31
+
32
+ export default () => {
33
+ const model = useGridModel({
34
+ columnCount: 5,
35
+ // @ts-ignore Create an array of [{id: 1}, ...{id: n}]
36
+ items: [...Array(25).keys()].map(i => ({id: i + 1})),
37
+ // we don't need virtualization here
38
+ shouldVirtualize: false,
39
+ });
40
+
41
+ return (
42
+ <ListBox model={model} as={Flex} flexDirection="row" flexWrap="wrap" width={200}>
43
+ {item => <Item>{item.id}</Item>}
44
+ </ListBox>
45
+ );
46
+ };
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+
3
+ import {ListBox, useListItemRovingFocus} from '@workday/canvas-kit-react/collection';
4
+
5
+ interface Item {
6
+ id: string;
7
+ text: string;
8
+ }
9
+
10
+ const items: Item[] = Array(1000)
11
+ .fill(true)
12
+ .map((_, index) => ({id: String(index + 1), text: `Item - ${index + 1}`}));
13
+
14
+ export default () => {
15
+ return (
16
+ <ListBox items={items} maxHeight={300}>
17
+ {(item: Item) => (
18
+ <ListBox.Item data-id={item.id} elemPropsHook={useListItemRovingFocus}>
19
+ {item.text}
20
+ </ListBox.Item>
21
+ )}
22
+ </ListBox>
23
+ );
24
+ };
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+
3
+ import {ListBox} from '@workday/canvas-kit-react/collection';
4
+
5
+ interface Item {
6
+ id: string;
7
+ text: string;
8
+ }
9
+
10
+ const items: Item[] = Array(1000)
11
+ .fill(true)
12
+ .map((_, index) => ({id: String(index + 1), text: `Item - ${index + 1}`}));
13
+
14
+ export default () => {
15
+ return (
16
+ <ListBox items={items} maxHeight={300}>
17
+ {(item: Item) => <ListBox.Item data-id={item.id}>{item.text}</ListBox.Item>}
18
+ </ListBox>
19
+ );
20
+ };
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+
3
+ import {ListBox} from '@workday/canvas-kit-react/collection';
4
+
5
+ export default () => {
6
+ return (
7
+ <ListBox>
8
+ <ListBox.Item data-id="first">First</ListBox.Item>
9
+ <ListBox.Item data-id="second">Second</ListBox.Item>
10
+ </ListBox>
11
+ );
12
+ };
@@ -0,0 +1,56 @@
1
+ import React from 'react';
2
+
3
+ import {
4
+ useListItemRegister,
5
+ useListItemRovingFocus,
6
+ useListItemSelect,
7
+ useListModel,
8
+ ListItemProps,
9
+ ListBox,
10
+ } from '@workday/canvas-kit-react/collection';
11
+ import {composeHooks, createSubcomponent} from '@workday/canvas-kit-react/common';
12
+ import {multiSelectionManager} from '../../lib/useSelectionListModel';
13
+
14
+ const useMultiSelectItem = composeHooks(
15
+ useListItemSelect,
16
+ useListItemRovingFocus,
17
+ useListItemRegister
18
+ );
19
+
20
+ const Item = createSubcomponent('button')({
21
+ displayName: 'MultiSelectableItem',
22
+ modelHook: useListModel,
23
+ elemPropsHook: useMultiSelectItem,
24
+ })<ListItemProps>((elemProps, Element, model) => {
25
+ return (
26
+ <Element
27
+ role="listitem"
28
+ {...elemProps}
29
+ style={{
30
+ background: model.state.selectedIds.includes(elemProps['data-id']) ? 'gray' : 'white',
31
+ }}
32
+ />
33
+ );
34
+ });
35
+
36
+ export default () => {
37
+ const model = useListModel({
38
+ initialSelectedIds: ['first', 'second'],
39
+ selection: multiSelectionManager,
40
+ orientation: 'horizontal',
41
+ });
42
+ return (
43
+ <>
44
+ <ListBox model={model}>
45
+ <Item data-id="first">First</Item>
46
+ <Item data-id="second">Second</Item>
47
+ <Item data-id="third">Third</Item>
48
+ </ListBox>
49
+
50
+ <p>Cursor ID: {model.state.cursorId}</p>
51
+ <p>
52
+ Selected IDs: {(model.state.selectedIds !== 'all' ? model.state.selectedIds : []).join(',')}
53
+ </p>
54
+ </>
55
+ );
56
+ };
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+
3
+ import {
4
+ useListItemRegister,
5
+ useListItemRovingFocus,
6
+ useListModel,
7
+ ListBox,
8
+ ListItemProps,
9
+ } from '@workday/canvas-kit-react/collection';
10
+ import {composeHooks, createSubcomponent} from '@workday/canvas-kit-react/common';
11
+
12
+ // create our own hook using `useListItemRegister` and `useListItemRovingFocus`. Note the
13
+ // `useListItemRegister` must be the last hook when using `composeHooks`
14
+ const useRovingFocusItem = composeHooks(useListItemRovingFocus, useListItemRegister);
15
+
16
+ // create our own item. We use `modelHook` to define which model should be used and `elemPropsHook`
17
+ // to determine which elemProps hook should be used. `elemProps` will be populated with props to
18
+ // pass to the element
19
+ const RovingFocusItem = createSubcomponent('li')({
20
+ displayName: 'RovingFocusItem',
21
+ modelHook: useListModel,
22
+ elemPropsHook: useRovingFocusItem,
23
+ })<ListItemProps>((elemProps, Element) => {
24
+ return <Element {...elemProps} />;
25
+ });
26
+
27
+ export default () => {
28
+ return (
29
+ <ListBox>
30
+ {/* We can use `ListBox.Item` and add `useListItemRovingFocus`. Useful for one-off */}
31
+ <ListBox.Item data-id="first" elemPropsHook={useListItemRovingFocus}>
32
+ First
33
+ </ListBox.Item>
34
+ {/* Use a custom item. Useful for reusing components */}
35
+ <RovingFocusItem data-id="second">Second</RovingFocusItem>
36
+ <RovingFocusItem data-id="third">Third</RovingFocusItem>
37
+ </ListBox>
38
+ );
39
+ };
@@ -0,0 +1,58 @@
1
+ import React from 'react';
2
+
3
+ import {
4
+ useListItemRegister,
5
+ useListItemRovingFocus,
6
+ useListItemSelect,
7
+ useListModel,
8
+ ListItemProps,
9
+ ListBox,
10
+ } from '@workday/canvas-kit-react/collection';
11
+ import {
12
+ composeHooks,
13
+ createElemPropsHook,
14
+ createSubcomponent,
15
+ } from '@workday/canvas-kit-react/common';
16
+
17
+ // Create a custom hook for our item
18
+ const useItem = composeHooks(
19
+ createElemPropsHook(useListModel)((model, ref, elemProps: ListItemProps) => {
20
+ return {
21
+ role: 'listitem',
22
+ style: {
23
+ background: model.state.selectedIds.includes(elemProps['data-id']) ? 'gray' : 'white',
24
+ },
25
+ };
26
+ }),
27
+ useListItemSelect,
28
+ useListItemRovingFocus,
29
+ useListItemRegister
30
+ );
31
+
32
+ // Create a custom item
33
+ const SelectableItem = createSubcomponent('button')({
34
+ displayName: 'SelectableItem',
35
+ modelHook: useListModel,
36
+ elemPropsHook: useItem,
37
+ })<ListItemProps>((elemProps, Element) => {
38
+ return <Element {...elemProps} />;
39
+ });
40
+
41
+ export default () => {
42
+ const model = useListModel({
43
+ initialSelectedIds: ['first'],
44
+ orientation: 'horizontal',
45
+ });
46
+ return (
47
+ <>
48
+ <ListBox model={model}>
49
+ <SelectableItem data-id="first">First</SelectableItem>
50
+ <SelectableItem data-id="second">Second</SelectableItem>
51
+ <SelectableItem data-id="third">Third</SelectableItem>
52
+ </ListBox>
53
+
54
+ <p>Cursor ID: {model.state.cursorId}</p>
55
+ <p>Selected ID: {model.state.selectedIds[0]}</p>
56
+ </>
57
+ );
58
+ };