@workday/canvas-kit-docs 6.0.0-beta.0-next.15 → 6.0.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 (82) hide show
  1. package/LICENSE +1 -1
  2. package/dist/commonjs/lib/specs.js +263 -33
  3. package/dist/es6/lib/specs.js +263 -33
  4. package/dist/mdx/4.0-MIGRATION-GUIDE.mdx +1 -1
  5. package/dist/mdx/6.0-MIGRATION-GUIDE.mdx +554 -0
  6. package/dist/mdx/COMPOUND_COMPONENTS.mdx +31 -30
  7. package/dist/mdx/CONTRIBUTING.mdx +90 -63
  8. package/dist/mdx/labs-react/search-form/SearchForm.mdx +64 -0
  9. package/dist/mdx/labs-react/search-form/examples/Basic.tsx +61 -0
  10. package/dist/mdx/labs-react/search-form/examples/CustomTheme.tsx +72 -0
  11. package/dist/mdx/labs-react/search-form/examples/Grow.tsx +62 -0
  12. package/dist/mdx/labs-react/search-form/examples/PropTables.splitProps.tsx +4 -0
  13. package/dist/mdx/labs-react/search-form/examples/RTL.tsx +70 -0
  14. package/dist/mdx/labs-react/search-form/examples/Theming.tsx +64 -0
  15. package/dist/mdx/labs-react/text-input/TextInput.mdx +123 -0
  16. package/dist/mdx/labs-react/text-input/examples/Alert.tsx +46 -0
  17. package/dist/mdx/labs-react/text-input/examples/Basic.tsx +20 -0
  18. package/dist/mdx/labs-react/text-input/examples/Disabled.tsx +20 -0
  19. package/dist/mdx/labs-react/text-input/examples/Error.tsx +43 -0
  20. package/dist/mdx/labs-react/text-input/examples/Grow.tsx +20 -0
  21. package/dist/mdx/labs-react/text-input/examples/HiddenLabel.tsx +17 -0
  22. package/dist/mdx/labs-react/text-input/examples/LabelPosition.tsx +20 -0
  23. package/dist/mdx/labs-react/text-input/examples/LoginForm.tsx +100 -0
  24. package/dist/mdx/labs-react/text-input/examples/Password.tsx +20 -0
  25. package/dist/mdx/labs-react/text-input/examples/Placeholder.tsx +20 -0
  26. package/dist/mdx/labs-react/text-input/examples/RefForwarding.tsx +27 -0
  27. package/dist/mdx/labs-react/text-input/examples/Required.tsx +20 -0
  28. package/dist/mdx/labs-react/text-input/examples/ThemedAlert.tsx +51 -0
  29. package/dist/mdx/labs-react/text-input/examples/ThemedError.tsx +40 -0
  30. package/dist/mdx/preview-react/breadcrumbs/Breadcrumbs.mdx +1 -1
  31. package/dist/mdx/preview-react/menu/Menu.mdx +17 -9
  32. package/dist/mdx/preview-react/menu/examples/Basic.tsx +65 -10
  33. package/dist/mdx/preview-react/menu/examples/ContextMenu.tsx +45 -29
  34. package/dist/mdx/preview-react/menu/examples/CustomMenuItem.tsx +2 -2
  35. package/dist/mdx/preview-react/menu/examples/Icons.tsx +1 -1
  36. package/dist/mdx/preview-react/menu/examples/ManyItems.tsx +2 -2
  37. package/dist/mdx/preview-react/side-panel/SidePanel.mdx +1 -1
  38. package/dist/mdx/react/action-bar/ActionBar.mdx +1 -1
  39. package/dist/mdx/react/button/button/Button.mdx +34 -9
  40. package/dist/mdx/react/button/button/examples/Primary.tsx +10 -1
  41. package/dist/mdx/react/button/button/examples/PrimaryInverse.tsx +14 -0
  42. package/dist/mdx/react/button/button/examples/Secondary.tsx +10 -1
  43. package/dist/mdx/react/button/button/examples/SecondaryInverse.tsx +14 -0
  44. package/dist/mdx/react/button/button/examples/Tertiary.tsx +10 -1
  45. package/dist/mdx/react/button/button/examples/TertiaryInverse.tsx +14 -0
  46. package/dist/mdx/react/button/icon-button/IconButton.mdx +1 -1
  47. package/dist/mdx/react/card/card.mdx +1 -1
  48. package/dist/mdx/react/pagination/PropTables.splitprops.tsx +47 -0
  49. package/dist/mdx/react/pagination/examples/{StepControls.tsx → Basic.tsx} +1 -1
  50. package/dist/mdx/react/pagination/examples/GoToForm.tsx +1 -1
  51. package/dist/mdx/react/pagination/examples/HoistedModel.tsx +36 -22
  52. package/dist/mdx/react/pagination/examples/RTL.tsx +1 -1
  53. package/dist/mdx/react/pagination/pagination.mdx +225 -474
  54. package/dist/mdx/react/popup/Popup.mdx +34 -36
  55. package/dist/mdx/react/radio/examples/Alert.tsx +3 -3
  56. package/dist/mdx/react/radio/examples/Basic.tsx +3 -3
  57. package/dist/mdx/react/radio/examples/Disabled.tsx +3 -3
  58. package/dist/mdx/react/radio/examples/Error.tsx +3 -3
  59. package/dist/mdx/react/radio/examples/LabelPosition.tsx +3 -3
  60. package/dist/mdx/react/radio/examples/NoValue.tsx +3 -3
  61. package/dist/mdx/react/radio/examples/RefForwarding.tsx +3 -3
  62. package/dist/mdx/react/radio/examples/Required.tsx +3 -3
  63. package/dist/mdx/react/segmented-control/SegmentedControl.mdx +1 -1
  64. package/dist/mdx/react/tabs/Tabs.mdx +160 -88
  65. package/dist/mdx/react/tabs/TabsModel.splitprops.tsx +5 -0
  66. package/dist/mdx/react/tabs/examples/{Simple.tsx → Basic.tsx} +0 -0
  67. package/dist/mdx/react/tabs/examples/DisabledTab.tsx +1 -1
  68. package/dist/mdx/react/tabs/examples/DynamicTabs.tsx +41 -13
  69. package/dist/mdx/react/tabs/examples/HoistedModel.tsx +4 -4
  70. package/dist/mdx/react/tabs/examples/Icons.tsx +36 -0
  71. package/dist/mdx/react/tabs/examples/{NamedKeys.tsx → NamedTabs.tsx} +0 -0
  72. package/dist/mdx/react/tabs/examples/OverflowTabs.tsx +58 -0
  73. package/dist/mdx/react/tabs/examples/SinglePanel.tsx +1 -1
  74. package/dist/mdx/react/text-area/TextArea.mdx +1 -1
  75. package/dist/mdx/react/toast/toast.mdx +1 -17
  76. package/dist/mdx/react/tooltip/Tooltip.mdx +1 -1
  77. package/dist/mdx/react/tooltip/examples/Ellipsis.tsx +6 -0
  78. package/package.json +3 -3
  79. package/dist/mdx/CODE_OF_CONDUCT.md +0 -68
  80. package/dist/mdx/preview-react/menu/examples/ContextMenuTarget.tsx +0 -33
  81. package/dist/mdx/preview-react/menu/examples/ControlButton.tsx +0 -84
  82. package/dist/mdx/react/pagination/examples/ShowAdditionalDetails.tsx +0 -52
