@workday/canvas-kit-docs 7.0.0-alpha.92-next.19 → 7.0.0-alpha.96-next.22

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.
@@ -1,31 +1,34 @@
1
1
  # Canvas Kit 7.0 Migration Guide
2
2
 
3
- Below are the breaking changes made in Canvas Kit v7. Please
3
+ This guide contains breaking changes in Canvas Kit v7. Please
4
4
  [reach out](https://github.com/Workday/canvas-kit/issues/new?labels=bug&template=bug.md) if you have
5
- any questions about the update.
5
+ any questions.
6
6
 
7
7
  - [Codemod](#codemod)
8
- - [Infrastructure](#infrastructure)
9
- - [Component Deprecations](#component-deprecations)
10
- - [Component Promotions](#component-promotion)
11
- - [Buttons](#buttons)
12
- - [Segmented Control](#segmented-control)
13
- - [Side Panel](#side-panel)
14
- - [Icons](#icons)
15
- - [ActionBar Component Updates](#actionbar-component-updates)
16
- - [Status Indicator Width](#status-indicator-width)
17
- - [Popup Cards](#popup-cards)
18
- - [Popper Props Update](#popper-props-update)
19
- - [Component Promotions](#component-promotion)
20
- - [Model Changes](#model-changes)
21
- - [Token Updates](#token-updates)
22
- - [Depth Tokens](#depth-tokens)
8
+ - [General Changes](#general-changes)
9
+ - [Dependency Upgrades](#dependency-upgrades)
10
+ - [Model Changes](#model-changes)
11
+ - [Tokens](#tokens)
12
+ - [Depth](#depth)
13
+ - [Components](#components)
14
+ - [Component Deprecations](#component-deprecations)
15
+ - [Component Promotions](#component-promotions)
16
+ - [Action Bar](#action-bar)
17
+ - [Banner](#banner)
18
+ - [Button](#button)
19
+ - [Icon](#icon)
20
+ - [Popper](#popper)
21
+ - [Popup](#popup)
22
+ - [Segmented Control](#segmented-control)
23
+ - [Side Panel](#side-panel)
24
+ - [Status Indicator](#status-indicator)
25
+ - [Tabs](#tabs)
23
26
 
24
27
  ## Codemod
25
28
 
26
29
  Please use our [codemod package](https://github.com/Workday/canvas-kit/tree/master/modules/codemod)
27
- to automatically update your code to work with a majority of the breaking changes in the migration
28
- from Canvas Kit v6 to v7:
30
+ to automatically update your code to work with many of the breaking changes as you migrate from
31
+ Canvas Kit v6 to v7:
29
32
 
30
33
  ```sh
31
34
  > npx @workday/canvas-kit-codemod v7 [path]
@@ -34,257 +37,584 @@ from Canvas Kit v6 to v7:
34
37
  > Note: This codemod only works on `.js`, `.jsx`, `.ts`, and `.tsx` extensions. You may need to make
35
38
  > some manual changes in other file types (`.json`, `.mdx`, `.md`, etc.).
36
39
 
37
- > Note: You may need to run your linter after executing the codemod, as it's resulting formatting
40
+ > Note: You may need to run your linter after executing the codemod, as its resulting formatting
38
41
  > (spacing, quotes, etc.) may not match your project's styling.
39
42
 
40
- **Breaking changes accounted for by this codemod will be marked with a 🤖.**
43
+ **Breaking changes handled by this codemod will be marked with a 🤖.**
41
44
 
42
45
  **Please verify all changes made by the codemod. As a safety precaution, we recommend committing the
43
46
  changes from the codemod as a single isolated commit (separate from other changes) so you can
44
47
  rollback more easily if necessary.**
45
48
 
46
49
  [Let us know](https://github.com/Workday/canvas-kit/issues/new?labels=bug&template=bug.md) if you
47
- encounter any issues or use cases that we've missed. The `@workday/canvas-kit-codemod` package will
48
- help us maintain additional codemod transforms to make future migrations easier.
50
+ encounter any issues or use cases that we've missed.
49
51
 
50
- ## Infrastructure
52
+ ## General Changes
51
53
 
52
- ## Infrastructure Upgrades
54
+ ### Dependency Upgrades
53
55
 
54
- Breaking:
56
+ We've upgraded to Emotion 11 and React 17 in v7. This allows teams to upgrade to newer versions of
57
+ Emotion and React without needing to maintain older versions in order to use Canvas Kit.
55
58
 
56
- - v7 now requires Typescript 4.1 and has dropped support for Typescript 3.5-3.9. Previously we used
57
- `downlevel-dts` to support Typescript 3.5+ while using Typescript 3.8 features, but
58
- `downlevel-dts` does not support the Typescript 4.1 features we use. Typescript 4.1 was release in
59
- November, 2020 and we feel it is time to move forward. Reach out if you experience issues
60
- upgrading your Typescript version. In our experience, Typescript 4.1 found a few more errors that
61
- Typescript 3.8 did not, but the upgrade was manageable.
59
+ As part of this upgrade, we've removed use of the `/** @jsx jsx */` pragma and `css` prop within
60
+ Canvas Kit. See our [React 17 discussion](https://github.com/Workday/canvas-kit/discussions/1455)
61
+ and [corresponding PR](https://github.com/Workday/canvas-kit/pull/1409) for more information on why
62
+ we made this change. Consumers may continue to use the `css` prop.
62
63
 
63
- ## Component Deprecations
64
+ To use v7, you'll need to upgrade the following dependencies:
64
65
 
65
- ### Deprecation Types
66
+ - React 16.14 OR React 17.X for backwards compatibility on JSX transform if you're using Babel or
67
+ TypeScript to compile code
68
+ - Emotion 11
69
+ - TypeScript 4.1 or higher, if applicable
70
+ - Babel 7.9 or higher, if applicable
71
+ - An Enzyme adapter for React 17, if applicable
66
72
 
67
- There are two types of deprecations: soft and hard.
73
+ > We no longer support TypeScript 3.5-3.9. Previously, we used `downlevel-dts` to support TypeScript
74
+ > 3.5+ while using TypeScript 3.8 features, but `downlevel-dts` does not support features we use in
75
+ > TypeScript 4.1. TypeScript 4.1 was released in November 2020, and we feel it is time to move
76
+ > forward. Reach out if you experience issues upgrading your TypeScript version. In our experience,
77
+ > TypeScript 4.1 found a few more errors than TypeScript 3.8, but the upgrade was manageable.
68
78
 
69
- #### Soft Deprecation
79
+ Please note that you may also need to update any side effect dependencies or linting packages with
80
+ this update.
70
81
 
71
- A soft-deprecated component is still available with its full functionality, but it will have been
72
- renamed with a prefix to indicate its soft-deprecated status. It will also include a console warning
73
- to announce its deprecation. This warning will only be triggered on the component's initial render.
82
+ View our [React 17](https://github.com/Workday/canvas-kit/discussions/1455) and
83
+ [Emotion 11](https://github.com/Workday/canvas-kit/discussions/1453) discussions to learn more about
84
+ any gotchas or tips and tricks with these upgrades. And of course, feel free to contribute to the
85
+ discussion with any questions or learnings of your own!
74
86
 
75
- Soft-deprecated types and utilities will also be renamed but generally will not trigger a console
76
- warning.
87
+ ---
77
88
 
78
- #### Hard Deprecation
89
+ ### Model Changes
79
90
 
80
- A hard-deprecated component or package is no longer available. You will need to follow the method
81
- prescribed in our migration guide to update your application. Please reach out to our team directly
82
- if you need additional help.
91
+ #### Guards and Callbacks
83
92
 
84
- ### Cookie Banner
93
+ We've changed the signature of model event guards and callbacks. In v6, the parameters were in an
94
+ object. This was a less than ideal developer experience as IntelliSense isn't engaged immediately
95
+ and we don't plan on adding any additional parameters to guard and callback functions. We've removed
96
+ the object wrapper.
85
97
 
86
- We are [hard deprecating](#hard-deprecation) `CookieBanner`. If you would like to migrate away from
87
- this deprecated component now, you can reference
88
- [this example](https://workday.github.io/canvas-kit/?path=/story/examples-cookiebanner-react--basic)
98
+ ```tsx
99
+ // v6
100
+ const model = useTabsModel({
101
+ onSelect({data: {id}, prevState}) {
102
+ console.log(id, prevState);
103
+ },
104
+ });
89
105
 
90
- ### Page Header
106
+ // v7
107
+ const model = useTabsModel({
108
+ onSelect({id}, prevState) {
109
+ console.log(id, prevState);
110
+ },
111
+ });
112
+ ```
91
113
 
92
- We are [hard deprecating](#hard-deprecation) `Page Header`. If you would like to migrate away from
93
- this deprecated component now, you can reference
94
- [this example](https://workday.github.io/canvas-kit/?path=/story/examples-pageheader-react--basic)
114
+ 🤖 The codemod will handle this change for you automatically.
95
115
 
96
- ### Header / GlobalHeader
116
+ #### Model Implementation
97
117
 
98
- We are [hard deprecating](#hard-deprecation) `Header`. If you would like to migrate away from this
99
- deprecated component now, you can reference
100
- [this example](https://workday.github.io/canvas-kit/?path=/story/examples-globalheader-react--basic)
118
+ If you don't extend models, you can skip this section.
101
119
 
102
- ## ActionBar Component Updates
120
+ In v6 we supported TypeScript 3.8 which limited the way types could be inferred and defined. v7
121
+ requires TypeScript 4.1 which introduced
122
+ [Template Literal Types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html).
123
+ This means guards and callbacks no longer need to be manually defined via an `eventMap`. Event maps
124
+ were a stopgap, manual, and prone to errors in defining them. Not all events have guards or
125
+ callbacks, and there's no way other than manual review to verify their existence. Template Literal
126
+ Types allow us to properly type guards and callbacks without event maps. The previous types forced
127
+ `data` to be an object. We've since dropped that restriction. You can still only pass a single
128
+ argument to events. If you need additional information, use an object.
103
129
 
104
- We've refactored our ActionBar components to simplify logic.
130
+ This change also allowed us to remove a lot of boilerplate associated with models without
131
+ sacrificing type safety. This change doesn't affect most use cases, but will affect those who
132
+ extended a model. We created a new `createModelHook` utility function to help set up types.
105
133
 
106
- PR: https://github.com/Workday/canvas-kit/pull/1396
134
+ ##### v6
107
135
 
108
- **Changes:**
136
+ ```ts
137
+ export type MyState = {
138
+ value: string;
139
+ };
109
140
 
110
- - Component has been converted to compound component.
111
- - `fixed` prop has been removed from component.
112
- - Now ActionBar uses `position` prop to set container position instead `fixed` prop.
113
- - Fixed position has been set as default if there is not passed `position` prop.
141
+ export type MyEvents = {
142
+ updateValue(data: {value: string}): void; // enforced that `data` is an object even if we only need to pass a string
143
+ };
114
144
 
115
- ## Status Indicator Width
145
+ export type MyModel = Model<MyState, MyEvents>;
116
146
 
117
- Status Indicators currently truncate when they reach their max width of `150px`. After receiving
118
- requests to increase this, we have upped it by 25% to `200px`.
147
+ export const myEventMap = createEventMap<MyEvents>()({
148
+ guards: {
149
+ shouldUpdateValue: 'updateValue', // easy to forget or make a mistake on guard name
150
+ },
151
+ callbacks: {
152
+ onUpdateValue: 'updateValue',
153
+ },
154
+ });
119
155
 
120
- We've also added a prop (`maxWidth`) to configure this if you need to. While this increases
121
- flexibility, please keep in mind that status text should be short, direct, and preferably a single
122
- word.
156
+ export type MyBaseConfig = {
157
+ initialValue?: string;
158
+ };
123
159
 
124
- ```tsx
125
- <StatusIndicator label="Slightly Longer Status" type={StatusIndicator.Type.Gray} maxWidth={250} />
160
+ export type MyConfig = MyBaseConfig & Partial<ToModelConfig<MyState, MyEvents, typeof myEventMap>>;
161
+
162
+ const useMyModel = (config: MyConfig = {}): MyModel => {
163
+ const [value, setValue] = React.useState(config.initialValue || '');
164
+
165
+ const state = {value};
166
+
167
+ // useEventMap is used to wrap the event object with guards and callbacks according to the event map
168
+ const events = useEventMap(myEventMap, state, config, {
169
+ updateValue(data) {
170
+ setValue(data.value);
171
+ },
172
+ });
173
+
174
+ return {state, events};
175
+ };
126
176
  ```
127
177
 
128
- ## Buttons
178
+ ##### v7
129
179
 
130
- To consolidate button APIs, we removed `IconButton` in favor of `PrimaryButton`, `SecondaryButton`
131
- and `TertiaryButton`.
180
+ ```tsx
181
+ const useMyModel = createModelHook({
182
+ defaultConfig: {
183
+ initialValue: '',
184
+ },
185
+ })(config => {
186
+ const [value, setValue] = React.useState(config.initialValue); // default is already handled
132
187
 
133
- ### Breaking Changes
188
+ const state = {value};
134
189
 
135
- - Removed the `toggled` prop when migrating from `IconButton`
136
- - Changed the values of `IconPosition: left | right` - > `IconPosition: start | end`
137
- - Remove `dataLabel` prop from `PrimaryButton` and `SecondaryButton`
190
+ const events = {
191
+ updateValue(value: string) {
192
+ // doesn't need to be an object anymore
193
+ setValue(value);
194
+ },
195
+ };
138
196
 
139
- 🤖 The codemod will handle all these changes automatically:
197
+ return {state, events};
198
+ });
199
+ ```
140
200
 
141
- - `iconPosition='left'` becomes `iconPosition='start'`
142
- - `iconPosition='right'` becomes `iconPosition='end'`
143
- - `<IconButton icon={plusIcon} />` becomes `<TertiaryButton icon={plusIcon} />`
144
- - `<IconButton variant='circleFilled' icon={plusIcon} />` becomes
145
- `<SecondaryButton icon={plusIcon} />`
146
- - `<IconButton variant='inverse' icon={plusIcon} />` becomes
147
- `<TertiaryButton variant='inverse' icon={plusIcon} />`
148
- - `<IconButton variant='inverseFilled' icon={plusIcon} />` becomes
149
- `<SecondaryButton variant='inverseFilled' icon={plusIcon} />`
201
+ Note the large reduction in TypeScript type boilerplate. In this example, the only place that
202
+ TypeScript syntax exists is in the `updateValue` function definition. This allows better collocating
203
+ of types and values. Also note that `useEventMap` is no longer needed. `createModelHook` will
204
+ automatically wrap the `events` returned to call guards and callbacks when appropriate. Today, this
205
+ is done by creating a new events object. Once we drop IE11 support, this will be done via a proxy
206
+ instead. `createModelHook` handles all type inference so you don't need to explicitly type
207
+ everything. `createModelHook` also attaches React Context directly to the hook along with
208
+ `defaultConfig` and `requiredConfig` for model extension.
150
209
 
151
- #### Manual Changes
210
+ If you extended a model, you'll notice all those types are no longer being exported. You'll have to
211
+ use this new utility function. Here's an example we found in the wild:
152
212
 
153
- The following changes will not be automatic updated and will require a manual update:
213
+ ##### v6
154
214
 
155
- - Remove `IconButton` variants: `plain`, `square`, and `squareFilled`
156
- - Remove `IconButtonProps`
157
- - Remove `IconButton` prop: `toggled`
158
- - Remove `PrimaryButton` and `SecondaryButton` prop: `dataLabel`
215
+ ```tsx
216
+ import {
217
+ BasePopupModelConfig,
218
+ createEventMap,
219
+ Model,
220
+ popupEventMap,
221
+ PopupEvents,
222
+ PopupModelConfig,
223
+ PopupState,
224
+ ToModelConfig,
225
+ useCloseOnEscape,
226
+ useEventMap,
227
+ useFocusTrap,
228
+ useInitialFocus,
229
+ usePopupModel,
230
+ useReturnFocus,
231
+ } from '@workday/canvas-kit-react';
159
232
 
160
- ### Button Mapping
233
+ type MyModalState = PopupState & {
234
+ showOverlay: boolean;
235
+ };
161
236
 
162
- Below is a mapping of V6 `IconButton` variants to their respective V7 buttons and variants. Further
163
- below is a description of how to manually migrate from unsupported V6 variants. | IconButton variant
164
- | Button Type | | ------------------ | ------------------------------------ | | `circle` |
165
- TertiaryButton | | `circleFilled` | SecondaryButton | | `inverse` | TertiButton with variant inverse
166
- | | `inverseFilled` | SecondaryButton with variant inverse | | `plain` | Not Supporting | | `square`
167
- | Not Supporting | | `squareFilled` | Not Supporting |
237
+ type MyModalEvents = PopupEvents;
168
238
 
169
- ### Remove `IconButton` `plain`, `square`, and `squareFilled` Variants
239
+ const myModalEventMap = createEventMap<MyModalEvents>()({
240
+ guards: {
241
+ ...popupEventMap.guards,
242
+ },
243
+ callbacks: {
244
+ ...popupEventMap.callbacks,
245
+ },
246
+ });
170
247
 
171
- As part of simplifying our variants and cleaning up the API, we've removed the variants `square`,
172
- `squareFilled` and `plain`. We've also removed the prop `toggled`.
248
+ type MyBaseModalConfig = BasePopupModelConfig & {
249
+ showOverlay?: boolean;
250
+ };
173
251
 
174
- Plain, Square, or Square-Filled Icon Buttons should either transition to the new icon only Primary,
175
- Secondary, and Tertiary button variants, the Toolbar Icon Button, or the Segmented Control component
252
+ type MyModalModel = Model<MyModalState, MyModalEvents>;
176
253
 
177
- If you would still like to have a squared icon, you can use
178
- [ToolbarIconButton](https://workday.github.io/canvas-kit/?path=/docs/components-buttons-button-react-toolbar--toolbar-icon-button)
179
- which also has the `toggled`prop.
254
+ type MyConfig = MyBaseConfig &
255
+ Partial<ToModelConfig<MyModalState, MyModalEvents, typeof myModalEventMap>>;
180
256
 
181
- If this button doesn't fit your specific use case, we've introduced a low level
182
- [`BaseButton` component](#basebutton-component). This component allows you to modify the colors,
183
- props, and size of the button. For an example of this being used, you can reference our
184
- [PageButton component](https://github.com/Workday/canvas-kit/blob/master/modules/react/pagination/lib/Pagination/PageButton.tsx).
257
+ export const useMyModalModel = (config: MyConfig = {}): MyModalModel => {
258
+ const [showOverlay] = React.useState(config.showOverlay ?? true);
185
259
 
186
- ### Rendering an icon button
260
+ const model = usePopupModel({
261
+ ...config,
262
+ // hook up to a redux store
263
+ onShow(...params) {
264
+ dispatch(setIsModalOpen(true));
265
+ config?.onShow?.(...params);
266
+ },
267
+ onHide(...params) {
268
+ dispatch(setIsModalOpen(false));
269
+ config?.onShow?.(...params);
270
+ },
271
+ });
187
272
 
188
- In order to render a icon button, omit any `children` and pass the button an `icon` prop.
273
+ useInitialFocus(model);
274
+ useReturnFocus(model);
275
+ useFocusTrap(model);
276
+ useCloseOnEscape(model);
189
277
 
190
- Example
278
+ const state = {
279
+ ...model.state,
280
+ showOverlay,
281
+ };
191
282
 
192
- v6
283
+ const events = useEventMap(myEventMap, state, config, {
284
+ ...model.events,
285
+ });
193
286
 
194
- ```tsx
195
- <IconButton variant="circleFilled" icon={plusIcon} />
287
+ return {state, events};
288
+ };
196
289
  ```
197
290
 
198
- v7
291
+ ##### v7
199
292
 
200
- ```tsx
201
- <SecondaryButton icon={plusIcon} />
202
- ```
293
+ ```ts
294
+ import {
295
+ useCloseOnEscape,
296
+ useEventMap,
297
+ useFocusTrap,
298
+ useInitialFocus,
299
+ usePopupModel,
300
+ useReturnFocus,
301
+ } from '@workday/canvas-kit-react';
203
302
 
204
- You can now render what use to be an `IconButton` using our main buttons.
303
+ const useMyModalModel = createModelHook({
304
+ defaultConfig: {
305
+ ...usePopupModel.defaultConfig,
306
+ showOverlay: true,
307
+ },
308
+ requiredConfig: usePopupModel.requiredConfig,
309
+ contextOverride: usePopupModel.Context, // needed to make sure this model uses the same context as the popup model, otherwise it will create a new one
310
+ })(config => {
311
+ // `mergeConfig` takes care of the manual merging we were doing earlier
312
+ const model = usePopupModel(
313
+ usePopupModel.mergeConfig(config, {
314
+ // hook up to a redux store
315
+ onShow() {
316
+ dispatch(setIsModalOpen(true));
317
+ },
318
+ onHide() {
319
+ dispatch(setIsModalOpen(false));
320
+ },
321
+ })
322
+ );
205
323
 
206
- ```tsx
207
- <PrimaryButton icon={plusIcon} />
208
- <SecondaryButton icon={plusIcon} />
209
- <TertiaryButton icon={plusIcon} />
210
- <PrimaryButton variant='inverse' icon={plusIcon} />
211
- <SecondaryButton variant='inverse' icon={plusIcon} />
212
- <TertiaryButton variant='inverse' icon={plusIcon} />
324
+ useInitialFocus(model);
325
+ useReturnFocus(model);
326
+ useFocusTrap(model);
327
+ useCloseOnEscape(model);
328
+
329
+ const state = {
330
+ ...model.state,
331
+ showOverlay,
332
+ };
333
+
334
+ return {...model, state};
335
+ });
213
336
  ```
214
337
 
215
- ### Button sizes
338
+ We've eliminated the cumbersome type boilerplate and type imports. The code is more focused on your
339
+ unique logic and less on boilerplate.
340
+
341
+ Given the complex nature of this code, this change is **not** handled by the codemod.
342
+
343
+ ## Tokens
216
344
 
217
- Each button now supports sizes: `extraSmall`, `small`, `medium` and `large` with `medium` being the
218
- default size.
345
+ ### Depth
346
+
347
+ **Changes:**
348
+
349
+ - Removed `inset` depth
350
+ - Added new depth values: `none` (to remove the default depth from a component), `5` and `6`
351
+ - Updated all depth values: depth now adds only `box-shadow` with two shadows and no border
352
+
353
+ We've also changed the default depth for the following components:
354
+
355
+ - Breadcrumbs (Dropdown Menu): Depth 2 → Depth 3
356
+ - Card: Depth 2 → Depth 1
357
+ - Color Picker (Palette): Depth 2 → Depth 5
358
+ - Combobox: Depth 1 → Depth 3
359
+ - Dialog: Depth 2 → Depth 5
360
+ - Menu: Depth 2 → Depth 3
361
+ - Modal: Depth 2 → Depth 6
362
+ - Popup: Depth 2 → Depth 5
363
+ - Side Panel (Preview, alternate variant): Depth 3 → Depth 5
364
+ - Toast: Depth 2 → Depth 5
365
+
366
+ ## Components
367
+
368
+ ### Component Deprecations
369
+
370
+ #### Deprecation Types
371
+
372
+ There are two types of deprecations: soft and hard.
373
+
374
+ ##### Soft Deprecation
375
+
376
+ A soft-deprecated component is still available with its full functionality, but it will have been
377
+ renamed with a prefix to indicate its soft-deprecated status. It will also include a console warning
378
+ announcing its deprecation. This warning will only be triggered on the component's initial render.
379
+
380
+ Soft-deprecated types and utilities will also be renamed but generally will not trigger a console
381
+ warning.
382
+
383
+ ##### Hard Deprecation
384
+
385
+ A hard-deprecated component or package is no longer available. You will need to follow the method
386
+ prescribed in our migration guide to update your application. Please
387
+ [reach out](https://github.com/Workday/canvas-kit/issues/new?labels=bug&template=bug.md) to our team
388
+ directly if you need additional help.
389
+
390
+ #### Cookie Banner
391
+
392
+ We are [hard-deprecating](#hard-deprecation) `CookieBanner`. Please reference this
393
+ [example](https://workday.github.io/canvas-kit/?path=/story/examples-cookiebanner-react--basic) to
394
+ migrate away from `CookieBanner`.
395
+
396
+ #### Page Header
397
+
398
+ We are [hard-deprecating](#hard-deprecation) `PageHeader`. Please reference this
399
+ [example](https://workday.github.io/canvas-kit/?path=/story/examples-pageheader-react--basic) to
400
+ migrate away from `PageHeader`.
401
+
402
+ #### Header / Global Header
403
+
404
+ We are [hard-deprecating](#hard-deprecation) `Header`. Please reference this
405
+ [example](https://workday.github.io/canvas-kit/?path=/story/examples-globalheader-react--basic) to
406
+ migrate away from `Header`.
407
+
408
+ ---
409
+
410
+ ### Component Promotions
411
+
412
+ We've [promoted](https://github.com/Workday/canvas-kit/issues/1395) the following components in v7:
413
+
414
+ - `Box` from `@workday/canvas-kit-labs/common` to `@workday/canvas-kit-react/layout`
415
+ - `Flex` from `@workday/canvas-kit-labs/layout` to `@workday/canvas-kit-react/layout`
416
+ - `Stack` from `@workday/canvas-kit-labs/layout` to `@workday/canvas-kit-react/layout`
219
417
 
220
418
  ```tsx
221
- <PrimaryButton icon={plusIcon} size='extraSmall' />
222
- <PrimaryButton icon={plusIcon} size='small' />
223
- <PrimaryButton icon={plusIcon} size='medium' /> // default
224
- <PrimaryButton icon={plusIcon} size='large' />
419
+ // v6
420
+ import {Box} from '@workday/canvas-kit-labs-react/common';
421
+
422
+ // v7
423
+ import {Box} from '@workday/canvas-kit-react/layout';
225
424
  ```
226
425
 
227
- ### Button Icon position
426
+ 🤖 The codemod will update imports for these promoted components.
427
+
428
+ The APIs for these promoted components remain unchanged.
429
+
430
+ ---
431
+
432
+ ### Action Bar
433
+
434
+ We've updated `ActionBar` to use the
435
+ [createComponent](/getting-started/for-developers/resources/creating-compound-components/#disclosurecontent-component)
436
+ utility from our
437
+ [common](https://github.com/Workday/canvas-kit/blob/ff77c5bd83e41c3ab2b9c55e41a8b7c1fde33a1b/modules/react/common/lib/utils/components.ts#L167)
438
+ module; it now supports [ref forwarding](https://reactjs.org/docs/forwarding-refs.html) and using
439
+ the `as` prop to change the rendered element.
440
+
441
+ We've removed the `fixed` prop from `ActionBar`. It now uses the `position` prop (defaults to
442
+ `fixed`) to set the container position.
443
+
444
+ 🤖 The codemod will remove uses of the `fixed` prop from `ActionBar`.
228
445
 
229
- The prop `iconPosition` which is used to determine which side an icon should be when rendered with
230
- some text, has been changed. The default is `start`
446
+ ---
231
447
 
232
- v6
448
+ ### Banner
449
+
450
+ Banner is now a [compound component](/getting-started/for-developers/resources/compound-components/)
451
+ composed of `Banner.Icon`, `Banner.Label`, and `Banner.ActionText`. This allows direct access to the
452
+ icon, label, and text elements.
233
453
 
234
454
  ```tsx
235
- iconPosition: 'left' | 'right';
455
+ // v6
456
+ <Banner label="3 Warnings" actionText="Show Details" variant={Banner.Variant.Sticky} error={Banner.ErrorType.Error} />
457
+
458
+ // v7
459
+ <Banner isSticky={true} hasError={true}>
460
+ <Banner.Icon />
461
+ <Banner.Label>3 Warnings</Banner.Label>
462
+ <Banner.ActionText>Show Details</Banner.ActionText>
463
+ </Banner>
236
464
  ```
237
465
 
238
- v7
466
+ 🤖 The codemod will rewrite your JSX to match the new API.
467
+
468
+ Like all compound components, `Banner` is written using the
469
+ [createComponent](/getting-started/for-developers/resources/creating-compound-components/#disclosurecontent-component)
470
+ utility from our
471
+ [common](https://github.com/Workday/canvas-kit/blob/ff77c5bd83e41c3ab2b9c55e41a8b7c1fde33a1b/modules/react/common/lib/utils/components.ts#L167)
472
+ module; it supports [ref forwarding](https://reactjs.org/docs/forwarding-refs.html) and using the
473
+ `as` prop to change the rendered element.
474
+
475
+ The `variant` prop (which previously accepted `Banner.Variant.Full` or `Banner.Variant.Sticky`) has
476
+ been converted to the boolean `isSticky` prop on the container `Banner` component.
477
+
478
+ Similarly, the `error` prop (which previously accepted `Banner.ErrorType.Alert` or
479
+ `Banner.ErrorType.Error`) has been converted to the boolean `hasError` prop on `Banner`. `Banner`
480
+ now uses the `useThemedPalette` hook which allows you to override its colors using the Canvas theme.
481
+
482
+ The icon is now customizable via the `icon` prop of `Banner.Icon`. Previously, the icon was limited
483
+ to `exclamationTriangleIcon` and `exclamationCircleIcon` for the alert and error states,
484
+ respectively.
485
+
486
+ ---
487
+
488
+ ### Button
489
+
490
+ #### Removal of Icon Button
491
+
492
+ To consolidate Button APIs, we've removed `IconButton` in favor of `SecondaryButton` and
493
+ `TertiaryButton`. The following table shows how `IconButton` variants in v6 map to their
494
+ corresponding buttons in v7.
495
+
496
+ | v6 `IconButton` variant | v7 button (and variant, if necessary) |
497
+ | -------------------------- | ---------------------------------------- |
498
+ | `circle` (default variant) | `TertiaryButton` |
499
+ | `circleFilled` | `SecondaryButton` |
500
+ | `inverse` | `TertiaryButton` with `inverse` variant |
501
+ | `inverseFilled` | `SecondaryButton` with `inverse` variant |
502
+ | `plain` | Unsupported |
503
+ | `square` | Unsupported |
504
+ | `squareFilled` | Unsupported |
505
+
506
+ > Note: See below for more information about how to manually migrate from
507
+ > [unsupported v6 variants](#unsupported-iconbutton-variants).
508
+
509
+ 🤖 Use the codemod to migrate your `IconButton` components in v6 to their corresponding buttons in
510
+ v7:
239
511
 
240
512
  ```tsx
241
- iconPosition: 'start' | 'end';
513
+ // v6
514
+ <IconButton icon={plusIcon} />
515
+ <IconButton variant="circleFilled" icon={plusIcon} />
516
+ <IconButton variant="inverse" icon={plusIcon} />
517
+ <IconButton variant="inverseFilled" icon={plusIcon} />
518
+
519
+ // v7
520
+ <TertiaryButton icon={plusIcon} />
521
+ <SecondaryButton icon={plusIcon} />
522
+ <TertiaryButton variant="inverse" icon={plusIcon} />
523
+ <SecondaryButton variant="inverse" icon={plusIcon} />
242
524
  ```
243
525
 
244
- _Note:_ The position of the icon should have no affect if you're rending an icon button.
526
+ ##### Unsupported IconButton Variants
527
+
528
+ In order to simplify our API, we no longer support the `plain`, `square`, and `squareFilled`
529
+ variants from `IconButton`.
530
+
531
+ `IconButton` components with `square`, `squareFilled` and `plain` variants should be updated to the
532
+ corresponding icon-only button versions (`PrimaryButton`, `SecondaryButton`, and `TertiaryButton`),
533
+ `ToolbarIconButton`, or `SegmentedControl`. You may use `ToolbarIconButton` if you would still like
534
+ to have a square icon that is toggleable.
245
535
 
246
- ### Removal of `dataLabel` Prop
536
+ These changes are **not** handled by the codemod.
247
537
 
248
- The `dataLabel` prop has been removed from our Buttons in v7 in order to simplify the API.
538
+ > If none of these options support your use case, we've introduced a low-level
539
+ > [`BaseButton`](#basebutton) component which allows you to modify the button's colors, size, and
540
+ > other props. For an example of it being used, reference our
541
+ > [`PageButton`](https://github.com/Workday/canvas-kit/blob/master/modules/react/pagination/lib/Pagination/PageButton.tsx)
542
+ > component.
249
543
 
250
- _Note:_ The codemod will not remove this prop since use of this prop varies. If you'd like to still
251
- have a similar effect, below is an example of how to achieve this.
544
+ ##### Removal of IconButtonProps
252
545
 
253
- v6
546
+ The `IconButtonProps` interface no longer exists now that `IconButton` has been removed.
547
+
548
+ This change is **not** handled by the codemod.
549
+
550
+ ##### Toggled
551
+
552
+ There is no equivalent to the `IconButton` `toggled` prop in `SecondaryButton` and `TertiaryButton`.
553
+ If you wish to render a button with a toggled state, consider using `ToolbarIconButton`.
554
+
555
+ This change is **not** handled by the codemod.
556
+
557
+ #### Icon Position
558
+
559
+ The `iconPosition` prop determines where an icon should be rendered relative to the button text.
560
+ We've updated the values from `left` and `right` to `start` and `end` respectively to better reflect
561
+ bidirectionality. The default value is `start`.
254
562
 
255
563
  ```tsx
256
- <PrimaryButton dataLabel="1:00">Time</PrimaryButton>
564
+ // v6
565
+ iconPosition: 'left' | 'right';
566
+
567
+ // v7
568
+ iconPosition: 'start' | 'end';
257
569
  ```
258
570
 
259
- v7
571
+ 🤖 The codemod will map `left` to `start` and `right` to `end` for all uses of `iconPosition`.
572
+
573
+ `iconPosition` will have no effect if you're rendering a button with only an icon and no text.
574
+
575
+ #### Removal of dataLabel
576
+
577
+ In order to simplify our API, we've removed the `dataLabel` prop from `PrimaryButton` and
578
+ `SecondaryButton`.
579
+
580
+ Given the varied use of `dataLabel`, this change is **not** handled by the codemod. Here's an
581
+ example of how to achieve a similar styling in v7:
260
582
 
261
583
  ```tsx
262
- <PrimaryButton>
263
- Time
264
- <span
265
- style={{
266
- position: 'relative', // Fixes an IE issue with text within button moving on click
267
- textOverflow: 'ellipsis',
268
- overflow: 'hidden',
269
- whiteSpace: 'nowrap',
270
- fontWeight: 400,
271
- marginLeft: 4,
272
- }}
273
- >
274
- 1:00
275
- </span>
276
- </PrimaryButton>
584
+ // v6
585
+ <PrimaryButton dataLabel="1:00">Time</PrimaryButton>;
586
+
587
+ // v7
588
+ import {space, type} from '@workday/canvas-kit-react/common';
589
+
590
+ const DataLabel = styled('span')({
591
+ position: 'relative', // Fixes an IE issue with text within button moving on click
592
+ overflow: 'hidden',
593
+ whiteSpace: 'nowrap',
594
+ fontWeight: type.properties.fontWeights.regular,
595
+ marginLeft: space.xxxs,
596
+ });
597
+
598
+ return (
599
+ <PrimaryButton>
600
+ Time
601
+ <DataLabel>1:00</DataLabel>
602
+ </PrimaryButton>
603
+ );
277
604
  ```
278
605
 
279
- ### BaseButton Component
606
+ #### BaseButton
280
607
 
281
- As part of the restructure of our Buttons, we've created a low level `BaseButton` component. This
608
+ > **Disclaimer**: We **strongly** advise consumers **not** to use `BaseButton` and to instead rely
609
+ > on `PrimaryButton`, `SecondaryButton` and `TertiaryButton` whenever possible. `BaseButton` is
610
+ > strictly provided as a last resort if no other option is available for your use case.
611
+
612
+ As part of our Button restructuring, we've created a low level `BaseButton` component. This
282
613
  component isn't intended to be used outside of Canvas Kit, but we do export it for very specific use
283
- cases which we'll outline below. The `BaseButton` is a styled `button` element which extends our
284
- style properties which allow us to customize a buttons `colors`, `padding`, `width` and other style
285
- properties.
614
+ cases. `BaseButton` is a styled `<button>` element which supports style properties such as `colors`,
615
+ `padding`, and `width` among many others.
286
616
 
287
- Basic example:
617
+ Here's an example:
288
618
 
289
619
  ```tsx
290
620
  import * as React from 'react';
@@ -335,116 +665,60 @@ export const BasicButton = ({children, ...elemProps}: BasicButtonProps) => {
335
665
  };
336
666
  ```
337
667
 
338
- **Note:** Under the hood, `BaseButton` uses our `Box` component which allows `BaseButton` to accept
339
- style properties. Because of the flexibility of this component, consumers can use this to create
340
- toggled buttons or a specific button that doesn't fall under the main use case you see in our design
341
- system.
342
-
343
- **Disclaimer** We strongly advise consumers not to use this component if possible and to rely on our
344
- `PrimaryButton`, `SecondaryButton` and `TertiaryButton` when possible.
345
-
346
- ## Segmented Control
347
-
348
- Segmented Control use to work when rendering `IconButton` as children. This has now moved to a
349
- compound component and removed the use of `IconButton`.
350
-
351
- ### Breaking Change
668
+ `BaseButton` uses our `Box` component under the hood, which allows it to accept a variety of style
669
+ properties. Because of the flexibility of this component, consumers can use it to create toggled
670
+ buttons or other buttons that aren't supported by our standard button components.
352
671
 
353
- `IconButton` is no longer a valid child of segmented control.
672
+ ---
354
673
 
355
- 🤖 The codemod will handle all these changes automatically:
674
+ ### Icon
356
675
 
357
- - `IconButton` becomes `SegmentedControl.Button`
676
+ We've updated `AccentIcon`, `AppletIcon`, `Graphic`, `Icon`, `Svg`, `SystemIcon`, and
677
+ `SystemIconCircle` to use the
678
+ [createComponent](/getting-started/for-developers/resources/creating-compound-components/#disclosurecontent-component)
679
+ utility from our
680
+ [common](https://github.com/Workday/canvas-kit/blob/ff77c5bd83e41c3ab2b9c55e41a8b7c1fde33a1b/modules/react/common/lib/utils/components.ts#L167)
681
+ module; they now support [ref forwarding](https://reactjs.org/docs/forwarding-refs.html) and using
682
+ the `as` prop to change the rendered element.
358
683
 
359
- v6
684
+ These components previously supported an `iconRef` prop. In v7, you'll need to use `ref` instead of
685
+ `iconRef`:
360
686
 
361
687
  ```tsx
362
- <SegmentedControl value={value} onChange={handleToggle}>
363
- <IconButton
364
- icon={listViewIcon}
365
- value="list-view"
366
- aria-label="List View"
367
- onClick={e => console.log('Existing IconButton onClick callback')}
368
- />
369
- <IconButton icon={worksheetsIcon} value="table-view" aria-label="Table View" disabled={true} />
370
- <IconButton icon={deviceTabletIcon} value="device-view" aria-label="Device View" />
371
- <IconButton icon={percentageIcon} value="percent-view" aria-label="Percent View" />
372
- </SegmentedControl>
373
- ```
374
-
375
- v7
688
+ // v6
689
+ <SystemIcon iconRef={ref} />;
376
690
 
377
- ```tsx
378
- <SegmentedControl value={value} onChange={handleToggle}>
379
- <SegmentedControl.Button
380
- icon={listViewIcon}
381
- value="list-view"
382
- aria-label="List View"
383
- onClick={e => console.log('Existing IconButton onClick callback')}
384
- />
385
- <SegmentedControl.Button
386
- icon={worksheetsIcon}
387
- value="table-view"
388
- aria-label="Table View"
389
- disabled={true}
390
- />
391
- <SegmentedControl.Button icon={deviceTabletIcon} value="device-view" aria-label="Device View" />
392
- <SegmentedControl.Button icon={percentageIcon} value="percent-view" aria-label="Percent View" />
393
- </SegmentedControl>
691
+ // v7
692
+ <SystemIcon ref={ref} />;
394
693
  ```
395
694
 
396
- ## Side Panel
695
+ 🤖 The codemod will update all Icon components that previously supported `iconRef` to use `ref`
696
+ instead.
397
697
 
398
- The `SidePanel` in our `preview` package has now been updated so that the toggle button has a
399
- tooltip built in. If you currently have a `Tooltip` component wrapping this element, you should
400
- remove it and provide the appropiate text to the button based on its state.
698
+ ---
401
699
 
402
- Two props where added to the `SidePanel.ToggleButton`:
700
+ ### Popper
403
701
 
404
- ```tsx
405
- /**
406
- * The tooltip text to expand the side panel
407
- * @default 'Expand'
408
- */
409
- tooltipTextExpand?: string;
410
- /**
411
- * The tooltip text to collapse the side panel
412
- * @default 'Collapse'
413
- */
414
- tooltipTextCollapse?: string;
415
- ```
416
-
417
- ## Icons
418
-
419
- We've updated our lower level icon components such as `AccentIcon`, `AppletIcon`, `Graphic`, `Icon`,
420
- `Svg`, `SystemIcon`, and `SystemIconCircle` to use our
421
- [createComponent](https://github.com/Workday/canvas-kit/blob/ff77c5bd83e41c3ab2b9c55e41a8b7c1fde33a1b/modules/react/common/lib/utils/components.ts#L167)
422
- which allows us to `forwardRef`.
423
-
424
- ### Breaking Change
425
-
426
- This is a breaking change since we've removed `iconRef`. You can now just pass a `ref` to the
427
- element.
428
-
429
- 🤖 The codemod will handle all these changes automatically:\
702
+ We've removed the `containerElement` prop from `Popper` because it's no longer needed with the
703
+ Fullscreen API.
430
704
 
431
- - `iconRef` becomes `ref`
705
+ ---
432
706
 
433
- ## Popup Cards
707
+ ### Popup
434
708
 
435
- `Popup.Card` (this includes `Modal.Card` and `Dialog.Card`) components are now a flexbox container.
436
- This was done to support overflowing content (by default, the `Popup.Body` component). The idea is
437
- the card is a vertical flexbox container and the `Popup.Heading`, `Popup.Body`, and any other
438
- children are flex items. The `Popup.Body` now has an `overflow-y: auto` on it to naturally allow the
439
- body content to overflow in a scroll container. This is a breaking change if your `Popup`, `Modal`,
440
- or `Dialog` doesn't work with a flexbox with `flex-direction: column`. In most cases, this shouldn't
441
- matter. If this change does cause your popup to display correctly, you may need to play around with
442
- flex item containers.
709
+ #### Popup.Card
443
710
 
444
- An example where this might break:
711
+ `Popup.Card` components (this includes `Modal.Card` and `Dialog.Card`) are now flexbox containers.
712
+ This was done to support overflowing content (by default, the `Popup.Body` component). The card is a
713
+ vertical flexbox container and `Popup.Heading`, `Popup.Body`, and any other children are flex items.
714
+ `Popup.Body` now has `overflow-y: auto` to naturally allow the body content to overflow in a scroll
715
+ container. This is a breaking change if your `Popup`, `Modal`, or `Dialog` doesn't work with a
716
+ flexbox with `flex-direction: column`. In most cases, this shouldn't matter. If this change does
717
+ cause your popup to display incorrectly, you may need to play around with flex item containers.
445
718
 
446
- A common Modal has a heading, body, and footer (Cancel/Submit buttons). If the Cancel and Submit
447
- buttons are direct children of the `Modal.Card` like the following:
719
+ Here's an example of where your current implementation might break. A common `Modal` has a heading,
720
+ body, and footer (Cancel/Submit buttons). If the Cancel and Submit buttons are direct children of
721
+ the `Modal.Card` like the following...
448
722
 
449
723
  ```tsx
450
724
  <Modal.Card>
@@ -455,11 +729,10 @@ buttons are direct children of the `Modal.Card` like the following:
455
729
  </Modal.Card>
456
730
  ```
457
731
 
458
- The buttons will become vertical flex items instead of the default which is displaying inline-block.
459
- Before, the buttons would layout next to each other horizontally. After, the buttons will stack
460
- vertically. To fix this, you'll have to add another element to be a flex item from the `Modal.Card`.
461
- Our examples use `HStack` to align the buttons. The following will render correctly after this
462
- change:
732
+ ...the buttons will become vertical flex items instead of the default which is displaying
733
+ inline-block. Before v7, the buttons would layout next to each other horizontally. In v7, the
734
+ buttons will stack vertically. To fix this, you'll need to add another element as a flex item in the
735
+ `Modal.Card`. The following example uses `HStack` to achieve the desired horizontal layout:
463
736
 
464
737
  ```tsx
465
738
  <Modal.Card>
@@ -472,41 +745,37 @@ change:
472
745
  </Modal.Card>
473
746
  ```
474
747
 
475
- If your code contains any hacks to make a `Modal` overflow, these hacks should now be removed.
748
+ If your code contains any hacks to make a `Modal` overflow, those hacks should now be removed.
476
749
  [This example shows how body content overflows](https://workday.github.io/canvas-kit/?path=/docs/components-popups-modal-react--body-overflow)
477
- (you may have to limit your browser height to see the overflow). Before you had to manually set the
478
- `max-height` of the `Modal.Body` element using calculations. These should be removed. The
750
+ (you may have to limit your browser height to see the overflow). Before v7, you had to manually set
751
+ the `max-height` of the `Modal.Body` element using calculations. These should now be removed. The
479
752
  `Popup.Card` now has a max height and the `Popup.Body` height is automatically calculated.
480
753
 
481
- ### Popup.Body
754
+ #### Popup.Body
482
755
 
483
- The `Popup.Body` is now an overflow container. This means 2 things:
756
+ `Popup.Body` is now an overflow container. This means two things:
484
757
 
485
758
  - `Popup.Body` will scroll if the contents are too big to fit in the page
486
759
  - `Popup.Body` will hide focus rings that render outside the overflow container
487
760
 
488
- Our examples contained some buttons inside the `Body` element and had focus rings cut off. The
489
- adjustment is to move the buttons outside the `Body` element. This is most likely the desired
490
- structure anyways since the buttons will not scroll with the overflowed `Body` content.
491
-
492
- Before:
761
+ Our examples contained buttons inside the `Body` element with their focus rings cut off. We fixed
762
+ this by moving the buttons outside the `Body` element. This is most likely the desired structure
763
+ anyway since the buttons will no longer scroll with overflowed `Body` content.
493
764
 
494
765
  ```tsx
766
+ // v6
495
767
  <Modal.Card>
496
768
  <Modal.Body>
497
769
  Body Contents
498
770
  <HStack spacing="s">
499
- {/*will scroll with the body*/}
771
+ {/* Will scroll with the body */}
500
772
  <Modal.CloseButton as={PrimaryButton}>Delete</Modal.CloseButton>
501
773
  <Modal.CloseButton>Cancel</Modal.CloseButton>
502
774
  </HStack>
503
775
  </Modal.Body>
504
776
  </Modal.Card>
505
- ```
506
777
 
507
- After:
508
-
509
- ```tsx
778
+ // v7
510
779
  <Modal.Card>
511
780
  <Modal.Body>Body Contents</Modal.Body>
512
781
  <HStack spacing="s">
@@ -516,301 +785,106 @@ After:
516
785
  </Modal.Card>
517
786
  ```
518
787
 
519
- ## Popper Props Update
520
-
521
- We removed the `containerElement` prop from Popper component because it's no longer needed with
522
- Fullscreen API.
523
-
524
- ## Component Promotions
525
-
526
- After some [assessment](https://github.com/Workday/canvas-kit/issues/1395) we've decided to promote
527
- the following components: `Flex`, `Stack`, `Box` and `Breadcumbs`
788
+ ---
528
789
 
529
- This promotion does not introduce any API changes, we've just changed moved the components to our
530
- main `react` package.
531
-
532
- **Changes:**
533
-
534
- - `Box` was promoted from `@workday/canvas-kit-labs/common` to `@workday/canvas-kit-react/layout`
535
- - `Flex` was promoted from `@workday/canvas-kit-labs/layout` to `@workday/canvas-kit-react/layout`
536
- - `Stack` was promoted from `@workday/canvas-kit-labs/layout` to `@workday/canvas-kit-react/layout`
537
-
538
- ## Model Changes
539
-
540
- ### Guards and Callbacks
541
-
542
- We changed the signature of model event guards and callbacks. In v6, the parameters were in an
543
- object. This has a less than ideal developer experience as intellisense isn't engaged immediately
544
- and we don't plan on adding any additional parameters to guard and callback functions. We've removed
545
- the object wrapper.
790
+ ### Segmented Control
546
791
 
547
- 🤖 The codemod handles these changes automatically.
792
+ `SegmentedControl` is now a
793
+ [compound component](/getting-started/for-developers/resources/compound-components/).
548
794
 
549
- Before:
795
+ Given the [removal of `IconButton`](#removal-of-icon-button) in v7, you'll now need to use
796
+ `SegmentedControl.Button` instead.
550
797
 
551
798
  ```tsx
552
- const model = useTabsModel({
553
- onSelect({data: {id}, prevState}) {
554
- console.log(id, prevState);
555
- },
556
- });
557
- ```
558
-
559
- After:
799
+ // v6
800
+ <SegmentedControl value={value} onChange={handleToggle}>
801
+ <IconButton
802
+ icon={listViewIcon}
803
+ value="list-view"
804
+ aria-label="List View"
805
+ onClick={e => console.log('Existing IconButton onClick callback')}
806
+ />
807
+ <IconButton icon={worksheetsIcon} value="table-view" aria-label="Table View" disabled={true} />
808
+ <IconButton icon={deviceTabletIcon} value="device-view" aria-label="Device View" />
809
+ <IconButton icon={percentageIcon} value="percent-view" aria-label="Percent View" />
810
+ </SegmentedControl>
560
811
 
561
- ```tsx
562
- const model = useTabsModel({
563
- onSelect({id}, prevState) {
564
- console.log(id, prevState);
565
- },
566
- });
812
+ // v7
813
+ <SegmentedControl value={value} onChange={handleToggle}>
814
+ <SegmentedControl.Button
815
+ icon={listViewIcon}
816
+ value="list-view"
817
+ aria-label="List View"
818
+ onClick={e => console.log('Existing IconButton onClick callback')}
819
+ />
820
+ <SegmentedControl.Button
821
+ icon={worksheetsIcon}
822
+ value="table-view"
823
+ aria-label="Table View"
824
+ disabled={true}
825
+ />
826
+ <SegmentedControl.Button icon={deviceTabletIcon} value="device-view" aria-label="Device View" />
827
+ <SegmentedControl.Button icon={percentageIcon} value="percent-view" aria-label="Percent View" />
828
+ </SegmentedControl>
567
829
  ```
568
830
 
569
- ### Model Implementation
570
-
571
- If you don't extend models, you can skip this section.
572
-
573
- In v6 we supported Typescript 3.8 which limited the way types could be inferred and defined. Canvas
574
- Kit v7 now requires Typescript 4.1 which introduced
575
- [Template Literal Types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html).
576
- This means that the guards and callbacks no longer need to be manually defined via an `eventMap`.
577
- Event maps were a stopgap, were manual, and prone to errors in defining them. Not all events had
578
- guards or callbacks there's no check other than manual review to ensure the existence of an event
579
- callback or guard. Template Literal Types allow us to properly type guards and callbacks without
580
- event maps. The previous types forced `data` to be an object. We've since dropped that restriction.
581
- You can still only pass a single argument to events. If you need additional information, use an
582
- object.
583
-
584
- This change also allowed us to remove a lot of boilerplate associated with models without
585
- sacrificing type safety. This change doesn't effect most use cases, but will effect those whole
586
- extended a model. We created a new utility function called `createModelHook` that helps set up
587
- types.
588
-
589
- Before:
590
-
591
- ```ts
592
- export type MyState = {
593
- value: string;
594
- };
595
-
596
- export type MyEvents = {
597
- updateValue(data: {value: string}): void; // enforced that `data` is an object even if we only need to pass a string
598
- };
599
-
600
- export type MyModel = Model<MyState, MyEvents>;
601
-
602
- export const myEventMap = createEventMap<MyEvents>()({
603
- guards: {
604
- shouldUpdateValue: 'updateValue', // easy to forget or make a mistake on guard name
605
- },
606
- callbacks: {
607
- onUpdateValue: 'updateValue',
608
- },
609
- });
610
-
611
- export type MyBaseConfig = {
612
- initialValue?: string;
613
- };
614
-
615
- export type MyConfig = MyBaseConfig & Partial<ToModelConfig<MyState, MyEvents, typeof myEventMap>>;
616
-
617
- const useMyModel = (config: MyConfig = {}): MyModel => {
618
- const [value, setValue] = React.useState(config.initialValue || '');
831
+ 🤖 The codemod will replace all `IconButton` children of `SegmentedControl` with
832
+ `SegmentedControl.Button`.
619
833
 
620
- const state = {value};
621
-
622
- // useEventMap is used to wrap the event object with guards and callbacks according to the event map
623
- const events = useEventMap(myEventMap, state, config, {
624
- updateValue(data) {
625
- setValue(data.value);
626
- },
627
- });
834
+ ---
628
835
 
629
- return {state, events};
630
- };
631
- ```
836
+ ### Side Panel
632
837
 
633
- After:
838
+ The `SidePanel` in our Preview package now has a tooltip built in to its toggle button. If you
839
+ currently have a `Tooltip` component wrapping this component, you should remove it. Instead, you'll
840
+ need to provide the appropriate tooltip text to the button based on its state using the following
841
+ new props added to `SidePanel.ToggleButton`:
634
842
 
635
843
  ```tsx
636
- const useMyModel = createModelHook({
637
- defaultConfig: {
638
- initialValue: '',
639
- },
640
- })(config => {
641
- const [value, setValue] = React.useState(config.initialValue); // default is already handled
642
-
643
- const state = {value};
644
-
645
- const events = {
646
- updateValue(value: string) {
647
- // doesn't need to be an object anymore
648
- setValue(value);
649
- },
650
- };
651
-
652
- return {state, events};
653
- });
844
+ /**
845
+ * The tooltip text to expand the side panel
846
+ * @default 'Expand'
847
+ */
848
+ tooltipTextExpand?: string;
849
+ /**
850
+ * The tooltip text to collapse the side panel
851
+ * @default 'Collapse'
852
+ */
853
+ tooltipTextCollapse?: string;
654
854
  ```
655
855
 
656
- Notice the large reduction in Typescript type boilerplate. In this example, the only place that
657
- Typescript syntax exists is in the `updateValue` function definition. This allows better collocating
658
- of types and values. Also notice that `useEventMap` doesn't need to be used anymore. The
659
- `createModelHook` will automatically wrap the `events` returned to call guards and callbacks when
660
- appropriate. Today this is done via creating a new events object. Once we drop IE11 support, this
661
- can be done via a proxy instead. The `createModelHook` handles all type inference so we don't have
662
- to explicitly type everything. Also `createModelHook` attaches React Context directly to the hook
663
- along with `defaultConfig` and `requiredConfig` for model extension.
664
-
665
- If you extended a model, you'll notice all those types are no longer being exported. You'll have to
666
- use this new utility function. Here's an example we found in the wild:
667
-
668
- ```tsx
669
- import {
670
- BasePopupModelConfig,
671
- createEventMap,
672
- Model,
673
- popupEventMap,
674
- PopupEvents,
675
- PopupModelConfig,
676
- PopupState,
677
- ToModelConfig,
678
- useCloseOnEscape,
679
- useEventMap,
680
- useFocusTrap,
681
- useInitialFocus,
682
- usePopupModel,
683
- useReturnFocus,
684
- } from '@workday/canvas-kit-react';
685
-
686
- type MyModalState = PopupState & {
687
- showOverlay: boolean;
688
- };
689
-
690
- type MyModalEvents = PopupEvents;
691
-
692
- const myModalEventMap = createEventMap<MyModalEvents>()({
693
- guards: {
694
- ...popupEventMap.guards,
695
- },
696
- callbacks: {
697
- ...popupEventMap.callbacks,
698
- },
699
- });
700
-
701
- type MyBaseModalConfig = BasePopupModelConfig & {
702
- showOverlay?: boolean;
703
- };
704
-
705
- type MyModalModel = Model<MyModalState, MyModalEvents>;
706
-
707
- type MyConfig = MyBaseConfig &
708
- Partial<ToModelConfig<MyModalState, MyModalEvents, typeof myModalEventMap>>;
709
-
710
- export const useMyModalModel = (config: MyConfig = {}): MyModalModel => {
711
- const [showOverlay] = React.useState(config.showOverlay ?? true);
712
-
713
- const model = usePopupModel({
714
- ...config,
715
- // hook up to a redux store
716
- onShow(...params) {
717
- dispatch(setIsModalOpen(true));
718
- config?.onShow?.(...params);
719
- },
720
- onHide(...params) {
721
- dispatch(setIsModalOpen(false));
722
- config?.onShow?.(...params);
723
- },
724
- });
856
+ ---
725
857
 
726
- useInitialFocus(model);
727
- useReturnFocus(model);
728
- useFocusTrap(model);
729
- useCloseOnEscape(model);
858
+ ### Status Indicator
730
859
 
731
- const state = {
732
- ...model.state,
733
- showOverlay,
734
- };
860
+ Status Indicators currently truncate when they reach their max width of `150px`. After receiving
861
+ requests to increase this value, we've increased it by 33% to `200px`.
735
862
 
736
- const events = useEventMap(myEventMap, state, config, {
737
- ...model.events,
738
- });
863
+ We've also added a `maxWidth` prop to further configure this value if necessary. While this
864
+ increases flexibility, please keep in mind that status text should be short, direct, and preferably
865
+ a single word.
739
866
 
740
- return {state, events};
741
- };
867
+ ```tsx
868
+ <StatusIndicator label="Slightly Longer Status" type={StatusIndicator.Type.Gray} maxWidth={250} />
742
869
  ```
743
870
 
744
- After:
745
-
746
- ```ts
747
- import {
748
- useCloseOnEscape,
749
- useEventMap,
750
- useFocusTrap,
751
- useInitialFocus,
752
- usePopupModel,
753
- useReturnFocus,
754
- } from '@workday/canvas-kit-react';
755
-
756
- const useMyModalModel = createModelHook({
757
- defaultConfig: {
758
- ...usePopupModel.defaultConfig,
759
- showOverlay: true,
760
- },
761
- requiredConfig: usePopupModel.requiredConfig,
762
- contextOverride: usePopupModel.Context, // needed to make sure this model uses the same context as the popup model, otherwise it will create a new one
763
- })(config => {
764
- // `mergeConfig` takes care of the manual merging we were doing earlier
765
- const model = usePopupModel(
766
- usePopupModel.mergeConfig(config, {
767
- // hook up to a redux store
768
- onShow() {
769
- dispatch(setIsModalOpen(true));
770
- },
771
- onHide() {
772
- dispatch(setIsModalOpen(false));
773
- },
774
- })
775
- );
871
+ ---
776
872
 
777
- useInitialFocus(model);
778
- useReturnFocus(model);
779
- useFocusTrap(model);
780
- useCloseOnEscape(model);
873
+ ### Tabs
781
874
 
782
- const state = {
783
- ...model.state,
784
- showOverlay,
785
- };
875
+ To avoid interference with the HTML `name` attribute, we're now using `data-id` instead of `name`
876
+ for `Tabs.Item`, `Tabs.Panel`, and `Tabs.Menu.Item`.
786
877
 
787
- return {...model, state};
788
- });
878
+ ```tsx
879
+ // v6
880
+ <Tabs.Item name="tabs-item">...</Tabs.Item>
881
+ <Tabs.Panel name="tabs-panel">...</Tabs.Panel>
882
+ <Tabs.Menu.Item name="tabs-menu-item">...</Tabs.Menu.Item>
883
+
884
+ // v7
885
+ <Tabs.Item data-id="tabs-item">...</TabsItem>
886
+ <Tabs.Panel data-id="tabs-panel">...</Tabs.Panel>
887
+ <Tabs.Menu.Item data-id="tabs-menu-item">...</Tabs.Menu.Item>
789
888
  ```
790
889
 
791
- All the cumbersome type boilerplate went away. Also all the type imports went away. The code is more
792
- focused on your unique logic and less on boilerplate. Unfortunately, this change doesn't have a
793
- codemod. While possible, this code isn't very common and the codemod would be very complex.
794
-
795
- ## Token Updates
796
-
797
- ### Depth Tokens
798
-
799
- **Changes:**
800
-
801
- - Depth `inset` was removed from token list.
802
- - Added new depth: `none` (to remove default depth from component), `5` and `6`.
803
- - Updated all depth values: now depth adds only `box-shadow` with 2 shadows and no border.
804
-
805
- Also we changed default depth for the following components:
806
-
807
- - Card: Depth 2 → Depth 1
808
- - Breadcrumbs Dropdown Menu: Depth 2 → Depth 3
809
- - Menu: Depth 2 → Depth 3
810
- - Combobox: Depth 1 → Depth 3
811
- - Popup: Depth 2 → Depth 5
812
- - Dialog: Depth 2 → Depth 5
813
- - Color Picker Palette: Depth 2 → Depth 5
814
- - Toast: Depth 2 → Depth 5
815
- - Modal: Depth 2 → Depth 6
816
- - Preview Side Panel (alternate variant): Depth 3 → Depth 6
890
+ 🤖 The codemod will handle these changes for you automatically.