@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.
- package/dist/mdx/7.0-MIGRATION-GUIDE.mdx +635 -561
- package/dist/mdx/COMPOUND_COMPONENTS.mdx +2 -2
- package/dist/mdx/preview-react/pill/Pill.mdx +241 -0
- package/dist/mdx/preview-react/pill/examples/Basic.tsx +18 -0
- package/dist/mdx/preview-react/pill/examples/WithAvatar.tsx +21 -0
- package/dist/mdx/preview-react/pill/examples/WithCount.tsx +9 -0
- package/dist/mdx/preview-react/pill/examples/WithList.tsx +31 -0
- package/dist/mdx/preview-react/pill/examples/WithReadOnly.tsx +15 -0
- package/dist/mdx/preview-react/pill/examples/WithRemovable.tsx +25 -0
- package/dist/mdx/preview-react/pill/examples/test-avatar.png +0 -0
- package/dist/mdx/react/tabs/Tabs.mdx +7 -6
- package/dist/mdx/react/tabs/examples/DynamicTabs.tsx +3 -7
- package/dist/mdx/react/tabs/examples/OverflowTabs.tsx +3 -7
- package/dist/mdx/react/tabs/examples/SinglePanel.tsx +3 -3
- package/package.json +3 -3
|
@@ -1,31 +1,34 @@
|
|
|
1
1
|
# Canvas Kit 7.0 Migration Guide
|
|
2
2
|
|
|
3
|
-
|
|
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
|
|
5
|
+
any questions.
|
|
6
6
|
|
|
7
7
|
- [Codemod](#codemod)
|
|
8
|
-
- [
|
|
9
|
-
- [
|
|
10
|
-
- [
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
13
|
-
- [
|
|
14
|
-
- [
|
|
15
|
-
- [
|
|
16
|
-
- [
|
|
17
|
-
- [
|
|
18
|
-
- [
|
|
19
|
-
- [
|
|
20
|
-
- [
|
|
21
|
-
- [
|
|
22
|
-
- [
|
|
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
|
|
28
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
##
|
|
52
|
+
## General Changes
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
### Dependency Upgrades
|
|
53
55
|
|
|
54
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
64
|
+
To use v7, you'll need to upgrade the following dependencies:
|
|
64
65
|
|
|
65
|
-
|
|
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
|
-
|
|
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
|
-
|
|
79
|
+
Please note that you may also need to update any side effect dependencies or linting packages with
|
|
80
|
+
this update.
|
|
70
81
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
76
|
-
warning.
|
|
87
|
+
---
|
|
77
88
|
|
|
78
|
-
|
|
89
|
+
### Model Changes
|
|
79
90
|
|
|
80
|
-
|
|
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
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
98
|
+
```tsx
|
|
99
|
+
// v6
|
|
100
|
+
const model = useTabsModel({
|
|
101
|
+
onSelect({data: {id}, prevState}) {
|
|
102
|
+
console.log(id, prevState);
|
|
103
|
+
},
|
|
104
|
+
});
|
|
89
105
|
|
|
90
|
-
|
|
106
|
+
// v7
|
|
107
|
+
const model = useTabsModel({
|
|
108
|
+
onSelect({id}, prevState) {
|
|
109
|
+
console.log(id, prevState);
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
```
|
|
91
113
|
|
|
92
|
-
|
|
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
|
-
|
|
116
|
+
#### Model Implementation
|
|
97
117
|
|
|
98
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
134
|
+
##### v6
|
|
107
135
|
|
|
108
|
-
|
|
136
|
+
```ts
|
|
137
|
+
export type MyState = {
|
|
138
|
+
value: string;
|
|
139
|
+
};
|
|
109
140
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
145
|
+
export type MyModel = Model<MyState, MyEvents>;
|
|
116
146
|
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
156
|
+
export type MyBaseConfig = {
|
|
157
|
+
initialValue?: string;
|
|
158
|
+
};
|
|
123
159
|
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
178
|
+
##### v7
|
|
129
179
|
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
188
|
+
const state = {value};
|
|
134
189
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
190
|
+
const events = {
|
|
191
|
+
updateValue(value: string) {
|
|
192
|
+
// doesn't need to be an object anymore
|
|
193
|
+
setValue(value);
|
|
194
|
+
},
|
|
195
|
+
};
|
|
138
196
|
|
|
139
|
-
|
|
197
|
+
return {state, events};
|
|
198
|
+
});
|
|
199
|
+
```
|
|
140
200
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
|
|
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
|
-
|
|
213
|
+
##### v6
|
|
154
214
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
233
|
+
type MyModalState = PopupState & {
|
|
234
|
+
showOverlay: boolean;
|
|
235
|
+
};
|
|
161
236
|
|
|
162
|
-
|
|
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
|
-
|
|
239
|
+
const myModalEventMap = createEventMap<MyModalEvents>()({
|
|
240
|
+
guards: {
|
|
241
|
+
...popupEventMap.guards,
|
|
242
|
+
},
|
|
243
|
+
callbacks: {
|
|
244
|
+
...popupEventMap.callbacks,
|
|
245
|
+
},
|
|
246
|
+
});
|
|
170
247
|
|
|
171
|
-
|
|
172
|
-
|
|
248
|
+
type MyBaseModalConfig = BasePopupModelConfig & {
|
|
249
|
+
showOverlay?: boolean;
|
|
250
|
+
};
|
|
173
251
|
|
|
174
|
-
|
|
175
|
-
Secondary, and Tertiary button variants, the Toolbar Icon Button, or the Segmented Control component
|
|
252
|
+
type MyModalModel = Model<MyModalState, MyModalEvents>;
|
|
176
253
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
which also has the `toggled`prop.
|
|
254
|
+
type MyConfig = MyBaseConfig &
|
|
255
|
+
Partial<ToModelConfig<MyModalState, MyModalEvents, typeof myModalEventMap>>;
|
|
180
256
|
|
|
181
|
-
|
|
182
|
-
[
|
|
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
|
-
|
|
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
|
-
|
|
273
|
+
useInitialFocus(model);
|
|
274
|
+
useReturnFocus(model);
|
|
275
|
+
useFocusTrap(model);
|
|
276
|
+
useCloseOnEscape(model);
|
|
189
277
|
|
|
190
|
-
|
|
278
|
+
const state = {
|
|
279
|
+
...model.state,
|
|
280
|
+
showOverlay,
|
|
281
|
+
};
|
|
191
282
|
|
|
192
|
-
|
|
283
|
+
const events = useEventMap(myEventMap, state, config, {
|
|
284
|
+
...model.events,
|
|
285
|
+
});
|
|
193
286
|
|
|
194
|
-
|
|
195
|
-
|
|
287
|
+
return {state, events};
|
|
288
|
+
};
|
|
196
289
|
```
|
|
197
290
|
|
|
198
|
-
v7
|
|
291
|
+
##### v7
|
|
199
292
|
|
|
200
|
-
```
|
|
201
|
-
|
|
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
|
-
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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
|
-
|
|
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
|
-
|
|
218
|
-
|
|
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
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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
|
-
|
|
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
|
-
|
|
230
|
-
some text, has been changed. The default is `start`
|
|
446
|
+
---
|
|
231
447
|
|
|
232
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
536
|
+
These changes are **not** handled by the codemod.
|
|
247
537
|
|
|
248
|
-
|
|
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
|
-
|
|
251
|
-
have a similar effect, below is an example of how to achieve this.
|
|
544
|
+
##### Removal of IconButtonProps
|
|
252
545
|
|
|
253
|
-
|
|
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
|
-
|
|
564
|
+
// v6
|
|
565
|
+
iconPosition: 'left' | 'right';
|
|
566
|
+
|
|
567
|
+
// v7
|
|
568
|
+
iconPosition: 'start' | 'end';
|
|
257
569
|
```
|
|
258
570
|
|
|
259
|
-
|
|
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
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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
|
-
|
|
606
|
+
#### BaseButton
|
|
280
607
|
|
|
281
|
-
|
|
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
|
|
284
|
-
|
|
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
|
-
|
|
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
|
-
|
|
339
|
-
|
|
340
|
-
|
|
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
|
-
|
|
672
|
+
---
|
|
354
673
|
|
|
355
|
-
|
|
674
|
+
### Icon
|
|
356
675
|
|
|
357
|
-
|
|
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
|
-
|
|
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
|
-
|
|
363
|
-
|
|
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
|
-
|
|
378
|
-
<
|
|
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
|
-
|
|
695
|
+
🤖 The codemod will update all Icon components that previously supported `iconRef` to use `ref`
|
|
696
|
+
instead.
|
|
397
697
|
|
|
398
|
-
|
|
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
|
-
|
|
700
|
+
### Popper
|
|
403
701
|
|
|
404
|
-
|
|
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
|
-
|
|
705
|
+
---
|
|
432
706
|
|
|
433
|
-
|
|
707
|
+
### Popup
|
|
434
708
|
|
|
435
|
-
|
|
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
|
-
|
|
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
|
-
|
|
447
|
-
|
|
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
|
-
|
|
459
|
-
Before, the buttons would layout next to each other horizontally.
|
|
460
|
-
vertically. To fix this, you'll
|
|
461
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
754
|
+
#### Popup.Body
|
|
482
755
|
|
|
483
|
-
|
|
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
|
|
489
|
-
|
|
490
|
-
|
|
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
|
-
{/*
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
792
|
+
`SegmentedControl` is now a
|
|
793
|
+
[compound component](/getting-started/for-developers/resources/compound-components/).
|
|
548
794
|
|
|
549
|
-
|
|
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
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
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
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
630
|
-
};
|
|
631
|
-
```
|
|
836
|
+
### Side Panel
|
|
632
837
|
|
|
633
|
-
|
|
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
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
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
|
-
|
|
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
|
-
|
|
727
|
-
useReturnFocus(model);
|
|
728
|
-
useFocusTrap(model);
|
|
729
|
-
useCloseOnEscape(model);
|
|
858
|
+
### Status Indicator
|
|
730
859
|
|
|
731
|
-
|
|
732
|
-
|
|
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
|
-
|
|
737
|
-
|
|
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
|
-
|
|
741
|
-
}
|
|
867
|
+
```tsx
|
|
868
|
+
<StatusIndicator label="Slightly Longer Status" type={StatusIndicator.Type.Gray} maxWidth={250} />
|
|
742
869
|
```
|
|
743
870
|
|
|
744
|
-
|
|
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
|
-
|
|
778
|
-
useReturnFocus(model);
|
|
779
|
-
useFocusTrap(model);
|
|
780
|
-
useCloseOnEscape(model);
|
|
873
|
+
### Tabs
|
|
781
874
|
|
|
782
|
-
|
|
783
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|