@workday/canvas-kit-docs 5.3.0-next.3 → 5.3.0-next.32

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 (105) hide show
  1. package/LICENSE +1 -1
  2. package/dist/commonjs/lib/specs.js +429 -33
  3. package/dist/es6/lib/specs.js +429 -33
  4. package/dist/mdx/5.0-MIGRATION-GUIDE.mdx +81 -7
  5. package/dist/mdx/6.0-MIGRATION-GUIDE.mdx +560 -0
  6. package/dist/mdx/COMPOUND_COMPONENTS.mdx +31 -30
  7. package/dist/mdx/CONTRIBUTING.mdx +90 -63
  8. package/dist/mdx/TESTING.mdx +29 -5
  9. package/dist/mdx/labs-react/search-form/SearchForm.mdx +64 -0
  10. package/dist/mdx/labs-react/search-form/examples/Basic.tsx +61 -0
  11. package/dist/mdx/labs-react/search-form/examples/CustomTheme.tsx +72 -0
  12. package/dist/mdx/labs-react/search-form/examples/Grow.tsx +62 -0
  13. package/dist/mdx/labs-react/search-form/examples/PropTables.splitProps.tsx +4 -0
  14. package/dist/mdx/labs-react/search-form/examples/RTL.tsx +70 -0
  15. package/dist/mdx/labs-react/search-form/examples/Theming.tsx +64 -0
  16. package/dist/mdx/preview-react/breadcrumbs/Breadcrumbs.mdx +1 -1
  17. package/dist/mdx/preview-react/form-field/FormField.mdx +27 -0
  18. package/dist/mdx/preview-react/form-field/examples/Custom.tsx +57 -0
  19. package/dist/mdx/preview-react/menu/Menu.mdx +17 -9
  20. package/dist/mdx/preview-react/menu/examples/Basic.tsx +65 -10
  21. package/dist/mdx/preview-react/menu/examples/ContextMenu.tsx +47 -29
  22. package/dist/mdx/preview-react/menu/examples/CustomMenuItem.tsx +2 -2
  23. package/dist/mdx/preview-react/menu/examples/Icons.tsx +1 -1
  24. package/dist/mdx/preview-react/menu/examples/ManyItems.tsx +2 -2
  25. package/dist/mdx/preview-react/text-area/TextArea.mdx +122 -0
  26. package/dist/mdx/preview-react/text-area/examples/Alert.tsx +31 -0
  27. package/dist/mdx/preview-react/text-area/examples/Basic.tsx +17 -0
  28. package/dist/mdx/preview-react/text-area/examples/Disabled.tsx +17 -0
  29. package/dist/mdx/preview-react/text-area/examples/Error.tsx +40 -0
  30. package/dist/mdx/preview-react/text-area/examples/Grow.tsx +17 -0
  31. package/dist/mdx/preview-react/text-area/examples/HiddenLabel.tsx +20 -0
  32. package/dist/mdx/preview-react/text-area/examples/LabelPositionHorizontal.tsx +17 -0
  33. package/dist/mdx/preview-react/text-area/examples/LabelPositionVertical.tsx +17 -0
  34. package/dist/mdx/preview-react/text-area/examples/Placeholder.tsx +21 -0
  35. package/dist/mdx/preview-react/text-area/examples/RefForwarding.tsx +28 -0
  36. package/dist/mdx/preview-react/text-area/examples/Required.tsx +17 -0
  37. package/dist/mdx/preview-react/text-area/examples/ResizeConstraints.tsx +22 -0
  38. package/dist/mdx/preview-react/text-input/TextInput.mdx +145 -0
  39. package/dist/mdx/preview-react/text-input/examples/Alert.tsx +40 -0
  40. package/dist/mdx/preview-react/text-input/examples/Basic.tsx +17 -0
  41. package/dist/mdx/preview-react/text-input/examples/Disabled.tsx +17 -0
  42. package/dist/mdx/preview-react/text-input/examples/Error.tsx +40 -0
  43. package/dist/mdx/preview-react/text-input/examples/Grow.tsx +17 -0
  44. package/dist/mdx/preview-react/text-input/examples/HiddenLabel.tsx +20 -0
  45. package/dist/mdx/preview-react/text-input/examples/LabelPositionHorizontal.tsx +17 -0
  46. package/dist/mdx/preview-react/text-input/examples/LabelPositionVertical.tsx +17 -0
  47. package/dist/mdx/preview-react/text-input/examples/LoginForm.tsx +105 -0
  48. package/dist/mdx/preview-react/text-input/examples/Password.tsx +17 -0
  49. package/dist/mdx/preview-react/text-input/examples/Placeholder.tsx +17 -0
  50. package/dist/mdx/preview-react/text-input/examples/RefForwarding.tsx +28 -0
  51. package/dist/mdx/preview-react/text-input/examples/Required.tsx +17 -0
  52. package/dist/mdx/preview-react/text-input/examples/ThemedAlert.tsx +46 -0
  53. package/dist/mdx/preview-react/text-input/examples/ThemedError.tsx +37 -0
  54. package/dist/mdx/react/_examples/CookieBanner.mdx +8 -0
  55. package/dist/mdx/react/_examples/GlobalHeader.mdx +9 -0
  56. package/dist/mdx/react/_examples/PageHeader.mdx +8 -0
  57. package/dist/mdx/react/_examples/examples/CookieBanner.tsx +97 -0
  58. package/dist/mdx/react/_examples/examples/GlobalHeader.tsx +66 -0
  59. package/dist/mdx/react/_examples/examples/PageHeader.tsx +63 -0
  60. package/dist/mdx/react/action-bar/ActionBar.mdx +1 -1
  61. package/dist/mdx/react/button/button/Button.mdx +34 -9
  62. package/dist/mdx/react/button/button/examples/Primary.tsx +11 -1
  63. package/dist/mdx/react/button/button/examples/PrimaryInverse.tsx +14 -0
  64. package/dist/mdx/react/button/button/examples/Secondary.tsx +10 -1
  65. package/dist/mdx/react/button/button/examples/SecondaryInverse.tsx +14 -0
  66. package/dist/mdx/react/button/button/examples/Tertiary.tsx +10 -1
  67. package/dist/mdx/react/button/button/examples/TertiaryInverse.tsx +14 -0
  68. package/dist/mdx/react/button/icon-button/IconButton.mdx +1 -1
  69. package/dist/mdx/react/loading-animation/LoadingAnimation.mdx +5 -0
  70. package/dist/mdx/react/loading-animation/examples/RTL.tsx +16 -0
  71. package/dist/mdx/react/pagination/PropTables.splitprops.tsx +47 -0
  72. package/dist/mdx/react/pagination/examples/{StepControls.tsx → Basic.tsx} +1 -1
  73. package/dist/mdx/react/pagination/examples/GoToForm.tsx +1 -1
  74. package/dist/mdx/react/pagination/examples/HoistedModel.tsx +36 -22
  75. package/dist/mdx/react/pagination/examples/RTL.tsx +1 -1
  76. package/dist/mdx/react/pagination/pagination.mdx +225 -474
  77. package/dist/mdx/react/popup/Popup.mdx +96 -36
  78. package/dist/mdx/react/popup/examples/FullScreen.tsx +115 -0
  79. package/dist/mdx/react/radio/examples/Alert.tsx +3 -3
  80. package/dist/mdx/react/radio/examples/Basic.tsx +3 -3
  81. package/dist/mdx/react/radio/examples/Disabled.tsx +3 -3
  82. package/dist/mdx/react/radio/examples/Error.tsx +3 -3
  83. package/dist/mdx/react/radio/examples/LabelPosition.tsx +3 -3
  84. package/dist/mdx/react/radio/examples/NoValue.tsx +3 -3
  85. package/dist/mdx/react/radio/examples/RefForwarding.tsx +3 -3
  86. package/dist/mdx/react/radio/examples/Required.tsx +3 -3
  87. package/dist/mdx/react/segmented-control/SegmentedControl.mdx +1 -1
  88. package/dist/mdx/react/tabs/Tabs.mdx +67 -36
  89. package/dist/mdx/react/tabs/examples/DisabledTab.tsx +1 -1
  90. package/dist/mdx/react/tabs/examples/DynamicTabs.tsx +82 -38
  91. package/dist/mdx/react/tabs/examples/HoistedModel.tsx +4 -4
  92. package/dist/mdx/react/tabs/examples/Icons.tsx +36 -0
  93. package/dist/mdx/react/tabs/examples/{NamedKeys.tsx → NamedTabs.tsx} +0 -0
  94. package/dist/mdx/react/tabs/examples/OverflowTabs.tsx +58 -0
  95. package/dist/mdx/react/tabs/examples/SinglePanel.tsx +1 -1
  96. package/dist/mdx/react/text-area/TextArea.mdx +1 -1
  97. package/dist/mdx/react/toast/toast.mdx +1 -17
  98. package/dist/mdx/react/tooltip/Tooltip.mdx +9 -1
  99. package/dist/mdx/react/tooltip/examples/DelayedTooltip.tsx +16 -0
  100. package/dist/mdx/react/tooltip/examples/Ellipsis.tsx +6 -0
  101. package/package.json +5 -4
  102. package/dist/mdx/CODE_OF_CONDUCT.md +0 -68
  103. package/dist/mdx/preview-react/menu/examples/ContextMenuTarget.tsx +0 -33
  104. package/dist/mdx/preview-react/menu/examples/ControlButton.tsx +0 -84
  105. package/dist/mdx/react/pagination/examples/ShowAdditionalDetails.tsx +0 -52
