@workday/canvas-kit-docs 5.3.0-next.2 → 5.3.0-next.24
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/LICENSE +1 -1
- package/dist/commonjs/lib/specs.js +428 -32
- package/dist/es6/lib/specs.js +428 -32
- package/dist/mdx/6.0-MIGRATION-GUIDE.mdx +560 -0
- package/dist/mdx/COMPOUND_COMPONENTS.mdx +31 -30
- package/dist/mdx/CONTRIBUTING.mdx +90 -63
- package/dist/mdx/labs-react/search-form/SearchForm.mdx +64 -0
- package/dist/mdx/labs-react/search-form/examples/Basic.tsx +61 -0
- package/dist/mdx/labs-react/search-form/examples/CustomTheme.tsx +72 -0
- package/dist/mdx/labs-react/search-form/examples/Grow.tsx +62 -0
- package/dist/mdx/labs-react/search-form/examples/PropTables.splitProps.tsx +4 -0
- package/dist/mdx/labs-react/search-form/examples/RTL.tsx +70 -0
- package/dist/mdx/labs-react/search-form/examples/Theming.tsx +64 -0
- package/dist/mdx/preview-react/breadcrumbs/Breadcrumbs.mdx +1 -1
- package/dist/mdx/preview-react/form-field/FormField.mdx +27 -0
- package/dist/mdx/preview-react/form-field/examples/Custom.tsx +57 -0
- package/dist/mdx/preview-react/menu/Menu.mdx +17 -9
- package/dist/mdx/preview-react/menu/examples/Basic.tsx +65 -10
- package/dist/mdx/preview-react/menu/examples/ContextMenu.tsx +45 -29
- package/dist/mdx/preview-react/menu/examples/CustomMenuItem.tsx +2 -2
- package/dist/mdx/preview-react/menu/examples/Icons.tsx +1 -1
- package/dist/mdx/preview-react/menu/examples/ManyItems.tsx +2 -2
- package/dist/mdx/preview-react/text-area/TextArea.mdx +122 -0
- package/dist/mdx/preview-react/text-area/examples/Alert.tsx +31 -0
- package/dist/mdx/preview-react/text-area/examples/Basic.tsx +17 -0
- package/dist/mdx/preview-react/text-area/examples/Disabled.tsx +17 -0
- package/dist/mdx/preview-react/text-area/examples/Error.tsx +40 -0
- package/dist/mdx/preview-react/text-area/examples/Grow.tsx +17 -0
- package/dist/mdx/preview-react/text-area/examples/HiddenLabel.tsx +20 -0
- package/dist/mdx/preview-react/text-area/examples/LabelPositionHorizontal.tsx +17 -0
- package/dist/mdx/preview-react/text-area/examples/LabelPositionVertical.tsx +17 -0
- package/dist/mdx/preview-react/text-area/examples/Placeholder.tsx +21 -0
- package/dist/mdx/preview-react/text-area/examples/RefForwarding.tsx +28 -0
- package/dist/mdx/preview-react/text-area/examples/Required.tsx +17 -0
- package/dist/mdx/preview-react/text-area/examples/ResizeConstraints.tsx +22 -0
- package/dist/mdx/preview-react/text-input/TextInput.mdx +145 -0
- package/dist/mdx/preview-react/text-input/examples/Alert.tsx +40 -0
- package/dist/mdx/preview-react/text-input/examples/Basic.tsx +17 -0
- package/dist/mdx/preview-react/text-input/examples/Disabled.tsx +17 -0
- package/dist/mdx/preview-react/text-input/examples/Error.tsx +40 -0
- package/dist/mdx/preview-react/text-input/examples/Grow.tsx +17 -0
- package/dist/mdx/preview-react/text-input/examples/HiddenLabel.tsx +20 -0
- package/dist/mdx/preview-react/text-input/examples/LabelPositionHorizontal.tsx +17 -0
- package/dist/mdx/preview-react/text-input/examples/LabelPositionVertical.tsx +17 -0
- package/dist/mdx/preview-react/text-input/examples/LoginForm.tsx +105 -0
- package/dist/mdx/preview-react/text-input/examples/Password.tsx +17 -0
- package/dist/mdx/preview-react/text-input/examples/Placeholder.tsx +17 -0
- package/dist/mdx/preview-react/text-input/examples/RefForwarding.tsx +28 -0
- package/dist/mdx/preview-react/text-input/examples/Required.tsx +17 -0
- package/dist/mdx/preview-react/text-input/examples/ThemedAlert.tsx +46 -0
- package/dist/mdx/preview-react/text-input/examples/ThemedError.tsx +37 -0
- package/dist/mdx/react/_examples/GlobalHeader.mdx +9 -0
- package/dist/mdx/react/_examples/PageHeader.mdx +8 -0
- package/dist/mdx/react/_examples/examples/GlobalHeader.tsx +66 -0
- package/dist/mdx/react/_examples/examples/PageHeader.tsx +63 -0
- package/dist/mdx/react/action-bar/ActionBar.mdx +1 -1
- package/dist/mdx/react/button/button/Button.mdx +34 -9
- package/dist/mdx/react/button/button/examples/Primary.tsx +10 -1
- package/dist/mdx/react/button/button/examples/PrimaryInverse.tsx +14 -0
- package/dist/mdx/react/button/button/examples/Secondary.tsx +10 -1
- package/dist/mdx/react/button/button/examples/SecondaryInverse.tsx +14 -0
- package/dist/mdx/react/button/button/examples/Tertiary.tsx +10 -1
- package/dist/mdx/react/button/button/examples/TertiaryInverse.tsx +14 -0
- package/dist/mdx/react/button/icon-button/IconButton.mdx +1 -1
- package/dist/mdx/react/loading-animation/LoadingAnimation.mdx +5 -0
- package/dist/mdx/react/loading-animation/examples/RTL.tsx +16 -0
- package/dist/mdx/react/pagination/PropTables.splitprops.tsx +47 -0
- package/dist/mdx/react/pagination/examples/{StepControls.tsx → Basic.tsx} +1 -1
- package/dist/mdx/react/pagination/examples/GoToForm.tsx +1 -1
- package/dist/mdx/react/pagination/examples/HoistedModel.tsx +36 -22
- package/dist/mdx/react/pagination/examples/RTL.tsx +1 -1
- package/dist/mdx/react/pagination/pagination.mdx +225 -474
- package/dist/mdx/react/popup/Popup.mdx +34 -36
- package/dist/mdx/react/radio/examples/Alert.tsx +3 -3
- package/dist/mdx/react/radio/examples/Basic.tsx +3 -3
- package/dist/mdx/react/radio/examples/Disabled.tsx +3 -3
- package/dist/mdx/react/radio/examples/Error.tsx +3 -3
- package/dist/mdx/react/radio/examples/LabelPosition.tsx +3 -3
- package/dist/mdx/react/radio/examples/NoValue.tsx +3 -3
- package/dist/mdx/react/radio/examples/RefForwarding.tsx +3 -3
- package/dist/mdx/react/radio/examples/Required.tsx +3 -3
- package/dist/mdx/react/segmented-control/SegmentedControl.mdx +1 -1
- package/dist/mdx/react/tabs/Tabs.mdx +67 -36
- package/dist/mdx/react/tabs/examples/DisabledTab.tsx +1 -1
- package/dist/mdx/react/tabs/examples/DynamicTabs.tsx +41 -13
- package/dist/mdx/react/tabs/examples/HoistedModel.tsx +4 -4
- package/dist/mdx/react/tabs/examples/Icons.tsx +36 -0
- package/dist/mdx/react/tabs/examples/{NamedKeys.tsx → NamedTabs.tsx} +0 -0
- package/dist/mdx/react/tabs/examples/OverflowTabs.tsx +58 -0
- package/dist/mdx/react/tabs/examples/SinglePanel.tsx +1 -1
- package/dist/mdx/react/text-area/TextArea.mdx +1 -1
- package/dist/mdx/react/toast/toast.mdx +1 -17
- package/dist/mdx/react/tooltip/Tooltip.mdx +9 -1
- package/dist/mdx/react/tooltip/examples/DelayedTooltip.tsx +16 -0
- package/dist/mdx/react/tooltip/examples/Ellipsis.tsx +6 -0
- package/package.json +5 -4
- package/dist/mdx/CODE_OF_CONDUCT.md +0 -68
- package/dist/mdx/preview-react/menu/examples/ContextMenuTarget.tsx +0 -33
- package/dist/mdx/preview-react/menu/examples/ControlButton.tsx +0 -84
- package/dist/mdx/react/pagination/examples/ShowAdditionalDetails.tsx +0 -52
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
46
|
-
and
|
|
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
|
|
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
|
|
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
|
-
<
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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,65 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
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,
|
|
10
11
|
} from '@workday/canvas-kit-react/popup';
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
const ContextMenuTarget = createComponent('div')({
|
|
14
|
+
displayName: 'Popup.ContextMenuTarget',
|
|
15
|
+
Component: ({children, ...elemProps}, ref, Element) => {
|
|
16
|
+
const model = React.useContext(PopupModelContext);
|
|
17
|
+
const elementRef = useForkRef(ref, model.state.targetRef as any);
|
|
13
18
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
const onContextMenu = (event: React.MouseEvent) => {
|
|
20
|
+
if (model.state.visibility === 'visible') {
|
|
21
|
+
model.events.hide({event});
|
|
22
|
+
} else if (model.state.visibility === 'hidden') {
|
|
23
|
+
model.events.show({event});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Prevent the default context menu from showing to avoid double menus
|
|
27
|
+
event.preventDefault();
|
|
28
|
+
};
|
|
20
29
|
|
|
30
|
+
return (
|
|
31
|
+
<Element ref={elementRef} onContextMenu={onContextMenu} {...elemProps}>
|
|
32
|
+
{children}
|
|
33
|
+
</Element>
|
|
34
|
+
);
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export default () => {
|
|
21
39
|
const model = usePopupModel();
|
|
22
40
|
|
|
23
41
|
useAlwaysCloseOnOutsideClick(model);
|
|
24
42
|
useCloseOnEscape(model);
|
|
25
43
|
|
|
26
44
|
return (
|
|
27
|
-
<
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
</Popup>
|
|
47
|
-
</CanvasProvider>
|
|
45
|
+
<Popup model={model}>
|
|
46
|
+
<ContextMenuTarget style={{display: 'inline'}} tabIndex={0}>
|
|
47
|
+
Right click on this text (Context menu target)
|
|
48
|
+
</ContextMenuTarget>
|
|
49
|
+
<Popup.Popper>
|
|
50
|
+
<Menu onClose={model.events.hide}>
|
|
51
|
+
<MenuItem>Back</MenuItem>
|
|
52
|
+
<MenuItem>Forward</MenuItem>
|
|
53
|
+
<MenuItem>Reload</MenuItem>
|
|
54
|
+
<MenuItem hasDivider>Bookmark Page</MenuItem>
|
|
55
|
+
<MenuItem>Save Page As...</MenuItem>
|
|
56
|
+
<MenuItem>Select All</MenuItem>
|
|
57
|
+
<MenuItem hasDivider>Take Screenshot</MenuItem>
|
|
58
|
+
<MenuItem hasDivider>View Page Source</MenuItem>
|
|
59
|
+
<MenuItem>Inspect Accessibility Properties</MenuItem>
|
|
60
|
+
<MenuItem>Inspect</MenuItem>
|
|
61
|
+
</Menu>
|
|
62
|
+
</Popup.Popper>
|
|
63
|
+
</Popup>
|
|
48
64
|
);
|
|
49
65
|
};
|
|
@@ -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
|
|
7
|
+
<Menu>
|
|
8
8
|
<MenuItem>First Item</MenuItem>
|
|
9
9
|
<MenuItem>Second Item</MenuItem>
|
|
10
|
-
<li role="
|
|
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
|
|
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
|
|
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
|
);
|
|
@@ -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" />
|