@workday/canvas-kit-docs 5.3.17 → 5.4.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commonjs/lib/specs.js +429 -19
- package/dist/es6/lib/specs.js +429 -19
- package/dist/mdx/6.0-MIGRATION-GUIDE.mdx +567 -0
- package/dist/mdx/COMPOUND_COMPONENTS.mdx +31 -30
- package/dist/mdx/TESTING.mdx +30 -6
- package/dist/mdx/changelog.stories.mdx +0 -1
- package/dist/mdx/labs-react/layout/Stack.mdx +7 -2
- package/dist/mdx/labs-react/search-form/SearchForm.mdx +62 -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/_examples/SelectWithFormik.mdx +8 -0
- package/dist/mdx/preview-react/_examples/TextInputWithFormik.mdx +8 -0
- package/dist/mdx/preview-react/_examples/examples/SelectWithFormik.tsx +47 -0
- package/dist/mdx/preview-react/_examples/examples/TextInputWithFormik.tsx +105 -0
- package/dist/mdx/preview-react/form-field/FormField.mdx +39 -0
- package/dist/mdx/preview-react/form-field/examples/Custom.tsx +57 -0
- package/dist/mdx/preview-react/form-field/examples/Select.tsx +50 -0
- package/dist/mdx/preview-react/side-panel/examples/AlwaysOpen.tsx +1 -1
- package/dist/mdx/preview-react/side-panel/examples/Basic.tsx +1 -1
- package/dist/mdx/preview-react/side-panel/examples/ExternalControl.tsx +1 -1
- package/dist/mdx/preview-react/side-panel/examples/RightOrigin.tsx +1 -1
- package/dist/mdx/preview-react/side-panel/examples/Variant.tsx +1 -1
- package/dist/mdx/preview-react/text-area/TextArea.mdx +122 -0
- package/dist/mdx/preview-react/text-area/examples/Alert.tsx +36 -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 +17 -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 +138 -0
- package/dist/mdx/preview-react/text-input/examples/Alert.tsx +35 -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/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 +35 -0
- package/dist/mdx/react/_examples/CookieBanner.mdx +8 -0
- package/dist/mdx/react/_examples/GlobalHeader.mdx +12 -0
- package/dist/mdx/react/_examples/PageHeader.mdx +8 -0
- package/dist/mdx/react/_examples/examples/CookieBanner.tsx +97 -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/button/button/Button.mdx +26 -2
- 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 +13 -1
- package/dist/mdx/react/button/button/examples/TertiaryInverse.tsx +14 -0
- package/dist/mdx/react/popup/examples/FocusRedirect.tsx +2 -1
- package/dist/mdx/react/tabs/Tabs.mdx +31 -5
- package/dist/mdx/react/tabs/examples/DisabledTab.tsx +1 -1
- package/dist/mdx/react/tabs/examples/DynamicTabs.tsx +82 -38
- 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/package.json +3 -3
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import {useFormik} from 'formik';
|
|
3
|
+
import {Select} from '@workday/canvas-kit-preview-react/select';
|
|
4
|
+
import {
|
|
5
|
+
FormField,
|
|
6
|
+
useFormFieldInput,
|
|
7
|
+
useFormFieldModel,
|
|
8
|
+
} from '@workday/canvas-kit-preview-react/form-field';
|
|
9
|
+
|
|
10
|
+
export default () => {
|
|
11
|
+
const formik = useFormik({
|
|
12
|
+
initialValues: {
|
|
13
|
+
selectedBook: '',
|
|
14
|
+
},
|
|
15
|
+
onSubmit: data => {
|
|
16
|
+
console.log(data);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const model = useFormFieldModel();
|
|
21
|
+
const formFieldInputProps = useFormFieldInput(model);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<form onSubmit={formik.handleSubmit}>
|
|
25
|
+
<FormField orientation="vertical" alignItems="stretch">
|
|
26
|
+
<FormField.Label>Choose a book</FormField.Label>
|
|
27
|
+
<Select
|
|
28
|
+
name="selectedBook"
|
|
29
|
+
options={bookList}
|
|
30
|
+
onChange={event => formik.setFieldValue('selectedBook', event.currentTarget.value)}
|
|
31
|
+
value={formik.values.selectedBook}
|
|
32
|
+
grow
|
|
33
|
+
{...formFieldInputProps}
|
|
34
|
+
/>
|
|
35
|
+
</FormField>
|
|
36
|
+
</form>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const bookList = [
|
|
41
|
+
{label: 'Dessert Person by Claire Saffitz', value: 'dessert person'},
|
|
42
|
+
{label: 'Elements of Pizza by Ken Forkish', value: 'the elements of pizza'},
|
|
43
|
+
{label: 'Flour Water Salt Yeast by Ken Forkish', value: 'flour water salt yeast'},
|
|
44
|
+
{label: 'Mastering Pasta by Marc Verti', value: 'mastering pasta'},
|
|
45
|
+
{label: 'Patisserie by Christophe Felder', value: 'patisserie'},
|
|
46
|
+
{label: 'Tartine by Elisabeth Prueitt & Chad Robertson', value: 'tartine'},
|
|
47
|
+
];
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {useFormik} from 'formik';
|
|
4
|
+
import * as yup from 'yup';
|
|
5
|
+
|
|
6
|
+
import {TextInput} from '@workday/canvas-kit-preview-react/text-input';
|
|
7
|
+
import {HStack, VStack} from '@workday/canvas-kit-labs-react/layout';
|
|
8
|
+
import {IconButton, PrimaryButton} from '@workday/canvas-kit-react/button';
|
|
9
|
+
import {visibleIcon, invisibleIcon} from '@workday/canvas-system-icons-web';
|
|
10
|
+
import {useUniqueId} from '@workday/canvas-kit-react/common';
|
|
11
|
+
|
|
12
|
+
export default () => {
|
|
13
|
+
const passwordMinimum = 8;
|
|
14
|
+
const passwordHint = `Password should be of minimum ${passwordMinimum} characters length`;
|
|
15
|
+
const emailRequired = 'Email is required';
|
|
16
|
+
const passwordRequired = 'Password is required';
|
|
17
|
+
|
|
18
|
+
const validationSchema = yup.object({
|
|
19
|
+
email: yup
|
|
20
|
+
.string()
|
|
21
|
+
.email('Enter a valid email')
|
|
22
|
+
.required(emailRequired),
|
|
23
|
+
password: yup
|
|
24
|
+
.string()
|
|
25
|
+
.min(passwordMinimum, passwordHint)
|
|
26
|
+
.required(passwordRequired),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const passwordRef = React.useRef<HTMLInputElement>(null);
|
|
30
|
+
const [showPassword, setShowPassword] = React.useState(false);
|
|
31
|
+
const passwordId = useUniqueId();
|
|
32
|
+
|
|
33
|
+
const formik = useFormik({
|
|
34
|
+
initialValues: {
|
|
35
|
+
email: 'example@baz.com',
|
|
36
|
+
password: 'foobarbaz',
|
|
37
|
+
},
|
|
38
|
+
validationSchema: validationSchema,
|
|
39
|
+
onSubmit: values => {
|
|
40
|
+
passwordRef.current.type = 'password';
|
|
41
|
+
|
|
42
|
+
// Send data to server
|
|
43
|
+
setTimeout(() => {
|
|
44
|
+
alert(JSON.stringify(values, null, 2));
|
|
45
|
+
}, 0);
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<form onSubmit={formik.handleSubmit} action=".">
|
|
51
|
+
<VStack spacing="xs" alignItems="flex-start">
|
|
52
|
+
<TextInput
|
|
53
|
+
orientation="vertical"
|
|
54
|
+
isRequired={true}
|
|
55
|
+
hasError={formik.touched.email && !!formik.errors.email}
|
|
56
|
+
>
|
|
57
|
+
<TextInput.Label>Email</TextInput.Label>
|
|
58
|
+
<TextInput.Field
|
|
59
|
+
name="email"
|
|
60
|
+
autoComplete="username"
|
|
61
|
+
placeholder="yourName@example.com"
|
|
62
|
+
onChange={formik.handleChange}
|
|
63
|
+
onBlur={formik.handleBlur}
|
|
64
|
+
value={formik.values.email}
|
|
65
|
+
/>
|
|
66
|
+
<TextInput.Hint>{formik.touched.email && formik.errors.email}</TextInput.Hint>
|
|
67
|
+
</TextInput>
|
|
68
|
+
<TextInput
|
|
69
|
+
orientation="vertical"
|
|
70
|
+
id={passwordId}
|
|
71
|
+
hasError={formik.touched.password && !!formik.errors.password}
|
|
72
|
+
isRequired={true}
|
|
73
|
+
>
|
|
74
|
+
<TextInput.Label>Password</TextInput.Label>
|
|
75
|
+
<HStack spacing="xxs">
|
|
76
|
+
<TextInput.Field
|
|
77
|
+
type={showPassword ? 'text' : 'password'}
|
|
78
|
+
name="password"
|
|
79
|
+
autoComplete="current-password"
|
|
80
|
+
ref={passwordRef}
|
|
81
|
+
onChange={formik.handleChange}
|
|
82
|
+
onBlur={formik.handleBlur}
|
|
83
|
+
value={formik.values.password}
|
|
84
|
+
/>
|
|
85
|
+
<IconButton
|
|
86
|
+
type="button"
|
|
87
|
+
icon={showPassword ? invisibleIcon : visibleIcon}
|
|
88
|
+
aria-label={showPassword ? 'Hide Password' : 'Show Password'}
|
|
89
|
+
aria-controls={`input-${passwordId}`}
|
|
90
|
+
onClick={() => {
|
|
91
|
+
setShowPassword(state => !state);
|
|
92
|
+
passwordRef.current.focus();
|
|
93
|
+
}}
|
|
94
|
+
/>
|
|
95
|
+
</HStack>
|
|
96
|
+
<TextInput.Hint>
|
|
97
|
+
{(formik.touched.password && formik.errors.password) || passwordHint}
|
|
98
|
+
</TextInput.Hint>
|
|
99
|
+
</TextInput>
|
|
100
|
+
|
|
101
|
+
<PrimaryButton type="submit">Submit</PrimaryButton>
|
|
102
|
+
</VStack>
|
|
103
|
+
</form>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
import WithSelect from './examples/Select';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Canvas Kit Form Field
|
|
10
|
+
|
|
11
|
+
FormField allows users to wrap input components to make them accessible. You usually won't want to
|
|
12
|
+
use FormField directly but instead should use the specific component you need, e.g. `TextInput`.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
yarn add @workday/canvas-kit-preview-react
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Customizing With Behavior Hooks Example
|
|
23
|
+
|
|
24
|
+
If you need full customization you can use the `FormField` behavior hooks to build your own
|
|
25
|
+
solution. It is also easy it work with custom components or third party libraries and get the CKR
|
|
26
|
+
accessibility guarantees by using the `as` prop.
|
|
27
|
+
|
|
28
|
+
<ExampleCodeBlock code={Custom} />
|
|
29
|
+
|
|
30
|
+
### Use with Select
|
|
31
|
+
|
|
32
|
+
For some custom inputs, such as Canvas Kit's `Select`, you won't be able to reliably cast the
|
|
33
|
+
`FormField.Input` with the `as` prop. Instead you'll want to use `FormField`'s hooks for the
|
|
34
|
+
implementation. In the example below, we're using the `useFormFieldModel` hook to hoist the model
|
|
35
|
+
and providing it to the `useFormFieldInput` behavior hook. Then we pass the model to the `FormField`
|
|
36
|
+
component and the input props to `Select`. This connects `Select` to the `FormField` components and
|
|
37
|
+
provides it with all the accessible attributes it needs.
|
|
38
|
+
|
|
39
|
+
<ExampleCodeBlock code={WithSelect} />
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
FormField,
|
|
4
|
+
useFormFieldInput,
|
|
5
|
+
useFormFieldModel,
|
|
6
|
+
} from '@workday/canvas-kit-preview-react/form-field';
|
|
7
|
+
import {Select} from '@workday/canvas-kit-preview-react/select';
|
|
8
|
+
|
|
9
|
+
export default () => {
|
|
10
|
+
const [selected, setSelected] = React.useState(wineList[0].value);
|
|
11
|
+
// Hoist the FormField model so we can pass it to `useFormFieldInput`
|
|
12
|
+
const model = useFormFieldModel({isRequired: true});
|
|
13
|
+
// Get all the FormField-related input props to pass to `Select`
|
|
14
|
+
const formFieldInputProps = useFormFieldInput(model);
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<FormField orientation="vertical" model={model}>
|
|
18
|
+
<FormField.Label>Choose a wine</FormField.Label>
|
|
19
|
+
<Select
|
|
20
|
+
options={wineList}
|
|
21
|
+
value={selected}
|
|
22
|
+
onChange={event => setSelected(event.currentTarget.value)}
|
|
23
|
+
{...formFieldInputProps}
|
|
24
|
+
/>
|
|
25
|
+
<FormField.Hint>When in doubt, go with the Chianti.</FormField.Hint>
|
|
26
|
+
</FormField>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default [
|
|
31
|
+
{label: 'Beaujolais', value: 'beaujolais'},
|
|
32
|
+
{label: 'Bordeaux', value: 'bordeaux'},
|
|
33
|
+
{label: 'Cabernet Sauvignon', value: 'cabernet sauvignon'},
|
|
34
|
+
{label: 'Champagne', value: 'champagne'},
|
|
35
|
+
{label: 'Chardonnay', value: 'chardonnay'},
|
|
36
|
+
{label: 'Chianti', value: 'chianti'},
|
|
37
|
+
{label: 'Malbec', value: 'malbec'},
|
|
38
|
+
{label: 'Merlot', value: 'merlot'},
|
|
39
|
+
{label: 'Pinot Grigio', value: 'pinot grigio'},
|
|
40
|
+
{label: 'Pinot Gris', value: 'pinot gris'},
|
|
41
|
+
{label: 'Pinot Noir', value: 'pinot noir'},
|
|
42
|
+
{label: 'Primitivo', value: 'primitivo'},
|
|
43
|
+
{label: 'Prosecco', value: 'prosecco'},
|
|
44
|
+
{label: 'Riesling', value: 'riesling'},
|
|
45
|
+
{label: 'Rioja', value: 'rioja'},
|
|
46
|
+
{label: 'Rosé', value: 'rosé'},
|
|
47
|
+
{label: 'Sauvignon Blanc', value: 'sauvignon blanc'},
|
|
48
|
+
{label: 'Syrah', value: 'syrah'},
|
|
49
|
+
{label: 'Zinfandel', value: 'zinfandel'},
|
|
50
|
+
];
|
|
@@ -19,7 +19,7 @@ export default () => {
|
|
|
19
19
|
return (
|
|
20
20
|
<Flex height={320}>
|
|
21
21
|
<SidePanel {...panelProps}>
|
|
22
|
-
<Flex alignItems="center" paddingY="s" paddingX="
|
|
22
|
+
<Flex alignItems="center" paddingY="s" paddingX="s">
|
|
23
23
|
<AccentIcon css={iconStyles} icon={rocketIcon} />
|
|
24
24
|
<h3
|
|
25
25
|
css={{
|
|
@@ -28,7 +28,7 @@ export default () => {
|
|
|
28
28
|
<SidePanel {...panelProps} onStateTransition={setPanelState}>
|
|
29
29
|
<SidePanel.ToggleButton {...controlProps} />
|
|
30
30
|
{panelState === 'expanded' && (
|
|
31
|
-
<Flex alignItems="center" paddingY="s" paddingX="
|
|
31
|
+
<Flex alignItems="center" paddingY="s" paddingX="s">
|
|
32
32
|
<Flex marginInlineEnd="s">
|
|
33
33
|
<AccentIcon icon={rocketIcon} />
|
|
34
34
|
</Flex>
|
|
@@ -30,7 +30,7 @@ const RightPanel = () => {
|
|
|
30
30
|
<SidePanel {...panelProps} onStateTransition={setPanelState} origin="right" css={panelStyles}>
|
|
31
31
|
<SidePanel.ToggleButton {...controlProps} />
|
|
32
32
|
{panelState === 'expanded' && (
|
|
33
|
-
<Flex alignItems="center" justifyContent="flex-end" paddingY="s" paddingX="
|
|
33
|
+
<Flex alignItems="center" justifyContent="flex-end" paddingY="s" paddingX="s">
|
|
34
34
|
<h3
|
|
35
35
|
css={{
|
|
36
36
|
...type.levels.body.large,
|
|
@@ -26,7 +26,7 @@ export default () => {
|
|
|
26
26
|
<SidePanel {...panelProps} onStateTransition={setPanelState} variant="alternate">
|
|
27
27
|
<SidePanel.ToggleButton {...controlProps} />
|
|
28
28
|
{panelState === 'expanded' && (
|
|
29
|
-
<Flex alignItems="center" paddingY="s" paddingX="
|
|
29
|
+
<Flex alignItems="center" paddingY="s" paddingX="s">
|
|
30
30
|
<h3
|
|
31
31
|
css={{
|
|
32
32
|
...type.levels.body.large,
|
|
@@ -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" />
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import {jsx} from '@emotion/core';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import {TextArea} from '@workday/canvas-kit-preview-react/text-area';
|
|
5
|
+
import {useThemedRing} from '@workday/canvas-kit-labs-react/common';
|
|
6
|
+
import {space, colors} from '@workday/canvas-kit-react/tokens';
|
|
7
|
+
|
|
8
|
+
export default () => {
|
|
9
|
+
const [value, setValue] = React.useState('');
|
|
10
|
+
|
|
11
|
+
const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
12
|
+
setValue(event.target.value.slice(0, 10));
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const alertStyles = useThemedRing(
|
|
16
|
+
value.length < 3 ? 'success' : value.length < 7 ? 'alert' : 'error'
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const hintColor =
|
|
20
|
+
value.length < 3
|
|
21
|
+
? colors.greenApple600
|
|
22
|
+
: value.length < 7
|
|
23
|
+
? colors.cantaloupe600
|
|
24
|
+
: colors.cinnamon500;
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<TextArea orientation="vertical">
|
|
28
|
+
<TextArea.Label>Add a comment</TextArea.Label>
|
|
29
|
+
<TextArea.Field css={alertStyles} onChange={handleChange} value={value} />
|
|
30
|
+
<TextArea.Hint paddingTop={space.xxs}>
|
|
31
|
+
<strong>Character Limit: </strong>
|
|
32
|
+
<span css={{color: hintColor}}>{10 - value.length} Left</span>
|
|
33
|
+
</TextArea.Hint>
|
|
34
|
+
</TextArea>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {TextArea} from '@workday/canvas-kit-preview-react/text-area';
|
|
3
|
+
|
|
4
|
+
export default () => {
|
|
5
|
+
const [value, setValue] = React.useState('');
|
|
6
|
+
|
|
7
|
+
const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
8
|
+
setValue(event.target.value);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<TextArea orientation="vertical">
|
|
13
|
+
<TextArea.Label>Leave a review</TextArea.Label>
|
|
14
|
+
<TextArea.Field onChange={handleChange} value={value} />
|
|
15
|
+
</TextArea>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {TextArea} from '@workday/canvas-kit-preview-react/text-area';
|
|
3
|
+
|
|
4
|
+
export default () => {
|
|
5
|
+
const [value, setValue] = React.useState('');
|
|
6
|
+
|
|
7
|
+
const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
8
|
+
setValue(event.target.value);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<TextArea orientation="vertical">
|
|
13
|
+
<TextArea.Label>Leave a review</TextArea.Label>
|
|
14
|
+
<TextArea.Field disabled onChange={handleChange} value={value} />
|
|
15
|
+
</TextArea>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {TextArea} from '@workday/canvas-kit-preview-react/text-area';
|
|
3
|
+
import {space} from '@workday/canvas-kit-react/tokens';
|
|
4
|
+
|
|
5
|
+
export default () => {
|
|
6
|
+
const [value, setValue] = React.useState('four');
|
|
7
|
+
const [hint, setHint] = React.useState('');
|
|
8
|
+
const [hasError, setHasError] = React.useState(false);
|
|
9
|
+
|
|
10
|
+
const validateInput = (value: string) => {
|
|
11
|
+
const stringLength = value.length;
|
|
12
|
+
if (stringLength !== 3) {
|
|
13
|
+
setHasError(true);
|
|
14
|
+
const hintStart = 'Word length must be';
|
|
15
|
+
setHint(stringLength < 3 ? `${hintStart} greater than 2` : `${hintStart} less than 4`);
|
|
16
|
+
} else {
|
|
17
|
+
setHasError(false);
|
|
18
|
+
setHint('');
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
React.useEffect(() => {
|
|
23
|
+
validateInput(value);
|
|
24
|
+
// Only run on load
|
|
25
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
26
|
+
}, []);
|
|
27
|
+
|
|
28
|
+
const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
29
|
+
validateInput(event.target.value);
|
|
30
|
+
setValue(event.target.value);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<TextArea hasError={hasError} orientation="vertical">
|
|
35
|
+
<TextArea.Label>A three letter word</TextArea.Label>
|
|
36
|
+
<TextArea.Field onChange={handleChange} value={value} />
|
|
37
|
+
<TextArea.Hint paddingTop={space.xxs}>{hint}</TextArea.Hint>
|
|
38
|
+
</TextArea>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {TextArea} from '@workday/canvas-kit-preview-react/text-area';
|
|
3
|
+
|
|
4
|
+
export default () => {
|
|
5
|
+
const [value, setValue] = React.useState('');
|
|
6
|
+
|
|
7
|
+
const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
8
|
+
setValue(event.target.value);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<TextArea orientation="vertical" alignItems="stretch">
|
|
13
|
+
<TextArea.Label>Leave a review</TextArea.Label>
|
|
14
|
+
<TextArea.Field onChange={handleChange} value={value} />
|
|
15
|
+
</TextArea>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import {jsx} from '@emotion/core';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import {TextArea} from '@workday/canvas-kit-preview-react/text-area';
|
|
5
|
+
import {accessibleHide} from '@workday/canvas-kit-react/common';
|
|
6
|
+
|
|
7
|
+
export default () => {
|
|
8
|
+
const [value, setValue] = React.useState('');
|
|
9
|
+
|
|
10
|
+
const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
11
|
+
setValue(event.target.value);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<TextArea orientation="vertical" spacing="zero">
|
|
16
|
+
<TextArea.Label css={{...accessibleHide}}>Email</TextArea.Label>
|
|
17
|
+
<TextArea.Field onChange={handleChange} value={value} />
|
|
18
|
+
</TextArea>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {TextArea} from '@workday/canvas-kit-preview-react/text-area';
|
|
3
|
+
|
|
4
|
+
export default () => {
|
|
5
|
+
const [value, setValue] = React.useState('');
|
|
6
|
+
|
|
7
|
+
const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
8
|
+
setValue(event.target.value);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<TextArea orientation="horizontal">
|
|
13
|
+
<TextArea.Label>Leave a review</TextArea.Label>
|
|
14
|
+
<TextArea.Field onChange={handleChange} value={value} />
|
|
15
|
+
</TextArea>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {TextArea} from '@workday/canvas-kit-preview-react/text-area';
|
|
3
|
+
|
|
4
|
+
export default () => {
|
|
5
|
+
const [value, setValue] = React.useState('');
|
|
6
|
+
|
|
7
|
+
const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
8
|
+
setValue(event.target.value);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<TextArea orientation="vertical" spacing="xxxs">
|
|
13
|
+
<TextArea.Label>Leave a review</TextArea.Label>
|
|
14
|
+
<TextArea.Field onChange={handleChange} value={value} />
|
|
15
|
+
</TextArea>
|
|
16
|
+
);
|
|
17
|
+
};
|