@@ -0,0 +1,62 @@
1
+ import * as React from 'react';
2
+ import {MenuItem} from '@workday/canvas-kit-preview-react/menu';
3
+ import {SearchForm} from '@workday/canvas-kit-labs-react/search-form';
4
+ import {Flex} from '@workday/canvas-kit-labs-react/layout';
5
+
6
+ const initialWineList = [
7
+ 'Beaujolais',
8
+ 'Bordeaux',
9
+ 'Cabernet Sauvignon',
10
+ 'Champagne',
11
+ 'Chardonnay',
12
+ 'Chianti',
13
+ 'Malbec',
14
+ 'Merlot',
15
+ 'Pinot Grigio',
16
+ 'Pinot Gris',
17
+ 'Pinot Noir',
18
+ 'Primitivo',
19
+ 'Prosecco',
20
+ 'Riesling',
21
+ 'Rioja',
22
+ 'Rosé',
23
+ 'Sauvignon Blanc',
24
+ 'Syrah',
25
+ 'Zinfandel',
26
+ ];
27
+
28
+ export default () => {
29
+ const [wineList, setWineList] = React.useState(initialWineList);
30
+ // Tracking the input value for onSubmit
31
+ const [searchInput, setSearchInput] = React.useState('');
32
+ const menuItems = wineList.map(wine => <MenuItem key={wine}>{wine}</MenuItem>);
33
+
34
+ const filterMenuItems = e => {
35
+ setSearchInput(e.target.value);
36
+ const formattedValue = e.target.value.toLowerCase();
37
+
38
+ // Reset the list if the input is cleared
39
+ if (!formattedValue.length) {
40
+ setWineList(initialWineList);
41
+ } else {
42
+ const filteredItems = wineList.filter(wine => wine.toLowerCase().startsWith(formattedValue));
43
+ setWineList(filteredItems);
44
+ }
45
+ };
46
+
47
+ const handleSubmit = () => {
48
+ // We don't need to prevent the default event because SearchForm handles that internally
49
+ console.log(`Searching for: ${searchInput}`);
50
+ };
51
+
52
+ return (
53
+ <Flex minHeight={200} alignItems="flex-start" padding="xs">
54
+ <SearchForm
55
+ autocompleteItems={menuItems}
56
+ grow
57
+ onInputChange={filterMenuItems}
58
+ onSubmit={handleSubmit}
59
+ />
60
+ </Flex>
61
+ );
62
+ };
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import {SearchThemeAttributes} from '@workday/canvas-kit-labs-react/search-form';
3
+
4
+ export default (props: SearchThemeAttributes) => <div />;
@@ -0,0 +1,70 @@
1
+ import * as React from 'react';
2
+ import {MenuItem} from '@workday/canvas-kit-preview-react/menu';
3
+ import {SearchForm} from '@workday/canvas-kit-labs-react/search-form';
4
+ import {Flex} from '@workday/canvas-kit-labs-react/layout';
5
+ import {CanvasProvider, ContentDirection} from '@workday/canvas-kit-react/common';
6
+
7
+ const initialWineList = [
8
+ 'Beaujolais',
9
+ 'Bordeaux',
10
+ 'Cabernet Sauvignon',
11
+ 'Champagne',
12
+ 'Chardonnay',
13
+ 'Chianti',
14
+ 'Malbec',
15
+ 'Merlot',
16
+ 'Pinot Grigio',
17
+ 'Pinot Gris',
18
+ 'Pinot Noir',
19
+ 'Primitivo',
20
+ 'Prosecco',
21
+ 'Riesling',
22
+ 'Rioja',
23
+ 'Rosé',
24
+ 'Sauvignon Blanc',
25
+ 'Syrah',
26
+ 'Zinfandel',
27
+ ];
28
+
29
+ export default () => {
30
+ const [wineList, setWineList] = React.useState(initialWineList);
31
+ // Tracking the input value for onSubmit
32
+ const [searchInput, setSearchInput] = React.useState('');
33
+ const menuItems = wineList.map(wine => <MenuItem key={wine}>{wine}</MenuItem>);
34
+
35
+ const filterMenuItems = e => {
36
+ setSearchInput(e.target.value);
37
+ const formattedValue = e.target.value.toLowerCase();
38
+
39
+ // Reset the list if the input is cleared
40
+ if (!formattedValue.length) {
41
+ setWineList(initialWineList);
42
+ } else {
43
+ const filteredItems = wineList.filter(wine => wine.toLowerCase().startsWith(formattedValue));
44
+ setWineList(filteredItems);
45
+ }
46
+ };
47
+
48
+ const handleSubmit = () => {
49
+ // We don't need to prevent the default event because SearchForm handles that internally
50
+ console.log(`Searching for: ${searchInput}`);
51
+ };
52
+
53
+ const theme = {
54
+ canvas: {
55
+ direction: ContentDirection.RTL,
56
+ },
57
+ };
58
+
59
+ return (
60
+ <CanvasProvider theme={theme}>
61
+ <Flex minHeight={200} alignItems="flex-start" padding="xs">
62
+ <SearchForm
63
+ autocompleteItems={menuItems}
64
+ onInputChange={filterMenuItems}
65
+ onSubmit={handleSubmit}
66
+ />
67
+ </Flex>
68
+ </CanvasProvider>
69
+ );
70
+ };
@@ -0,0 +1,64 @@
1
+ import * as React from 'react';
2
+ import {MenuItem} from '@workday/canvas-kit-preview-react/menu';
3
+ import {SearchForm, SearchTheme} from '@workday/canvas-kit-labs-react/search-form';
4
+ import {Flex} from '@workday/canvas-kit-labs-react/layout';
5
+
6
+ const initialWineList = [
7
+ 'Beaujolais',
8
+ 'Bordeaux',
9
+ 'Cabernet Sauvignon',
10
+ 'Champagne',
11
+ 'Chardonnay',
12
+ 'Chianti',
13
+ 'Malbec',
14
+ 'Merlot',
15
+ 'Pinot Grigio',
16
+ 'Pinot Gris',
17
+ 'Pinot Noir',
18
+ 'Primitivo',
19
+ 'Prosecco',
20
+ 'Riesling',
21
+ 'Rioja',
22
+ 'Rosé',
23
+ 'Sauvignon Blanc',
24
+ 'Syrah',
25
+ 'Zinfandel',
26
+ ];
27
+
28
+ export default () => {
29
+ const [wineList, setWineList] = React.useState(initialWineList);
30
+ // Tracking the input value for onSubmit
31
+ const [searchInput, setSearchInput] = React.useState('');
32
+ const menuItems = wineList.map(wine => <MenuItem key={wine}>{wine}</MenuItem>);
33
+
34
+ const filterMenuItems = e => {
35
+ setSearchInput(e.target.value);
36
+ const formattedValue = e.target.value.toLowerCase();
37
+
38
+ // Reset the list if the input is cleared
39
+ if (!formattedValue.length) {
40
+ setWineList(initialWineList);
41
+ } else {
42
+ const filteredItems = wineList.filter(wine => wine.toLowerCase().startsWith(formattedValue));
43
+ setWineList(filteredItems);
44
+ }
45
+ };
46
+
47
+ const handleSubmit = () => {
48
+ // We don't need to prevent the default event because SearchForm handles that internally
49
+ console.log(`Searching for: ${searchInput}`);
50
+ };
51
+
52
+ return (
53
+ <Flex minHeight={200} alignItems="flex-start">
54
+ <Flex padding="xs" backgroundColor="blueberry500" flex={1} flexBasis="auto">
55
+ <SearchForm
56
+ searchTheme={SearchTheme.Dark}
57
+ autocompleteItems={menuItems}
58
+ onInputChange={filterMenuItems}
59
+ onSubmit={handleSubmit}
60
+ />
61
+ </Flex>
62
+ </Flex>
63
+ );
64
+ };
@@ -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
+ };
@@ -3,7 +3,6 @@ import {Menu, MenuItem} from '@workday/canvas-kit-preview-react/menu';
3
3
 
