@workday/canvas-kit-docs 5.3.0-next.11 → 5.3.0-next.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/LICENSE +1 -1
  2. package/dist/commonjs/lib/specs.js +263 -33
  3. package/dist/es6/lib/specs.js +263 -33
  4. package/dist/mdx/6.0-MIGRATION-GUIDE.mdx +259 -1
  5. package/dist/mdx/COMPOUND_COMPONENTS.mdx +31 -30
  6. package/dist/mdx/preview-react/breadcrumbs/Breadcrumbs.mdx +1 -1
  7. package/dist/mdx/preview-react/form-field/FormField.mdx +27 -0
  8. package/dist/mdx/preview-react/form-field/examples/Custom.tsx +57 -0
  9. package/dist/mdx/preview-react/menu/examples/Icons.tsx +1 -1
  10. package/dist/mdx/preview-react/menu/examples/ManyItems.tsx +1 -1
  11. package/dist/mdx/preview-react/text-area/TextArea.mdx +122 -0
  12. package/dist/mdx/preview-react/text-area/examples/Alert.tsx +31 -0
  13. package/dist/mdx/preview-react/text-area/examples/Basic.tsx +17 -0
  14. package/dist/mdx/preview-react/text-area/examples/Disabled.tsx +17 -0
  15. package/dist/mdx/preview-react/text-area/examples/Error.tsx +40 -0
  16. package/dist/mdx/preview-react/text-area/examples/Grow.tsx +17 -0
  17. package/dist/mdx/preview-react/text-area/examples/HiddenLabel.tsx +20 -0
  18. package/dist/mdx/preview-react/text-area/examples/LabelPositionHorizontal.tsx +17 -0
  19. package/dist/mdx/preview-react/text-area/examples/LabelPositionVertical.tsx +17 -0
  20. package/dist/mdx/preview-react/text-area/examples/Placeholder.tsx +21 -0
  21. package/dist/mdx/preview-react/text-area/examples/RefForwarding.tsx +28 -0
  22. package/dist/mdx/preview-react/text-area/examples/Required.tsx +17 -0
  23. package/dist/mdx/preview-react/text-area/examples/ResizeConstraints.tsx +22 -0
  24. package/dist/mdx/{labs-react → preview-react}/text-input/TextInput.mdx +40 -18
  25. package/dist/mdx/preview-react/text-input/examples/Alert.tsx +40 -0
  26. package/dist/mdx/{labs-react/text-input/examples/HiddenLabel.tsx → preview-react/text-input/examples/Basic.tsx} +3 -3
  27. package/dist/mdx/preview-react/text-input/examples/Disabled.tsx +17 -0
  28. package/dist/mdx/{labs-react → preview-react}/text-input/examples/Error.tsx +6 -9
  29. package/dist/mdx/preview-react/text-input/examples/Grow.tsx +17 -0
  30. package/dist/mdx/preview-react/text-input/examples/HiddenLabel.tsx +20 -0
  31. package/dist/mdx/preview-react/text-input/examples/LabelPositionHorizontal.tsx +17 -0
  32. package/dist/mdx/preview-react/text-input/examples/LabelPositionVertical.tsx +17 -0
  33. package/dist/mdx/{labs-react → preview-react}/text-input/examples/LoginForm.tsx +10 -5
  34. package/dist/mdx/preview-react/text-input/examples/Password.tsx +17 -0
  35. package/dist/mdx/preview-react/text-input/examples/Placeholder.tsx +17 -0
  36. package/dist/mdx/{labs-react → preview-react}/text-input/examples/RefForwarding.tsx +7 -6
  37. package/dist/mdx/preview-react/text-input/examples/Required.tsx +17 -0
  38. package/dist/mdx/preview-react/text-input/examples/ThemedAlert.tsx +46 -0
  39. package/dist/mdx/{labs-react → preview-react}/text-input/examples/ThemedError.tsx +8 -11
  40. package/dist/mdx/react/action-bar/ActionBar.mdx +1 -1
  41. package/dist/mdx/react/button/button/Button.mdx +34 -9
  42. package/dist/mdx/react/button/button/examples/Primary.tsx +10 -1
  43. package/dist/mdx/react/button/button/examples/PrimaryInverse.tsx +14 -0
  44. package/dist/mdx/react/button/button/examples/Secondary.tsx +10 -1
  45. package/dist/mdx/react/button/button/examples/SecondaryInverse.tsx +14 -0
  46. package/dist/mdx/react/button/button/examples/Tertiary.tsx +10 -1
  47. package/dist/mdx/react/button/button/examples/TertiaryInverse.tsx +14 -0
  48. package/dist/mdx/react/button/icon-button/IconButton.mdx +1 -1
  49. package/dist/mdx/react/pagination/pagination.mdx +5 -3
  50. package/dist/mdx/react/popup/Popup.mdx +34 -36
  51. package/dist/mdx/react/radio/examples/Alert.tsx +3 -3
  52. package/dist/mdx/react/radio/examples/Basic.tsx +3 -3
  53. package/dist/mdx/react/radio/examples/Disabled.tsx +3 -3
  54. package/dist/mdx/react/radio/examples/Error.tsx +3 -3
  55. package/dist/mdx/react/radio/examples/LabelPosition.tsx +3 -3
  56. package/dist/mdx/react/radio/examples/NoValue.tsx +3 -3
  57. package/dist/mdx/react/radio/examples/RefForwarding.tsx +3 -3
  58. package/dist/mdx/react/radio/examples/Required.tsx +3 -3
  59. package/dist/mdx/react/segmented-control/SegmentedControl.mdx +1 -1
  60. package/dist/mdx/react/tabs/Tabs.mdx +67 -36
  61. package/dist/mdx/react/tabs/examples/DisabledTab.tsx +1 -1
  62. package/dist/mdx/react/tabs/examples/DynamicTabs.tsx +41 -13
  63. package/dist/mdx/react/tabs/examples/HoistedModel.tsx +4 -4
  64. package/dist/mdx/react/tabs/examples/Icons.tsx +36 -0
  65. package/dist/mdx/react/tabs/examples/{NamedKeys.tsx → NamedTabs.tsx} +0 -0
  66. package/dist/mdx/react/tabs/examples/OverflowTabs.tsx +58 -0
  67. package/dist/mdx/react/tabs/examples/SinglePanel.tsx +1 -1
  68. package/dist/mdx/react/toast/toast.mdx +1 -17
  69. package/dist/mdx/react/tooltip/Tooltip.mdx +1 -1
  70. package/dist/mdx/react/tooltip/examples/Ellipsis.tsx +6 -0
  71. package/package.json +3 -3
  72. package/dist/mdx/labs-react/text-input/examples/Alert.tsx +0 -46
  73. package/dist/mdx/labs-react/text-input/examples/Basic.tsx +0 -20
  74. package/dist/mdx/labs-react/text-input/examples/Disabled.tsx +0 -20
  75. package/dist/mdx/labs-react/text-input/examples/Grow.tsx +0 -20
  76. package/dist/mdx/labs-react/text-input/examples/LabelPosition.tsx +0 -20
  77. package/dist/mdx/labs-react/text-input/examples/Password.tsx +0 -20
  78. package/dist/mdx/labs-react/text-input/examples/Placeholder.tsx +0 -20
  79. package/dist/mdx/labs-react/text-input/examples/Required.tsx +0 -20
  80. package/dist/mdx/labs-react/text-input/examples/ThemedAlert.tsx +0 -51