@@ -1,17 +1,30 @@
1
1
  import {Tabs} from '@workday/canvas-kit-react/tabs';
2
2
  import {Specifications} from '@workday/canvas-kit-docs';
3
3
 
4
- import Simple from './examples/Simple';
5
- import NamedKeys from './examples/NamedKeys';
4
+ import Basic from './examples/Basic';
5
+ import NamedTabs from './examples/NamedTabs';
6
6
  import RightToLeft from './examples/RightToLeft';
7
+ import OverflowTabs from './examples/OverflowTabs';
7
8
  import DisabledTab from './examples/DisabledTab';
9
+ import Icons from './examples/Icons';
8
10
  import SinglePanel from './examples/SinglePanel';
9
11
  import AlternativeTabStop from './examples/AlternativeTabStop';
10
12
  import HoistedModel from './examples/HoistedModel';
11
13
  import DynamicTabs from './examples/DynamicTabs';
14
+ import {
15
+ TabsModelConfigComponent,
16
+ TabsStateComponent,
17
+ TabsEventsComponent,
18
+ } from './TabsModel.splitprops.tsx';
12
19
 
13
20
 
14
- # Canvas Kit React Tabs
21
+ # Canvas Kit Tabs
22
+
23
+ `Tabs` is a [compound component](/getting-started/for-developers/resources/compound-components/)
24
+ that allows users to navigate between related views of content while remaining in context of the
25
+ page.
26
+
27
+ [> Workday Design Reference](https://design.workday.com/components/navigation/tabs)
15
28
 
16
29
  ## Installation
17
30
 
@@ -21,85 +34,98 @@ yarn add @workday/canvas-kit-react
21
34
 
22
35
  ## Usage
23
36
 
24
- This component follows the
25
- [W3 Tabs specification](https://www.w3.org/TR/wai-aria-practices/#tabpanel). `Tabs` is a
26
- [Compound Component](/getting-started/for-developers/resources/compound-components/), which means it
27
- can be composed in a variety of different ways. We'll first cover some basic usage examples followed
28
- by more advanced usage.
37
+ ### Basic Example
29
38
 
30
- ### Basic Usage
39
+ `Tabs` includes a container `Tabs` component and the following subcomponents which can be composed
40
+ in a variety of ways: `Tabs.List`, `Tabs.Item` and `Tabs.Panel`. It follows the
41
+ [W3 Tabs specification](https://www.w3.org/TR/wai-aria-practices/#tabpanel).
31
42
 
32
- Below are examples we expect will work for most cases. Please refer to the
33
- [Advanced Usage](#advanced-usage) section for details on supporting custom implementations.
43
+ In this example, we set up a basic `Tabs` component with five tabs. This example uses a static API
44
+ that does not support overflow.
34
45
 
35
- #### Basic Example
46
+ <ExampleCodeBlock code={Basic} />
36
47
 
37
- In this example, a few tab items and tab panels are set up without any named keys.
48
+ ### Overflow Tabs
38
49
 
39
- <ExampleCodeBlock code={Simple} />
50
+ Tabs is a responsive component based on the width of its container. If the rendered tabs exceed the
51
+ width of the `Tabs.List`, an overflow menu will be rendered. This only works against the dynamic API
52
+ where you give the `TabsModel` an array of items to be rendered. The dynamic API handles the React
53
+ `key` for you based on the item's identifier. The dynamic API requires either an `id` on each item
54
+ object or a `getId` function that returns an identifier based on the item. The below example uses an
55
+ `id` property on each item.
40
56
 
41
- #### Named Keys
57
+ The dynamic API takes in any object, but since nothing is known about your object, a
58
+ [render prop](https://reactjs.org/docs/render-props.html) is necessary to instruct a list how it
59
+ should render.
42
60
 
43
- `Tabs.Item` and `Tabs.Panel` both take an optional `name` attribute that are used for the
44
- `onActivate` callback. This example is the same, but with named keys for the tabs and panels.
61
+ <ExampleCodeBlock code={OverflowTabs} />
45
62
 
46
- <ExampleCodeBlock code={NamedKeys} />
63
+ ### Hoisted Model
47
64
 
48
- #### Right-to-Left
65
+ By default, `Tabs` will create and use its own [model](#model) internally. Alternatively, you may
66
+ configure your own model with `useTabsModel` and pass it to `Tabs` via the `model` prop. This
67
+ pattern is referred to as
68
+ [hoisting the model](/getting-started/for-developers/resources/compound-components/#configuring-a-model)
69
+ and provides direct access to its `state` and `events` outside of the `Tabs` component.
49
70
 
50
- `Tabs` supports right-to-left through the theme of the `CanvasProvider`.
71
+ In this example, we set up external observation of the model state and create an external button to
72
+ trigger an event to change the active tab.
51
73
 
52
- <ExampleCodeBlock code={RightToLeft} />
74
+ <ExampleCodeBlock code={HoistedModel} />
53
75
 
54
- #### Disabled Tab
76
+ ### Named Tabs
55
77
 
56
- A `Tab.Item` can be disabled by passing `disabled={true}`.
78
+ `Tabs.Item` and `Tabs.Panel` both take an optional `name` attribute that is used for the
79
+ `onActivate` callback. This example is identical to the Basic Example, but with named tabs for the
80
+ `Tabs.Item` and `Tabs.Panel` subcomponents.
57
81
 
58
- <ExampleCodeBlock code={DisabledTab} />
82
+ <ExampleCodeBlock code={NamedTabs} />
59
83
 
60
- #### Alternative Tab Stop
84
+ ### Right-to-Left (RTL)
61
85
 
62
- By default, tab panels are focusable for accessibility. If the contents of a tab panel have a
63
- focusable element, you may disable this default behavior by setting `tabIndex` to `undefined`. This
64
- example has a tab panel with a focusable button in the tab panel.
86
+ `Tabs` supports right-to-left languages when specified in the `CanvasProvider` `theme`.
65
87
 
66
- <ExampleCodeBlock code={AlternativeTabStop} />
88
+ <ExampleCodeBlock code={RightToLeft} />
67
89
 
68
- ### Advanced Usage
90
+ ### Disabled Tab
69
91
 
70
- Below are some examples for more advanced / custom use cases. We expect most people won't need to
71
- read this section, but if you're needing to go beyond basic examples or are curious, feel free to
72
- explore this section. While these examples are not exhaustive, they provide additional insight into
73
- what's possible.
92
+ Set the `disabled` prop of a `Tabs.Item` to `true` to disable it.
74
93
 
75
- #### Hoisted Model
94
+ <ExampleCodeBlock code={DisabledTab} />
76
95
 
77
- The `Tabs` component takes in an optional `model` property. If not defined, it will create and use
78
- its own. Hoisting the model allows access to state and events outside the `Tabs` component family.
79
- You can create a `TabsModel` using the `useTabsModel` hook and configure the model with the same
80
- configuration that the `Tabs` component receives. If you pass in a configured model, configuration
81
- properties passed to the `Tabs` component will be ignored.
96
+ ### Tab Icons
82
97
 
83
- In this example, we'll set up external observation of the `TabsModel` state and set up an external
84
- button to trigger an event to change the currently active tab.
98
+ Tabs can have icons. You must set `hasIcon` on the `Tabs.Item` and use the `Icon` and `Text`
99
+ subcomponent. The `hasIcon` changes the `Tabs.Item` to change where overflow detection is from the
100
+ `Tabs.Item` element to the `Tabs.Item.Text` element.
85
101
 
86
- <ExampleCodeBlock code={HoistedModel} />
102
+ <ExampleCodeBlock code={Icons} />
103
+
104
+ ### Alternative Tab Stop
87
105
 
88
- #### Single Tab Panel
106
+ By default, tab panels are focusable for accessibility. If the contents of a tab panel have a
107
+ focusable element, you may disable this default behavior by setting the `tabIndex` prop of
108
+ `Tabs.Panel` to `undefined`. This example has a tab panel with a focusable button.
109
+
110
+ <ExampleCodeBlock code={AlternativeTabStop} />
89
111
 
90
- The compound component patterns allows advanced composition. For example, the tabs can be composed
91
- to have only a single tab panel using attribute overrides and callbacks. More info about attributes
92
- and callbacks are in property tables below for each subcomponent. In this example, we'll use a
93
- Hoisted model and the `activeTab` property of the state to show content of our `contents` object.
112
+ ### Single Tab Panel
113
+
114
+ The compound component pattern allows for advanced composition. For example, `Tabs` can be composed
115
+ to have only a single `Tabs.Panel` using attribute overrides and callbacks. More information about
116
+ attributes and callbacks can be found in the prop tables below for each subcomponent.
117
+
118
+ In this example, we use a hoisted model and the `activeTab` property of the state to show content
119
+ from the `contents` object.
94
120
 
95
121
  <ExampleCodeBlock code={SinglePanel} />
96
122
 
97
- #### Dynamic Tabs
123
+ ### Dynamic Tabs
98
124
 
99
125
  The `Tabs.Item` component takes in an optional `index` property if you want to specify the position
100
- of a tab. If not defined, by default it will append tabs to the end. For example, if your tabs are
101
- stored as an array in the state that can be added to along with a fixed tab that should remain at
102
- the end.
126
+ of a tab. If not defined, by default it will append tabs to the end. In this example, our tabs are
127
+ stored as an array in the state, and we have a fixed tab at the end that can add new tabs to that
128
+ array.
103
129
 
104
130
  <ExampleCodeBlock code={DynamicTabs} />
105
131
 
@@ -107,83 +133,129 @@ the end.
107
133
 
108
134
  ### Tabs
109
135
 
110
- The `Tabs` component is the container component that is responsible for creating a `TabsModel` that
111
- is shared using React context. It does not represent a real element.
112
-
113
136
  #### Usage
114
137
 
138
+ `Tabs` is a container component that is responsible for creating a `TabsModel` and sharing it with
139
+ its subcomponents using React context. It does not represent a real element.
140
+
115
141
  ```tsx
116
- // configuration
117
- <Tabs onActivate={({ data }) => console.log('Activate tab', data.tab)}>
118
- {/* sub components go here */ }
142
+ <Tabs onActivate={({data}) => console.log('Activated tab', data.tab)}>
143
+ {/* Child components */}
119
144
  </Tabs>
145
+ ```
120
146
 
121
- // OR
147
+ Alternatively, you may pass in a model using the hoisted model pattern.
122
148
 
123
- // model
124
- const model = useTabsModel(config)
149
+ ```tsx
150
+ const model = useTabsModel({
151
+ onActivate({data}) {
152
+ console.log('Activated Tab', data.tab);
153
+ },
154
+ });
125
155
 
126
- <Tabs model={model}>
127
- {/* sub components go here */ }
128
- </Tabs>
156
+ <Tabs model={model}>{/* Child components */}</Tabs>;
129
157
  ```
130
158
 
131
- #### Component Props
159
+ #### Props
132
160
 
133
- <PropsTable of={Tabs} />
161
+ Note that if you pass in a `model` configured with `useTabsModel`, configuration props passed to
162
+ `Tabs` will be ignored.
134
163
 
135
- ---
164
+ <ArgsTable of={Tabs} />
136
165
 
137
166
  ### Tabs.List
138
167
 
139
- `Tabs.List` is a `div` element with a `role=tablist`. It is a container for `Tabs.Item` components.
140
- Any additional attributes provided will be forwared to the dom element.
141
-
142
168
  #### Usage
143
169
 
170
+ `Tabs.List` is a `<div role="tablist">` element. It is a container for `Tabs.Item` subcomponents.
171
+
144
172
  ```tsx
145
- <Tabs.List>{/* Tabs.Items go here */}</Tabs.List>
173
+ <Tabs.List>{/* Tabs.Items */}</Tabs.List>
146
174
  ```
147
175
 
148
- #### Component Props
176
+ #### Props
149
177
 
150
- <PropsTable of={Tabs.List} />
178
+ Undocumented props are spread to the underlying `<div>` element.
151
179
 
152
- ---
180
+ <ArgsTable of={Tabs.List} />
153
181
 
154
182
  ### Tabs.Item
155
183
 
156
- `Tabs.Item` is a `button` element with a `role=tab`. Each `Tabs.Item` is associated with a
157
- `Tabs.Panel` either by a `name` attribute or by the position in the list. If a `name` is provided,
158
- it must match the name passed to the `Tabs.Panel` component.
159
-
160
184
  #### Usage
161
185
 
186
+ `Tabs.Item` is a `<button role="tab">` element. Each `Tabs.Item` is associated with a `Tabs.Panel`
187
+ either by a `name` attribute or by the position in the list. If a `name` is provided, it must match
188
+ the name passed to the corresponding `Tabs.Panel` component.
189
+
162
190
  ```tsx
163
191
  <Tabs.Item name="first">First Tab</Tabs.Item>
164
192
  ```
165
193
 
166
- #### Component Props
194
+ #### Props
167
195
 
168
- <PropsTable of={Tabs.Item} />
196
+ Undocumented props are spread to the underlying `button` element.
169
197
 
170
- ---
198
+ <ArgsTable of={Tabs.Item} />
171
199
 
172
200
  ### Tabs.Panel
173
201
 
174
- `Tabs.Panel` is a `div` element with a `role=tabpanel`. It is focusable by default. Each
175
- `Tabs.Panel` is controlled by a `Tabs.Item` either by a `name` attribute or by the position in the
176
- list. If a `name` is provided, it must match the name passed to the `Tabs.Item` component.
177
-
178
202
  #### Usage
179
203
 
204
+ `Tabs.Panel` is a `<div role="tabpanel">` element. It is focusable by default. Each `Tabs.Panel` is
205
+ controlled by a `Tabs.Item` either by a `name` attribute or by the position in the list. If a `name`
206
+ is provided, it must match the name passed to the corresponding `Tabs.Item` component.
207
+
208
+ ```tsx
209
+ <Tabs.Panel name="first">{/* Contents of the tab panel */}</Tabs.Panel>
210
+ ```
211
+
212
+ #### Props
213
+
214
+ Undocumented props are spread to the underlying `<div>` element.
215
+
216
+ <ArgsTable of={Tabs.Panel} />
217
+
218
+ ## Model
219
+
220
+ If `Tabs` was stripped of all its markup, attributes, and styling, what would remain is the
221
+ [model](/getting-started/for-developers/resources/compound-components/#models). The model is an
222
+ object composed of two parts: `state` which describes the current snapshot in time of the component
223
+ and `events` which describes events that can be sent to the model.
224
+
225
+ By default, `Tabs` will create a model and share it internally with its subcomponents using React
226
+ context. Alternatively, if you need direct access to the model's `state` and `events` outside of the
227
+ `Tabs` component, you may configure your own model with `useTabsModel` and pass it to `Tabs` via a
228
+ pattern called
229
+ [hoisting the model](/getting-started/for-developers/resources/compound-components/#configuring-a-model).
230
+
180
231
  ```tsx
181
- <Tabs.Panel name="first">{/* contents of the tab panel */}</Tabs.Panel>
232
+ const model = useTabsModel({
233
+ onActivate({data}) {
234
+ console.log('Activated Tab', data);
235
+ },
236
+ });
237
+
238
+ <Tabs model={model}>{/* Child components */}</Tabs>;
182
239
  ```
183
240
 
184
- #### Component Props
241
+ ### Config
242
+
243
+ `useTabsModel` accepts a configuration object with the following properties and returns a
244
+ `TabsModel` with `state` and `events` properties.
245
+
246
+ <ArgsTable of={TabsModelConfigComponent} />
247
+
248
+ ### State
249
+
250
+ The `TabsModel` `state` is an object with the following properties.
251
+
252
+ <ArgsTable of={TabsStateComponent} />
253
+
254
+ ### Events
255
+
256
+ The `TabsModel` `events` is an object with the following properties.
185
257
 
186
- <PropsTable of={Tabs.Panel} />
258
+ <ArgsTable of={TabsEventsComponent} />
187
259
 
188
260
  ## Specifications
189
261
 
@@ -0,0 +1,5 @@
1
+ import {TabsModelConfig, TabsState, TabsEvents} from '@workday/canvas-kit-react/tabs';
2
+
3
+ export const TabsModelConfigComponent = (_: TabsModelConfig) => <div />;
4
+ export const TabsStateComponent = (_: TabsState) => <div />;
5
+ export const TabsEventsComponent = (_: TabsEvents) => <div />;
@@ -8,7 +8,7 @@ export default () => {
8
8
  <Tabs>
9
9
  <Tabs.List>
10
10
  <Tabs.Item>First Tab</Tabs.Item>
11
- <Tabs.Item disabled>Disabled Tab</Tabs.Item>
11
+ <Tabs.Item aria-disabled>Disabled Tab</Tabs.Item>
12
12
  <Tabs.Item>Third Tab</Tabs.Item>
13
13
  </Tabs.List>
14
14
  <div style={{marginTop: space.m}}>
@@ -1,22 +1,50 @@
1
1
  import React from 'react';
2
2
  import {space} from '@workday/canvas-kit-react/tokens';
3
3
 
4
- import {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';
4
+ import {Tabs, useTabsModel, TabsModel} from '@workday/canvas-kit-react/tabs';
5
+ import {SelectionModel} from '../../lib/selection';
5
6
 
6
7
  export default () => {
7
8
  const [tabs, setTabs] = React.useState([
8
- {tab: 'Tab 1', name: 'tab-1'},
9
- {tab: 'Tab 2', name: 'tab-2'},
10
- {tab: 'Tab 3', name: 'tab-3'},
9
+ {tab: 'Tab 1', id: 'tab-1'},
10
+ {tab: 'Tab 2', id: 'tab-2'},
11
+ {tab: 'Tab 3', id: 'tab-3'},
11
12
  ]);
12
13
  const addedRef = React.useRef(tabs.length);
13
14
  const model = useTabsModel({
14
- shouldActivate: ({data}) => data.tab !== 'last',
15
+ shouldSelect: ({data}) => data.id !== 'last',
15
16
  });
16
17
 
17
- const onKeyDown = (e: React.KeyboardEvent<HTMLElement>, name: string) => {
18
- if (e.key === 'Backspace') {
19
- setTabs(tabs.filter(item => item.name !== name));
18
+ /**
19
+ * Helper function that should be called when an item is programmatically removed. The following
20
+ * side effects depend on state of the model:
21
+ * * **Item is focused**: Focus will be moved to next item in the list
22
+ * * **Item is selected**: Selection will be moved to the next item in the list
23
+ * @param id The id of the item that will be removed
24
+ */
25
+ const removeItem = (id: string, model: SelectionModel) => {
26
+ const index = model.state.items.findIndex(item => model.getId(item) === model.state.cursorId);
27
+ const nextIndex = index === model.state.items.length - 1 ? index - 1 : index + 1;
28
+ const nextId = model.getId(model.state.items[nextIndex]);
29
+ if (model.state.selectedIds[0] === id) {
30
+ // We're removing the currently selected item. Select next item
31
+ model.events.select({id: nextId});
32
+ }
33
+ if (model.state.cursorId === id) {
34
+ // We're removing the currently focused item. Focus next item
35
+ model.events.goTo({id: nextId});
36
+
37
+ // wait for stabilization of state
38
+ requestAnimationFrame(() => {
39
+ document.querySelector<HTMLElement>(`#${model.state.id}-${nextId}`)?.focus();
40
+ });
41
+ }
42
+ };
43
+
44
+ const onKeyDown = (e: React.KeyboardEvent<HTMLElement>, id: string) => {
45
+ if (e.key === 'Delete') {
46
+ setTabs(tabs.filter(item => item.id !== id));
47
+ removeItem(id, model);
20
48
  }
21
49
  };
22
50
 
@@ -25,10 +53,10 @@ export default () => {
25
53
  <Tabs.List>
26
54
  {tabs.map((item, index) => (
27
55
  <Tabs.Item
28
- key={item.name}
29
- name={item.name}
56
+ key={item.id}
57
+ name={item.id}
30
58
  index={index}
31
- onKeyDown={e => onKeyDown(e, item.name)}
59
+ onKeyDown={e => onKeyDown(e, item.id)}
32
60
  >
33
61
  {item.tab}
34
62
  </Tabs.Item>
@@ -40,7 +68,7 @@ export default () => {
40
68
  onClick={() => {
41
69
  addedRef.current += 1;
42
70
  setTabs(tabs =>
43
- tabs.concat({tab: `Tab ${addedRef.current}`, name: `tab-${addedRef.current}`})
71
+ tabs.concat({tab: `Tab ${addedRef.current}`, id: `tab-${addedRef.current}`})
44
72
  );
45
73
  model.events.goTo({id: 'last'});
46
74
  }}
@@ -50,7 +78,7 @@ export default () => {
50
78
  </Tabs.List>
51
79
  <div style={{marginTop: space.m}}>
52
80
  {tabs.map((item, index) => (
53
- <Tabs.Panel key={item.name} name={item.name}>
81
+ <Tabs.Panel key={item.id} name={item.id}>
54
82
  Contents of {item.tab}
55
83
  </Tabs.Panel>
56
84
  ))}
@@ -6,8 +6,8 @@ import {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';
6
6
 
7
7
  export default () => {
8
8
  const model = useTabsModel({
9
- onActivate({data, prevState}) {
10
- console.log('Activated Tab', data, prevState);
9
+ onSelect({data, prevState}) {
10
+ console.log('Selected Tab', data, prevState);
11
11
  },
12
12
  });
13
13
 
@@ -27,10 +27,10 @@ export default () => {
27
27
  </Tabs>
28
28
  <SecondaryButton
29
29
  onClick={() => {
30
- model.events.activate({tab: 'third'});
30
+ model.events.select({id: 'third'});
31
31
  }}
32
32
  >
33
- Activate third tab
33
+ Select Third Tab
34
34
  </SecondaryButton>
35
35
  </>
36
36
  );
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+
3
+ import {space} from '@workday/canvas-kit-react/tokens';
4
+ import {starIcon, searchIcon, selectIcon, shareIcon} from '@workday/canvas-system-icons-web';
5
+ import {Tabs} from '@workday/canvas-kit-react/tabs';
6
+
7
+ export default () => {
8
+ return (
9
+ <Tabs>
10
+ <Tabs.List>
11
+ <Tabs.Item hasIcon>
12
+ <Tabs.Item.Icon icon={starIcon} />
13
+ <Tabs.Item.Text>First Tab</Tabs.Item.Text>
14
+ </Tabs.Item>
15
+ <Tabs.Item hasIcon>
16
+ <Tabs.Item.Icon icon={searchIcon} />
17
+ <Tabs.Item.Text>Second Tab</Tabs.Item.Text>
18
+ </Tabs.Item>
19
+ <Tabs.Item hasIcon>
20
+ <Tabs.Item.Icon icon={selectIcon} />
21
+ <Tabs.Item.Text>Third Tab</Tabs.Item.Text>
22
+ </Tabs.Item>
23
+ <Tabs.Item hasIcon>
24
+ <Tabs.Item.Icon icon={shareIcon} />
25
+ <Tabs.Item.Text>Fourth Tab</Tabs.Item.Text>
26
+ </Tabs.Item>
27
+ </Tabs.List>
28
+ <div style={{marginTop: space.m}}>
29
+ <Tabs.Panel>Contents of First Tab</Tabs.Panel>
30
+ <Tabs.Panel>Contents of Second Tab</Tabs.Panel>
31
+ <Tabs.Panel>Contents of Third Tab</Tabs.Panel>
32
+ <Tabs.Panel>Contents of Fourth Tab</Tabs.Panel>
33
+ </div>
34
+ </Tabs>
35
+ );
36
+ };
@@ -0,0 +1,58 @@
1
+ import React from 'react';
2
+
3
+ import {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';
4
+ import {HStack} from '@workday/canvas-kit-labs-react';
5
+ import {SecondaryButton} from '../../../button';
6
+
7
+ type MyTabItem = {
8
+ id: string;
9
+ text: React.ReactNode;
10
+ contents: string;
11
+ };
12
+
13
+ export default () => {
14
+ const [items] = React.useState<MyTabItem[]>([
15
+ {id: 'first', text: 'First Tab', contents: 'Contents of First Tab'},
16
+ {id: 'second', text: 'Second Tab', contents: 'Contents of Second Tab'},
17
+ {id: 'third', text: 'Third Tab', contents: 'Contents of Third Tab'},
18
+ {id: 'fourth', text: 'Fourth Tab', contents: 'Contents of Fourth Tab'},
19
+ {id: 'fifth', text: 'Fifth Tab', contents: 'Contents of Fifth Tab'},
20
+ {id: 'sixth', text: 'Sixth Tab', contents: 'Contents of Sixth Tab'},
21
+ {id: 'seventh', text: 'Seventh Tab', contents: 'Contents of Seventh Tab'},
22
+ ]);
23
+ const model = useTabsModel({
24
+ items,
25
+ });
26
+ const [containerWidth, setContainerWidth] = React.useState('100%');
27
+ return (
28
+ <div style={{width: containerWidth}}>
29
+ <Tabs model={model}>
30
+ <Tabs.List overflowButton={<Tabs.OverflowButton>More</Tabs.OverflowButton>}>
31
+ {(item: MyTabItem) => <Tabs.Item name={item.id}>{item.text}</Tabs.Item>}
32
+ </Tabs.List>
33
+ <Tabs.Menu.Popper>
34
+ <Tabs.Menu.Card maxWidth={300} maxHeight={200}>
35
+ <Tabs.Menu.List>
36
+ {(item: MyTabItem) => <Tabs.Menu.Item name={item.id}>{item.text}</Tabs.Menu.Item>}
37
+ </Tabs.Menu.List>
38
+ </Tabs.Menu.Card>
39
+ </Tabs.Menu.Popper>
40
+ <Tabs.Panels>
41
+ {(item: MyTabItem) => (
42
+ <Tabs.Panel marginTop="m" name={item.id}>
43
+ {item.contents}
44
+ </Tabs.Panel>
45
+ )}
46
+ </Tabs.Panels>
47
+ </Tabs>
48
+ <hr />
49
+ <h4>Change tab container size</h4>
50
+ <HStack spacing="xs">
51
+ <SecondaryButton onClick={() => setContainerWidth('100%')}>100%</SecondaryButton>
52
+ <SecondaryButton onClick={() => setContainerWidth('500px')}>500px</SecondaryButton>
53
+ <SecondaryButton onClick={() => setContainerWidth('235px')}>235px</SecondaryButton>
54
+ <SecondaryButton onClick={() => setContainerWidth('150px')}>150px</SecondaryButton>
55
+ </HStack>
56
+ </div>
57
+ );
58
+ };
@@ -34,7 +34,7 @@ export default () => {
34
34
  </Tabs.Item>
35
35
  </Tabs.List>
36
36
  <Tabs.Panel style={{marginTop: space.m}} hidden={undefined} id="mytab-panel">
37
- {contents[model.state.activeTab]}
37
+ {contents[model.state.selectedIds[0]]}
38
38
  </Tabs.Panel>
39
39
  </Tabs>
40
40
  );
@@ -23,7 +23,7 @@ Text Areas allow users to enter and edit multiple lines of text.
23
23
  ## Installation
24
24
 
25
25
  ```sh
26
- yarn add @workday/canvas-kit-react
26
+ yarn add @workday/canvas-kit-labs-react
27
27
  ```
28
28
 
29
29
  ## Usage
@@ -29,52 +29,36 @@ Below are examples we expect will work for most use cases. Note that all example
29
29
  they are an important signifier to communicate meaning. For this reason, Toast notifications should
30
30
  always include an icon.
31
31
 
32
- ---
33
-
34
32
  #### Complete Example with Popper
35
33
 
36
34
  We use Popper to position Toast. Here's an example of how to use them together.
37
35
 
38
36
  <ExampleCodeBlock code={WithPopper} />
39
37
 
40
- ---
41
-
42
38
  #### Success
43
39
 
44
40
  <ExampleCodeBlock code={Success} />
45
41
 
46
- ---
47
-
48
42
  #### Error
49
43
 
50
44
  <ExampleCodeBlock code={Error} />
51
45
 
52
- ---
53
-
54
46
  #### WithCloseButton
55
47
 
56
48
  <ExampleCodeBlock code={WithCloseButton} />
57
49
 
58
- ---
59
-
60
50
  #### With an Action Link
61
51
 
62
52
  <ExampleCodeBlock code={WithActionLink} />
63
53
 
64
- ---
65
-
66
54
  #### With an Action Link and CloseIcon
67
55
 
68
56
  <ExampleCodeBlock code={WithActionLinkAndCloseIcon} />
69
57
 
70
- ---
71
-
72
58
  #### With RTL
73
59
 
74
60
  <ExampleCodeBlock code={RTL} />
75
61
 
76
- ---
77
-
78
- ## Component Props
62
+ ## Props
79
63
 
80
64
  <ArgsTable of={Toast} />
@@ -168,7 +168,7 @@ example uses those parts directly while being functionally equivalent to the ori
168
168
 
169
169
  <ExampleCodeBlock code={UseTooltip} />
170
170
 
171
- ## Properties
171
+ ## Props
172
172
 
173
173
  <ArgsTable of={Tooltip} />
174
174