@workday/canvas-kit-docs 7.0.0-alpha.94-next.20 → 7.0.0-alpha.97-next.23

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