@@ -11,6 +11,30 @@ any questions about the update.
11
11
  - [Page Header](#page-header)
12
12
  - [Component Migrations](#component-migrations)
13
13
  - [Search Bar](#search-bar)
14
+ - [Name Updates](#name-updates)
15
+ - [Depth Tokens](#depth-tokens)
16
+ - [Theme Breakpoint Updates](#theme-breakpoint-updates)
17
+ - [Action Bar](#action-bar)
18
+ - [Tabs Component](#tabs-component)
19
+ - [Button Updates](#button-updates)
20
+ - [Primary Button](#primary-button)
21
+ - [Primary Disabled](#primary-disabled)
22
+ - [Primary Large](#primary-large)
23
+ - [Primary Medium](#primary-medium)
24
+ - [Primary Small](#primary-small)
25
+ - [Primary Extra Small](#primary-extra-small)
26
+ - [Secondary Button](#secondary-button)
27
+ - [Secondary Disabled](#secondary-disabled)
28
+ - [Secondary Large](#secondary-large)
29
+ - [Secondary Medium](#secondary-medium)
30
+ - [Secondary Small](#secondary-small)
31
+ - [Secondary Extra Small](#secondary-extra-small)
32
+ - [Tertiary Button](#tertiary-button)
33
+ - [Tertiary Default](#tertiary-default)
34
+ - [Tertiary Disabled](#tertiary-disabled)
35
+ - [Tertiary Medium](#tertiary-medium)
36
+ - [Tertiary Small](#tertiary-small)
37
+ - [Tertiary Extra Small](#tertiary-extra-small)
14
38
 
15
39
  ## Codemod
16
40
 
@@ -293,4 +317,238 @@ import {
293
317
  const CustomSearchForm = (props: SearchFormProps) => {
294
318
  return <SearchForm searchTheme={SearchTheme.Dark} {...props} />;
295
319
  };
296
- ```
320
+ ```
321
+
322
+ ## Name Updates
323
+
324
+ ### Depth Tokens
325
+
326
+ The `CanvasDepthValue` type has been renamed to `CanvasDepthValues` to be more consistent with our
327
+ other token type names, such as `CanvasBorderRadiusValues`, `CanvasSpaceValues`, and
328
+ `CanvasSpaceNumberValues`.
329
+
330
+ 🤖 The codemod will handle this rename transformation automatically:
331
+
332
+ ```ts
333
+ // v5
334
+ import {CanvasDepthValue} from '@workday/canvas-kit-react/tokens';
335
+
336
+ type CustomDepthValues = CanvasDepthValue;
337
+ interface OtherCustomDepthValues extends CanvasDepthValue {}
338
+
339
+ // v6
340
+ import {CanvasDepthValues} from '@workday/canvas-kit-react/tokens';
341
+
342
+ type CustomDepthValues = CanvasDepthValues;
343
+ interface OtherCustomDepthValues extends CanvasDepthValues {}
344
+ ```
345
+
346
+ ## Theme Breakpoint Updates
347
+
348
+ Our default theme breakpoints have been updated to match the viewport ranges described in our design
349
+ guidelines. We also updated `ActionBar`'s media query to align with this change. Those changes are
350
+ described in [the section below](#action-bar). If you are using these default breakpoints, you will
351
+ need to do visual regression testing to ensure there are no adverse effects to your application's
352
+ layout. If you have questions about this testing, please reach out to our team.
353
+
354
+ Below is a reference table for the V5 and V6 breakpoint values.
355
+
356
+ | Breakpoint Name | V5 Value (px) | V6 Value (px) |
357
+ | --------------- | ------------- | ------------- |
358
+ | `zero` | 0 | 0 |
359
+ | `s` | 600 | 320 |
360
+ | `m` | 900 | 768 |
361
+ | `l` | 1280 | 1024 |
362
+ | `xl` | 1920 | 1440 |
363
+
364
+ Also for reference, these are our viewport ranges:
365
+
366
+ - `small` (`320px` - `767px`) Used for mobile-sized screens
367
+ - `medium` (`768px` - `1023px`) Used for tablet-sized screens
368
+ - `large` - (`1024px` - `1439px`) Used for laptop and small desktop screens
369
+ - `extra-large` (`≥1440px`) Used for very large screens
370
+
371
+ ### Action Bar
372
+
373
+ `ActionBar` was updated to use the new breakpoint values. It previously had two media queries with
374
+ `max-width: 575px`. They now use `max-width: 767.5px` – the upper limit of the `small` range. This
375
+ will have two effects for this component:
376
+
377
+ - Container padding will decrease from `s` (`16px`) to `xxs` (`8px`) on all viewports less than `768px` wide
378
+ - This was previously happening only on viewports less than `576px` wide
379
+ - Button order will be reversed on all viewports less than `768px` wide
380
+ - This was previously happening only on viewports less than `576px` wide
381
+
382
+ These changes in behavior are intentional and expected.
383
+
384
+ ## Tabs Component
385
+
386
+ The Tabs API changed to support a responsive layout
387
+ ([#1325](https://github.com/Workday/canvas-kit/pull/1325)). The model API was updated to support
388
+ more generic behaviors to allow for other components to support responsive layouts using the same
389
+ models and behaviors. The most notable changes were concerning the state and events around tab
390
+ selection. The verb "select" was chosen to more accurately reflect selection for more component
391
+ types. Also selection of lists (which Tabs is based on) can support single or multiple selection.
392
+ Selection is now stored on state as an array of selected keys.
393
+
394
+ ```tsx
395
+ // v5
396
+ const model = useTabsModel({
397
+ shouldActivate,
398
+ onActivate,
399
+ });
400
+
401
+ console.log('Selected tab', model.state.activeTab);
402
+ model.events.activate({tab: tabName});
403
+
404
+ // v6
405
+ const model = useTabsModel({
406
+ shouldSelect,
407
+ onSelect,
408
+ });
409
+
410
+ console.log('Selected tab', model.state.selectedKey[0]);
411
+ model.events.select({id: tabName});
412
+ ```
413
+
414
+ The Tabs component can now handle responsive containers, but the support is not automatic. You must
415
+ use the dynamic API and provide an overflow menu subcomponent. The dynamic API doesn't know the
416
+ shape of your object, so render props must be used to instruct React how to render each item.
417
+
418
+ ```tsx
419
+ // Use `useState` because React will give the same reference each render
420
+ const [items] = React.useState([
421
+ {id: 'first', text: 'First Tab', contents: 'First Tab Content'},
422
+ {id: 'second', text: 'Second Tab', contents: 'Second Tab Content'},
423
+ ]);
424
+
425
+ return (
426
+ <Tabs items={items}>
427
+ <Tabs.List overflowButton={<Tabs.OverflowButton>More</Tabs.OverflowButton>}>
428
+ {item => <Tabs.Item name={item.id}>{item.text}</Tabs.Item>}
429
+ </Tabs.List>
430
+ <Tabs.Menu.Popper>
431
+ <Tabs.Menu.Card maxWidth={300} maxHeight={200}>
432
+ <Tabs.Menu.List>
433
+ {(item: MyTabItem) => <Tabs.Menu.Item name={item.id}>{item.text}</Tabs.Menu.Item>}
434
+ </Tabs.Menu.List>
435
+ </Tabs.Menu.Card>
436
+ </Tabs.Menu.Popper>
437
+ </Tabs>
438
+ );
439
+ ```
440
+
441
+ ## Button Updates
442
+
443
+ All button updates for V6 are limited to our Primary, Secondary, and Tertiary buttons. Most of the
444
+ button updates are small visual adjustments:
445
+
446
+ - We tightened up tighten the spacing for visual balance and added our new type hierarchy.
447
+ - We adjusted icon sizes for uniformity:
448
+ - `large`: `24px` x `24px`
449
+ - `medium`: `20px` x `20px`
450
+ - `small`: `20px` x `20px`
451
+ - `extraSmall`: `18px` x `18px`
452
+ - We also adjusted the opacity for their disabled state so they behave more appropriately on varied
453
+ / dark backgrounds.
454
+
455
+ These changes are automatic when you upgrade and do not require any manual updates in your codebase.
456
+ However, they will likely cause any automated visual regression tests to fail, and you will need to
457
+ update your tests accordingly. We do not expect these minor adjustments to create significant layout
458
+ shifts in your UI. But, as with any visual update, you will want to review your UI to ensure there
459
+ are no adverse effects.
460
+
461
+ We also added some net-new features:
462
+
463
+ - All buttons have a new `extraSmall` size.
464
+ - Icons are now supported for all sizes.
465
+ - `PrimaryButton` has a new `inverse` variant.
466
+
467
+ All these changes are described in detail by button type in the sections below.
468
+
469
+ ### Primary Button
470
+
471
+ #### Primary Disabled State
472
+
473
+ Previously the button's disabled state had a `blueberry200` background, but it now uses the default
474
+ `blueberry400` and sets the entire button to 40% opacity. This creates more consistency for the
475
+ disabled states across all our buttons.
476
+
477
+ #### Primary Large
478
+
479
+ The padding for large `PrimaryButton`s has been slightly adjusted for more visual balance and to
480
+ take up a bit less layout space. Specifically we:
481
+
482
+ - decreased the space between the button icon and text from `12px` to `8px`
483
+ - decreased the space between the button container and the icon from `28px` to `24px`
484
+
485
+ #### Primary Medium
486
+
487
+ The icon size for medium `PrimaryButton`s has been decreased from `24px` to `20px`, but the overall
488
+ height of the button will remain the same.
489
+
490
+ #### Primary Small
491
+
492
+ We now support icons for small `PrimaryButton`s. The icons are `20px` x `20px`.
493
+
494
+ #### Primary Extra Small
495
+
496
+ We added a new size, `extraSmall` to our `PrimaryButton`s. These are particularly helpful for use
497
+ cases where you have dense UI or tight layout constraints such as tables.
498
+
499
+ ### Secondary Button
500
+
501
+ #### Secondary Large
502
+
503
+ The padding for large `SecondaryButton`s has been slightly adjusted for more visual balance and to
504
+ take up a bit less layout space. Specifically we:
505
+
506
+ - decreased the space between the button icon and text from `12px` to `8px`
507
+ - decreased the space between the button container and the icon from `28px` to `24px`
508
+
509
+ #### Secondary Medium
510
+
511
+ The icon size for medium `SecondaryButton`s has been decreased from `24px` to `20px`, but the
512
+ overall height of the button will remain the same.
513
+
514
+ #### Secondary Small
515
+
516
+ We now support icons for small `SecondaryButton`s. The icons are `20px` x `20px`.
517
+
518
+ #### Secondary Extra Small
519
+
520
+ We added a new size, `extraSmall` to our `SecondaryButton`s. These are particularly helpful for use
521
+ cases where you have dense UI or tight layout constraints such as tables.
522
+
523
+ ### Tertiary Button
524
+
525
+ #### Tertiary Default
526
+
527
+ We added an underline to the button text for all states to help distinguish it from the
528
+ `SecondaryButton` and create more visual consistency.
529
+
530
+ #### Tertiary Disabled
531
+
532
+ As with our other buttons, we updated the disabled state to set the entire button to 40% opacity.
533
+ They were previously using our light theme color at 50% opacity for icons and text.
534
+
535
+ #### Tertiary Medium
536
+
537
+ The medium `TertiaryButton` now uses our new type hierarchy and adjusted the padding, but the
538
+ overall size of the button will stay the same. Specifically, we:
539
+
540
+ - decreased the space between the button icon and text from `8px` to `4px`
541
+
542
+ #### Tertiary Small
543
+
544
+ The small `TertiaryButton` now uses our new type hierarchy and adjusted the padding, but the overall
545
+ size of the button will stay the same. Specifically, we:
546
+
547
+ - decreased the space between the button icon and text from `8px` to `4px`
548
+ - increased the container padding outside the button text when an icon is present from `8px` to
549
+ `12px`
550
+
551
+ #### Tertiary Extra Small
552
+
553
+ We added a new size, `extraSmall` to our `TertiaryButton`s. These are particularly helpful for use
554
+ cases where you have dense UI or tight layout constraints such as tables.
@@ -78,8 +78,8 @@ const Tabs = ({children, model, ...config}) => {
78
78
 
79
79
  ## Subcomponents
80
80
 
81
- A subcomponent typically follows ARIA roles. For the `Tabs` example, these are the `tablist`,
82
- `tab`, and `tabpanel` roles. A subcomponent provides direct access to semantic or key elements of a
81
+ A subcomponent typically follows ARIA roles. For the `Tabs` example, these are the `tablist`, `tab`,
82
+ and `tabpanel` roles. A subcomponent provides direct access to semantic or key elements of a
83
83
  compound component. In the `IconButton` example, the icon is not semantic and might be hidden from
84
84
  screen readers while the `IconButton.Text` content is instead used for a tooltip and as the
85
85
  accessible name while being visibly hidden.
@@ -175,35 +175,35 @@ Components that directly wrap an element (most of them) will have the following
175
175
 
176
176
  Compound components are also made up of [models](#models) that accept [guards](#guards) to
177
177
  conditionally prevent state changes and [callbacks](#callbacks) to attach listeners. For example, in
178
- our Tabs component clicking a Tab will activate that tab. The `Tabs` container component will accept
179
- a `shouldActivate` and a `onActivate` for the event called `activate`.
178
+ our Tabs component clicking a Tab will select that tab. The `Tabs` container component will accept a
179
+ `shouldSelect` and a `onSelect` for the event called `select`.
180
180
 
181
181
  ```tsx
182
182
  const MyComponent = () => {
183
- // `data` is all event data from the `activate` event
183
+ // `data` is all event data from the `select` event
184
184
 
185
185
  // `state` is the current state of the `Tabs` component
186
- const shouldActivate = ({data, state}) => {
187
- // for some reason, we only want to allow activation the 'first' tab
188
- // Clicking on the first tab will activate it, but clicking on the
186
+ const shouldSelect = ({data, state}) => {
187
+ // for some reason, we only want to allow selection the 'first' tab
188
+ // Clicking on the first tab will select it, but clicking on the
189
189
  // second tab will do nothing
190
190
  return data.tab === 'first' ? true : false;
191
191
 
192
192
  // returning true allows the event to trigger a state change and will
193
- // also call the `onActivate` callback
193
+ // also call the `onSelect` callback
194
194
  };
195
195
 
196
196
  // `prevState` is the previous state of the model. Callbacks are called _before_ state has resolved.
197
197
  // This means the passed state hasn't updated yet. It also means it is safe to call `setState` without
198
198
  // triggering extra renders. `setState` calls will add to React's batching system before a state changes
199
199
  // are flushed and render functions are called.
200
- const onActivate = ({data, prevState}) => {
201
- // called any time the `activate` event is triggered
202
- console.log('onActivate', data, prevState);
200
+ const onSelect = ({data, prevState}) => {
201
+ // called any time the `select` event is triggered
202
+ console.log('onSelect', data, prevState);
203
203
  };
204
204
 
205
205
  return (
206
- <Tabs shouldActivate={shouldActivate} onActivate={onActivate}>
206
+ <Tabs shouldSelect={shouldSelect} onSelect={onSelect}>
207
207
  <Tabs.List>
208
208
  <Tabs.Item name="first">First</Tabs.Item>
209
209
  <Tabs.Item name="second">Second</Tabs.Item>
@@ -324,20 +324,20 @@ const useEllipsisTooltipModel = (config = {}) => {
324
324
 
325
325
  Models are meant to be composable. For example, a `TabsModel` uses a `CursorModel` (which itself
326
326
  uses `ListModel`) and a `ListModel` for a list of panels. `TabsModel` also keeps track of which tab
327
- is currently active. This might look like the following:
327
+ is currently selected. This might look like the following:
328
328
 
329
329
  ```ts
330
330
  const useTabsModel = (config = {}) => {
331
331
  // id is used for ARIA attributes
332
332
  const id = useUniqueId(config.id);
333
- const [activeTab, setActiveTab] = React.useState('');
333
+ const [selectedTab, setSelectedTab] = React.useState('');
334
334
  const cursor = useCursorModel(config);
335
335
  const panels = useListModel(config);
336
336
 
337
337
  const state = {
338
338
  ...cursor.state, // extend the CursorModel state
339
339
  id,
340
- activeTab,
340
+ selectedTab,
341
341
  panels: panels.state.items, // we only care about
342
342
  };
343
343
 
@@ -346,12 +346,12 @@ const useTabsModel = (config = {}) => {
346
346
  registerPanel: panels.events.registerItem,
347
347
  unregisterPanel: panels.events.unregisterItem,
348
348
 
349
- activate(data) {
350
- if (config.shouldActivate?.({data, prevState: state}) === false) {
349
+ select(data) {
350
+ if (config.shouldSelect?.({data, prevState: state}) === false) {
351
351
  return;
352
352
  }
353
- setActiveTab(data.tab);
354
- config.onActivate?.({data, prevState: state});
353
+ setSelectedTab(data.tab);
354
+ config.onSelect?.({data, prevState: state});
355
355
  },
356
356
  };
357
357
 
@@ -362,10 +362,11 @@ const useTabsModel = (config = {}) => {
362
362
  Model composition allows for components to share functionality with other components. In the Tabs
363
363
  example, `ListModel` is in charge of maintaining a list of tab elements. The `CursorModel` is in
364
364
  charge of maintaining a current cursor position of the tab list. The `Tabs.List` component uses the
365
- cursor to allow keyboard navigation of the tabs. The `TabsModel` also maintains the currently active
366
- tab to ensure the correct `TabPanel` is visible. The `TabsModel` is also using a `ListModel` to
367
- maintain a list of tab panels. The `TabsModel` is in charge of composing all this and providing data
368
- and events to the `Tabs` compound component - coordination state between subcomponents.
365
+ cursor to allow keyboard navigation of the tabs. The `TabsModel` also maintains the currently
366
+ selected tab to ensure the correct `TabPanel` is visible. The `TabsModel` is also using a
367
+ `ListModel` to maintain a list of tab panels. The `TabsModel` is in charge of composing all this and
368
+ providing data and events to the `Tabs` compound component - coordination state between
369
+ subcomponents.
369
370
 
370
371
  Many other components like `Select`, `Breadcrumbs`, or dropdown menus can also use the `ListModel`
371
372
  and/or the `CursorModel`. These models could be thought of as abstract models where they do not
@@ -463,11 +464,11 @@ const TabList = ({children, ...elemProps}) => {
463
464
 
464
465
  A container component can either accept model configuration _or_ a model. Passing model
465
466
  configuration allows for simpler model configuration of guards, callbacks, or any other model
466
- configuration. The following example provides an `onActivate` callback that fetches some data from
467
- the server:
467
+ configuration. The following example provides an `onSelect` callback that fetches some data from the
468
+ server:
468
469
 
469
470
  ```tsx
470
- <Tabs onActivate={({data}) => fetch('/api/activate' + data.id)}>...</Tabs>
471
+ <Tabs onSelect={({data}) => fetch('/api/selectTab' + data.id)}>...</Tabs>
471
472
  ```
472
473
 
473
474
  If you need direct access to a model's state or events, you can hoist the model into your component
@@ -479,15 +480,15 @@ look like this:
479
480
  const MyTabs = () => {
480
481
  const model = useTabsModel({
481
482
  // we can still load data from the server
482
- onActivate: ({data}) => fetch('/api/activate' + data.id),
483
+ onSelect: ({data}) => fetch('/api/selectTab' + data.id),
483
484
  });
484
485
 
485
486
  return (
486
487
  <>
487
488
  <Tabs model={model}>...</Tabs>
488
- // direct access to the model's state Currently selected tab: {model.state.activeTab}
489
+ // direct access to the model's state Currently selected tab: {model.state.selectedTab}
489
490
  // Now we can send events directly to the model
490
- <button onClick={() => model.events.activate({tab: 'third'})}>Activate third tab</button>
491
+ <button onClick={() => model.events.select({tab: 'third'})}>Select third tab</button>
491
492
  </>
492
493
  );
493
494
  };
@@ -46,7 +46,7 @@ you'll need to add `buttonAriaLabel` to `Breadcrumbs.CollapsibleList`.
46
46
 
47
47
  <ExampleCodeBlock code={CollapsibleList} />
48
48
 
49
- ### Right-to-Left Example
49
+ ### Right-to-Left (RTL)
50
50
 
51
51
  Breadcrumbs has bidirectional support out of the box. That means outside of setting the content
52
52
  direction in your application's Canvas theme, you don't need to do anything else to make it work.
@@ -0,0 +1,27 @@
1
+ import {Specifications} from '@workday/canvas-kit-docs';
2
+
3
+ import {FormField} from '@workday/canvas-kit-preview-react/form-field';
4
+
5
+ import Custom from './examples/Custom';
6
+
7
+
8
+ # Canvas Kit Form Field
9
+
10
+ FormField allows users to wrap input components to make them accessible. You usually won't want to
11
+ use FormField directly but instead should use the specific component you need, e.g. `TextInput`.
12
+
13
+ ## Installation
14
+
15
+ ```sh
16
+ yarn add @workday/canvas-kit-preview-react
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### Customizing With Behavior Hooks Example
22
+
23
+ If you need full customization you can use the form field behavior hooks to build your own solution.
24
+ It is also easy it work with custom components or third party libraries and get the CKR
25
+ accessibility guarantees by using the `as` prop.
26
+
27
+ <ExampleCodeBlock code={Custom} />
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ import {
3
+ useFormFieldHint,
4
+ useFormFieldInput,
5
+ useFormFieldLabel,
6
+ useFormFieldModel,
7
+ useFormFieldOrientation,
8
+ FormFieldModelContext,
9
+ } from '@workday/canvas-kit-preview-react/form-field';
10
+ import {useModelContext} from '@workday/canvas-kit-react/common';
11
+ import {Stack} from '@workday/canvas-kit-labs-react/layout';
12
+
13
+ const Label = ({model, children}) => {
14
+ const localModel = useModelContext(FormFieldModelContext, model);
15
+ const props = useFormFieldLabel(localModel);
16
+
17
+ return (
18
+ <label {...props}>
19
+ {children}
20
+ {model.state.isRequired ? '*' : ''}
21
+ </label>
22
+ );
23
+ };
24
+
25
+ const Hint = ({model, children}) => {
26
+ const localModel = useModelContext(FormFieldModelContext, model);
27
+ const props = useFormFieldHint(localModel);
28
+
29
+ return <span {...props}>{children}</span>;
30
+ };
31
+
32
+ const Input = ({model, ...elementProps}) => {
33
+ const localModel = useModelContext(FormFieldModelContext, model);
34
+ const props = useFormFieldInput(localModel, elementProps);
35
+
36
+ return <input type="text" required={model.state.isRequired ? true : false} {...props} />;
37
+ };
38
+
39
+ export default () => {
40
+ const [value, setValue] = React.useState('');
41
+
42
+ const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
43
+ setValue(event.target.value);
44
+ };
45
+
46
+ const model = useFormFieldModel({isRequired: true});
47
+
48
+ const layoutProps = useFormFieldOrientation('vertical')
49
+
50
+ return (
51
+ <Stack {...layoutProps}>
52
+ <Label model={model}>My Custom Field</Label>
53
+ <Input model={model} value={value} onChange={handleChange} />
54
+ <Hint model={model}>You can be anything</Hint>
55
+ </Stack>
56
+ );
57
+ };
@@ -10,7 +10,7 @@ import {Menu, MenuItem} from '@workday/canvas-kit-preview-react/menu';
10
10
 
11
11
  export default () => {
12
12
  return (
13
- <Menu title="Menu Title">
13
+ <Menu>
14
14
  <MenuItem icon={uploadCloudIcon}>First Item</MenuItem>
15
15
  <MenuItem icon={setupIcon}>Second Item (with a really really really long label)</MenuItem>
16
16
  <MenuItem isDisabled icon={uploadCloudIcon} secondaryIcon={taskContactIcon}>
@@ -4,7 +4,7 @@ import {Menu, MenuItem} from '@workday/canvas-kit-preview-react/menu';
4
4
 
5
5
  export default () => {
6
6
  return (
7
- <Menu title="Menu Titles">
7
+ <Menu>
8
8
  {'One Two Three Four Five Six Seven Eight Nine Ten Eleven Twelve Thirteen Fourteen Fifteen'
9
9
  .split(' ')
10
10
  .map(item => {
@@ -0,0 +1,122 @@
1
+ import {Specifications} from '@workday/canvas-kit-docs';
2
+
3
+ import {TextArea} from '@workday/canvas-kit-preview-react/text-area';
4
+
5
+ import Alert from './examples/Alert';
6
+ import Basic from './examples/Basic';
7
+ import Disabled from './examples/Disabled';
8
+ import Error from './examples/Error';
9
+ import Grow from './examples/Grow';
10
+ import LabelPositionVertical from './examples/LabelPositionVertical';
11
+ import LabelPositionHorizontal from './examples/LabelPositionHorizontal';
12
+ import HiddenLabel from './examples/HiddenLabel';
13
+ import Placeholder from './examples/Placeholder';
14
+ import RefForwarding from './examples/RefForwarding';
15
+ import Required from './examples/Required';
16
+ import ResizeConstraints from './examples/ResizeConstraints';
17
+
18
+
19
+ # Canvas Kit Text Area
20
+
21
+ TextArea's allow users to enter and edit multiple lines of text.
22
+
23
+ [> Workday Design Reference](https://design.workday.com/components/inputs/text-area)
24
+
25
+ ## Installation
26
+
27
+ ```sh
28
+ yarn add @workday/canvas-kit-preview-react
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ### Basic Example
34
+
35
+ <ExampleCodeBlock code={Basic} />
36
+
37
+ ### Disabled
38
+
39
+ Use `TextArea.Field`'s `disabled` prop to prevent users from interacting with the field.
40
+
41
+ <ExampleCodeBlock code={Disabled} />
42
+
43
+ ### Placeholder
44
+
45
+ Use `TextArea.Field`'s `placeholder` prop to display a sample of its expected format or value before
46
+ a value has been provided.
47
+
48
+ <ExampleCodeBlock code={Placeholder} />
49
+
50
+ ### Required
51
+
52
+ Use `TextArea.Field`'s `isRequired` prop (or use with the `useTextAreaModel` hook) to indicate that
53
+ the field is required. This will also add a red asterisk to `TextArea.Label`.
54
+
55
+ <ExampleCodeBlock code={Required} />
56
+
57
+ ### Ref Forwarding
58
+
59
+ `TextArea` supports [ref forwarding](https://reactjs.org/docs/forwarding-refs.html). It will forward
60
+ `ref` to its underlying `<textarea>` element.
61
+
62
+ <ExampleCodeBlock code={RefForwarding} />
63
+
64
+ ### Resize Constraints
65
+
66
+ Use the `resize` css attribute to restrict resizing of it to certain dimensions.
67
+
68
+ <ExampleCodeBlock code={ResizeConstraints} />
69
+
70
+ ### Grow
71
+
72
+ There are lots of ways to accomplish this. The `TextArea.Field` extends from Box so it is easy to
73
+ extend full width, e.g. setting width prop to 100%, or you can set the `alignItems` prop to
74
+ `stretch` on `TextArea`, etc.
75
+
76
+ <ExampleCodeBlock code={Grow} />
77
+
78
+ ### Label Position
79
+
80
+ Use the `orientation` property to set `TextArea.Label`'s position. You can override the default
81
+ spacing using the `spacing` prop. Below are examples of both positions:
82
+
83
+ #### Horizontal
84
+
85
+ <ExampleCodeBlock code={LabelPositionHorizontal} />
86
+
87
+ #### Vertical
88
+
89
+ <ExampleCodeBlock code={LabelPositionVertical} />
90
+
91
+ ### Visually Hiding The Label
92
+
93
+ If your label is just for screen reader users you can use the `accessibleHide` utility class from
94
+ `@workday/canvas-kit-react/common`. You will likely want to set the `spacing` prop on `TextArea` to
95
+ `zero`.
96
+
97
+ <ExampleCodeBlock code={HiddenLabel} />
98
+
99
+ ### Error States
100
+
101
+ Use the `hasError` property from `useTextAreaModel` to set the `TextArea` to the Error state. If you
102
+ have an accompanying hint you can use the `TextArea.Hint` subcomponent.
103
+
104
+ <ExampleCodeBlock code={Error} />
105
+
106
+ ### Other Visual States
107
+
108
+ Use the `useThemedRing` hook to change the visual state of the `<textarea>` element.
109
+
110
+ #### Alert
111
+
112
+ <ExampleCodeBlock code={Alert} />
113
+
114
+ ## Props
115
+
116
+ Undocumented props are spread to the underlying `<textarea>` element.
117
+
118
+ <ArgsTable of={TextArea} />
119
+
120
+ ## Specifications
121
+
122
+ <Specifications file="TextAreaPreview.spec.ts" name="Text Area" />