4
4
  import Basic from './examples/Basic';
5
5
  import ContextMenu from './examples/ContextMenu';
6
- import ControlButton from './examples/ControlButton';
7
6
  import CustomMenuItem from './examples/CustomMenuItem';
8
7
  import Icons from './examples/Icons';
9
8
  import ManyItems from './examples/ManyItems';
@@ -11,7 +10,7 @@ import ManyItems from './examples/ManyItems';
11
10
 
12
11
  # Canvas Kit Menu
13
12
 
14
- Menus display a list of options when triggered by an action or UI element like an icon or button.
13
+ `Menu` displays a list of options when triggered by an action or UI element like an icon or button.
15
14
 
16
15
  [> Workday Design Reference](https://design.workday.com/components/popups/menus)
17
16
 
@@ -25,8 +24,15 @@ yarn add @workday/canvas-kit-preview-react
25
24
 
26
25
  ### Basic Example
27
26
 
27
+ `Menu` is typically triggered by an action such as pressing a button. Here's an example of how you
28
+ might implement that behavior using a [`Popup`](/components/popups/popup/).
29
+
28
30
  <ExampleCodeBlock code={Basic} />
29
31
 
32
+ `Menu` will automatically assign focus to itself when it appears provided you set the `isOpen` prop
33
+ correctly, so you do **not** need to use the `useInitialFocus` `Popup` hook. You **will**, however,
34
+ need to use `useReturnFocus` to return focus back to the triggering button after closing the `Menu`.
35
+
30
36
  `Menu` follows the
31
37
  [Actions Menu pattern](https://www.w3.org/TR/wai-aria-practices/examples/menu-button/menu-button-actions-active-descendant.html)
32
38
  using `aria-activedescendant`. Below is table of supported keyboard shortcuts and associated
@@ -42,10 +48,8 @@ actions.
42
48
  | `End` | Moves focus to the last menu item |
43
49
  | `A-Z / a-z` | Moves focus to the next menu item with a label that starts with the typed character if such an menu item exists – otherwise, focus does not move |
44
50
 
45
- If you're using a menu button, you will need to add your own keyboard shortcuts, aria attributes,
46
- and focus management. See the example below.
47
-
48
- <ExampleCodeBlock code={ControlButton} />
51
+ Note that although `Menu` includes support for keyboard shortcuts for the menu itself, you'll need
52
+ to add your own keyboard handling and aria attributes to the triggering button.
49
53
 
50
54
  ### Context Menu
51
55
 
@@ -59,7 +63,6 @@ custom menu items, be sure to use semantic `<li>` elements with the following at
59
63
 
60
64
  - `role="menuitem"`
61
65
  - `tabindex={-1}`
62
- - `id`s following this pattern: `${MenuId}-${index}`
63
66
 
64
67
  Below is an example:
65
68
 
@@ -79,19 +82,22 @@ Below is an example:
79
82
 
80
83
  #### Usage
81
84
 
82
- `Menu` renders a styled `<ul>` element with a role of `menu` and follows the
85
+ `Menu` renders a styled `<ul role="menu">` element within a [`Card`](/components/containers/card/)
86
+ and follows the
83
87
  [Active Menu pattern](https://www.w3.org/TR/wai-aria-practices/examples/menu-button/menu-button-actions-active-descendant.html)
84
88
  using `aria-activedescendant`.
85
89
 
86
90
  #### Props
87
91
 
92
+ Undocumented props are spread to the underlying `<ul>` element.
93
+
88
94
  <ArgsTable of={Menu} />
89
95
 
90
96
  ### MenuItem
91
97
 
92
98
  #### Usage
93
99
 
94
- `MenuItem` renders a `<li>` element with the correct attributes to ensure it is accessible. If you
100
+ `MenuItem` renders an `<li>` element with the correct attributes to ensure it is accessible. If you
95
101
  choose to implement your own custom menu items, be sure to use semantic `<li>` elements with the
96
102
  following attributes:
97
103
 
@@ -101,6 +107,8 @@ following attributes:
101
107
 
102
108
  #### Props
103
109
 
110
+ Undocumented props are spread to the underlying `<li>` element.
111
+
104
112
  <ArgsTable of={MenuItem} />
105
113
 
106
114
  ## Specifications
@@ -1,17 +1,72 @@
1
1
  import React from 'react';
2
-
3
2
  import {Menu, MenuItem} from '@workday/canvas-kit-preview-react/menu';
3
+ import {SecondaryButton} from '@workday/canvas-kit-react/button';
4
+ import {
5
+ Popup,
6
+ usePopupModel,
7
+ useAlwaysCloseOnOutsideClick,
8
+ useReturnFocus,
9
+ useCloseOnEscape,
10
+ } from '@workday/canvas-kit-react/popup';
11
+
12
+ const menuId = 'basic-menu';
4
13
 
5
14
  export default () => {
15
+ const model = usePopupModel();
16
+
17
+ useAlwaysCloseOnOutsideClick(model);
18
+ useCloseOnEscape(model);
19
+ useReturnFocus(model);
20
+
21
+ const isOpen = model.state.visibility !== 'hidden';
22
+
23
+ const handleButtonKeyDown = (event: React.KeyboardEvent) => {
24
+ let isShortcut = false;
25
+ if (event.key === `Spacebar` || event.key === ` ` || event.key === `Enter`) {
26
+ isShortcut = true;
27
+ if (isOpen) {
28
+ model.events.hide();
29
+ } else {
30
+ model.events.show();
31
+ }
32
+ } else if (event.key === `ArrowDown` || event.key === `ArrowUp`) {
33
+ isShortcut = true;
34
+ model.events.show();
35
+ }
36
+
37
+ if (isShortcut) {
38
+ // Prevent ArrowDown and ArrowUp keys from scrolling the entire page
39
+ event.preventDefault();
40
+ }
41
+ };
42
+
6
43
  return (
7
- <Menu title="Menu Title">
8
- <MenuItem>First Item</MenuItem>
9
- <MenuItem>Second Item (with a really really really long label)</MenuItem>
10
- <MenuItem isDisabled>Third Item (disabled)</MenuItem>
11
- <MenuItem>
12
- Fourth Item (<b>with markup</b>)
13
- </MenuItem>
14
- <MenuItem hasDivider>Fifth Item (with divider)</MenuItem>
15
- </Menu>
44
+ <Popup model={model}>
45
+ <Popup.Target
46
+ as={SecondaryButton}
47
+ onKeyDown={handleButtonKeyDown}
48
+ aria-expanded={isOpen}
49
+ aria-haspopup={true}
50
+ aria-controls={isOpen ? menuId : undefined}
51
+ >
52
+ Open Menu
53
+ </Popup.Target>
54
+ <Popup.Popper placement="bottom-start">
55
+ {/*
56
+ isOpen must be set for focus to be properly assigned to the Menu;
57
+ onClose must be set in order to the Menu to close properly after
58
+ selecting a MenuItem
59
+ */}
60
+ <Menu id={menuId} isOpen={isOpen} onClose={model.events.hide}>
61
+ <MenuItem>First Item</MenuItem>
62
+ <MenuItem>Second Item (with a really really really long label)</MenuItem>
63
+ <MenuItem isDisabled>Third Item (disabled)</MenuItem>
64
+ <MenuItem>
65
+ Fourth Item (<b>with markup</b>)
66
+ </MenuItem>
67
+ <MenuItem hasDivider>Fifth Item (with divider)</MenuItem>
68
+ </Menu>
69
+ </Popup.Popper>
70
+ </Popup>
16
71
  );
17
72
  };
@@ -1,49 +1,67 @@
1
1
  import * as React from 'react';
2
2
 
3
- import {CanvasProvider, ContentDirection} from '@workday/canvas-kit-react/common';
3
+ import {createComponent, useForkRef} from '@workday/canvas-kit-react/common';
4
4
  import {Menu, MenuItem} from '@workday/canvas-kit-preview-react/menu';
5
5
  import {
6
6
  Popup,
7
+ PopupModelContext,
7
8
  usePopupModel,
8
9
  useAlwaysCloseOnOutsideClick,
9
10
  useCloseOnEscape,
11
+ useTransferOnFullscreenExit,
10
12
  } from '@workday/canvas-kit-react/popup';
11
13
 
12
- import {ContextMenuTarget} from './ContextMenuTarget';
14
+ const ContextMenuTarget = createComponent('div')({
15
+ displayName: 'Popup.ContextMenuTarget',
16
+ Component: ({children, ...elemProps}, ref, Element) => {
17
+ const model = React.useContext(PopupModelContext);
18
+ const elementRef = useForkRef(ref, model.state.targetRef as any);
13
19
 
14
- export default () => {
15
- const canvasTheme = {
16
- canvas: {
17
- direction: ContentDirection.LTR,
18
- },
19
- };
20
+ const onContextMenu = (event: React.MouseEvent) => {
21
+ if (model.state.visibility === 'visible') {
22
+ model.events.hide({event});
23
+ } else if (model.state.visibility === 'hidden') {
24
+ model.events.show({event});
25
+ }
26
+
27
+ // Prevent the default context menu from showing to avoid double menus
28
+ event.preventDefault();
29
+ };
20
30
 
31
+ return (
32
+ <Element ref={elementRef} onContextMenu={onContextMenu} {...elemProps}>
33
+ {children}
34
+ </Element>
35
+ );
36
+ },
37
+ });
38
+
39
+ export default () => {
21
40
  const model = usePopupModel();
22
41
 
23
42
  useAlwaysCloseOnOutsideClick(model);
24
43
  useCloseOnEscape(model);
44
+ useTransferOnFullscreenExit(model);
25
45
 
26
46
  return (
27
- <CanvasProvider theme={canvasTheme}>
28
- <Popup model={model}>
29
- <ContextMenuTarget style={{display: 'inline'}} tabIndex={0}>
30
- Right click on this text (Context menu target)
31
- </ContextMenuTarget>
32
- <Popup.Popper>
33
- <Menu onClose={model.events.hide}>
34
- <MenuItem>Back</MenuItem>
35
- <MenuItem>Forward</MenuItem>
36
- <MenuItem>Reload</MenuItem>
37
- <MenuItem hasDivider>Bookmark Page</MenuItem>
38
- <MenuItem>Save Page As...</MenuItem>
39
- <MenuItem>Select All</MenuItem>
40
- <MenuItem hasDivider>Take Screenshot</MenuItem>
41
- <MenuItem hasDivider>View Page Source</MenuItem>
42
- <MenuItem>Inspect Accessibility Properties</MenuItem>
43
- <MenuItem>Inspect</MenuItem>
44
- </Menu>
45
- </Popup.Popper>
46
- </Popup>
47
- </CanvasProvider>
47
+ <Popup model={model}>
48
+ <ContextMenuTarget style={{display: 'inline'}} tabIndex={0}>
49
+ Right click on this text (Context menu target)
50
+ </ContextMenuTarget>
51
+ <Popup.Popper>
52
+ <Menu onClose={model.events.hide}>
53
+ <MenuItem>Back</MenuItem>
54
+ <MenuItem>Forward</MenuItem>
55
+ <MenuItem>Reload</MenuItem>
56
+ <MenuItem hasDivider>Bookmark Page</MenuItem>
57
+ <MenuItem>Save Page As...</MenuItem>
58
+ <MenuItem>Select All</MenuItem>
59
+ <MenuItem hasDivider>Take Screenshot</MenuItem>
60
+ <MenuItem hasDivider>View Page Source</MenuItem>
61
+ <MenuItem>Inspect Accessibility Properties</MenuItem>
62
+ <MenuItem>Inspect</MenuItem>
63
+ </Menu>
64
+ </Popup.Popper>
65
+ </Popup>
48
66
  );
49
67
  };
@@ -4,10 +4,10 @@ import {Menu, MenuItem} from '@workday/canvas-kit-preview-react/menu';
4
4
 
5
5
  export default () => {
6
6
  return (
7
- <Menu title="Menu Title">
7
+ <Menu>
8
8
  <MenuItem>First Item</MenuItem>
9
9
  <MenuItem>Second Item</MenuItem>
10
- <li role="menuItem" id="customMenu-3" tabIndex={-1} style={{listStyle: 'none'}}>
10
+ <li role="menuitem" tabIndex={-1} style={{listStyle: 'none'}}>
11
11
  Third Item (custom)
12
12
  </li>
13
13
  </Menu>
@@ -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,11 +4,11 @@ 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 => {
11
- return <MenuItem>Item {item}</MenuItem>;
11
+ return <MenuItem key={item}>Item {item}</MenuItem>;
12
12
  })}
13
13
  </Menu>
14
14
  );