@workday/canvas-kit-docs 11.1.0-833-next.0 → 11.1.0

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.
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import {AriaLiveRegion, changeFocus} from '@workday/canvas-kit-react/common';
3
+ import {FormField} from '@workday/canvas-kit-preview-react/form-field';
4
+ import {PrimaryButton} from '@workday/canvas-kit-react/button';
5
+ import {TextInput} from '@workday/canvas-kit-react/text-input';
6
+ import {system} from '@workday/canvas-tokens-web';
7
+ import {createStyles} from '@workday/canvas-kit-styling';
8
+
9
+ const hintStyles = createStyles({
10
+ height: system.space.x6,
11
+ });
12
+ export default () => {
13
+ const errMsg = 'Error: First name is required.';
14
+ const [hasError, setHasError] = React.useState('no');
15
+ const inputRef = React.useRef(null);
16
+ const handleBlur = e => setHasError(e.target.value.trim().length === 0 ? 'error' : 'no');
17
+ const handleSubmit = () => hasError && changeFocus(inputRef.current);
18
+
19
+ return (
20
+ <>
21
+ <FormField error={hasError === 'error' ? 'error' : undefined} isRequired={true}>
22
+ <FormField.Label>First Name:</FormField.Label>
23
+ <FormField.Input as={TextInput} onBlur={handleBlur} ref={inputRef} />
24
+ <FormField.Hint cs={hintStyles}>
25
+ <AriaLiveRegion>{hasError === 'error' && errMsg}</AriaLiveRegion>
26
+ </FormField.Hint>
27
+ </FormField>
28
+ <PrimaryButton onClick={handleSubmit}>Continue</PrimaryButton>
29
+ </>
30
+ );
31
+ };
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+
3
+ import {AriaLiveRegion} from '@workday/canvas-kit-react/common';
4
+ import {PrimaryButton} from '@workday/canvas-kit-react/button';
5
+ import {FormField} from '@workday/canvas-kit-preview-react/form-field';
6
+ import {Flex} from '@workday/canvas-kit-react/layout';
7
+ import {Text} from '@workday/canvas-kit-react/text';
8
+ import {TextInput} from '@workday/canvas-kit-react/text-input';
9
+ import {system, base} from '@workday/canvas-tokens-web';
10
+ import {createStyles, px2rem, calc} from '@workday/canvas-kit-styling';
11
+
12
+ const liveRegionStyle = createStyles({
13
+ border: `${px2rem(1)} solid ${system.color.border.caution.default}`,
14
+ backgroundColor: system.color.bg.caution.default,
15
+ padding: system.space.x4,
16
+ display: 'block',
17
+ marginBlockStart: system.space.x4,
18
+ marginBlockEnd: system.space.x4,
19
+ width: calc.multiply(system.space.x16, 7),
20
+ });
21
+
22
+ const flexGapStyles = createStyles({
23
+ gap: system.space.x4,
24
+ alignItems: 'center',
25
+ });
26
+
27
+ let liveRegionStr = 'This is an ARIA Live Region!';
28
+
29
+ export default () => {
30
+ const [message, setMessage] = React.useState('');
31
+
32
+ function handleChange(e) {
33
+ setMessage(e.target.value);
34
+ }
35
+
36
+ function handleSendMessage(e) {
37
+ e.preventDefault();
38
+ liveRegionStr = message;
39
+ setMessage('');
40
+ }
41
+
42
+ return (
43
+ <>
44
+ <AriaLiveRegion>
45
+ <Text cs={liveRegionStyle}>{liveRegionStr}</Text>
46
+ </AriaLiveRegion>
47
+ <Flex
48
+ as="form"
49
+ aria-label="Visible Live Region"
50
+ onSubmit={handleSendMessage}
51
+ cs={flexGapStyles}
52
+ >
53
+ <FormField>
54
+ <FormField.Label>Type your message:</FormField.Label>
55
+ <FormField.Input as={TextInput} onChange={handleChange} value={message} />
56
+ </FormField>
57
+ <PrimaryButton type="submit">Send Message</PrimaryButton>
58
+ </Flex>
59
+ </>
60
+ );
61
+ };
@@ -41,9 +41,24 @@ const myCustomStyles = createStyles({
41
41
  textTransform: 'uppercase',
42
42
  });
43
43
 
44
+ const customColors = {
45
+ default: {
46
+ background: system.color.static.green.soft,
47
+ icon: system.color.static.green.strong,
48
+ label: system.color.static.green.strong,
49
+ },
50
+ hover: {
51
+ background: system.color.static.green.default,
52
+ icon: system.color.static.green.strong,
53
+ },
54
+ };
55
+
44
56
  export default () => (
45
57
  <Grid cs={{gap: px2rem(4), gridTemplateColumns: 'repeat(3, 1fr)', alignItems: 'center'}}>
46
58
  <MyCustomButton icon={plusIcon}>Styling Override Via Stencil Variables</MyCustomButton>
47
59
  <PrimaryButton cs={myCustomStyles}>Style Override Via Create Styles</PrimaryButton>
60
+ <PrimaryButton icon={plusIcon} colors={customColors}>
61
+ Styling Override Via Colors Prop
62
+ </PrimaryButton>
48
63
  </Grid>
49
64
  );
@@ -10,6 +10,7 @@ import FocusRedirect from './examples/FocusRedirect';
10
10
  import FocusTrap from './examples/FocusTrap';
11
11
  import RTL from './examples/RTL';
12
12
  import CustomTarget from './examples/CustomTarget';
13
+ import ExternalWindow from './examples/ExternalWindow';
13
14
  import FullScreen from './examples/FullScreen';
14
15
 
15
16
 
@@ -159,6 +160,16 @@ the popup's stack context when entering/exiting fullscreen.
159
160
 
160
161
  <ExampleCodeBlock code={FullScreen} />
161
162
 
163
+ ### Opening an External Window
164
+
165
+ A popup can open an external window. This isn't supported directly. The `Popup.Popper` subcomponent
166
+ is replaced with a custom subcomponent that connects to the Popup model and controls the lifecycle
167
+ of the extenal window. Be sure to connect the `unload` event of both the parent `window` and the
168
+ external child `window` to the lifecycle of the Popup model to prevent memory leaks or zombie
169
+ windows.
170
+
171
+ <ExampleCodeBlock code={ExternalWindow} />
172
+
162
173
  ### RTL
163
174
 
164
175
  The Popup component automatically handles right-to-left rendering.
@@ -170,8 +181,8 @@ The Popup component automatically handles right-to-left rendering.
170
181
  ## Component API
171
182
 
172
183
  <>
173
- <SymbolDoc name="Popper" fileName="/react/" />
174
- <SymbolDoc name="Popup" fileName="/react/" />
184
+ <SymbolDoc name="Popper" fileName="/react/" />
185
+ <SymbolDoc name="Popup" fileName="/react/" />
175
186
  </>
176
187
 
177
188
  ## Hooks
@@ -0,0 +1,176 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+
4
+ import {system} from '@workday/canvas-tokens-web';
5
+ import {createStyles} from '@workday/canvas-kit-styling';
6
+ import {infoIcon} from '@workday/canvas-system-icons-web';
7
+
8
+ import {
9
+ CanvasProvider,
10
+ ContentDirection,
11
+ createSubcomponent,
12
+ PartialEmotionCanvasTheme,
13
+ useMount,
14
+ useTheme,
15
+ } from '@workday/canvas-kit-react/common';
16
+ import {Tooltip} from '@workday/canvas-kit-react/tooltip';
17
+ import {Popup, usePopupModel} from '@workday/canvas-kit-react/popup';
18
+ import {SecondaryButton} from '@workday/canvas-kit-react/button';
19
+ import {Flex} from '@workday/canvas-kit-react/layout';
20
+
21
+ const mainContentStyles = createStyles({
22
+ padding: system.space.x4,
23
+ });
24
+
25
+ export interface ExternalWindowPortalProps {
26
+ /**
27
+ * Child components of WindowPortal
28
+ */
29
+ children: React.ReactNode;
30
+ /**
31
+ * Callback to close the popup
32
+ */
33
+ onWindowClose?: () => void;
34
+ /**
35
+ * Width of the popup window
36
+ */
37
+ width?: number;
38
+ /**
39
+ * Height of the popup window
40
+ */
41
+ height?: number;
42
+ /**
43
+ * The name of the popup window. If another popup opens with the same name, that instance will
44
+ * be reused. Use caution with setting this value
45
+ */
46
+ target?: string;
47
+ }
48
+
49
+ async function copyAssets(sourceDoc: Document, targetDoc: Document) {
50
+ for (const font of (sourceDoc as any).fonts.values()) {
51
+ (targetDoc as any).fonts.add(font);
52
+
53
+ font.load();
54
+ }
55
+
56
+ await (targetDoc as any).fonts.ready;
57
+
58
+ // The current ES lib version doesn't include iterable interfaces, so we cast as an iterable
59
+ for (const styleSheet of sourceDoc.styleSheets as StyleSheetList & Iterable<CSSStyleSheet>) {
60
+ if (styleSheet.cssRules) {
61
+ // text based styles
62
+ const styleEl = targetDoc.createElement('style');
63
+ for (const cssRule of styleSheet.cssRules as CSSRuleList & Iterable<CSSRule>) {
64
+ styleEl.appendChild(targetDoc.createTextNode(cssRule.cssText));
65
+ }
66
+ targetDoc.head.appendChild(styleEl);
67
+ } else if (styleSheet.href) {
68
+ // link based styles
69
+ const linkEl = targetDoc.createElement('link');
70
+
71
+ linkEl.rel = 'stylesheet';
72
+ linkEl.href = styleSheet.href;
73
+ targetDoc.head.appendChild(linkEl);
74
+ }
75
+ }
76
+ }
77
+
78
+ const ExternalWindowPortal = ({
79
+ children,
80
+ width = 300,
81
+ height = 500,
82
+ target = '',
83
+ onWindowClose,
84
+ }: ExternalWindowPortalProps) => {
85
+ const [portalElement, setPortalElement] = React.useState<HTMLDivElement | null>(null);
86
+
87
+ useMount(() => {
88
+ const newWindow = window.open(
89
+ '', // url
90
+ target,
91
+ `width=${width},height=${height},left=100,top=100,popup=true`
92
+ );
93
+
94
+ if (newWindow) {
95
+ // copy fonts and styles
96
+ copyAssets(document, newWindow.document);
97
+
98
+ const element = newWindow.document.createElement('div');
99
+ newWindow.document.body.appendChild(element);
100
+ setPortalElement(element);
101
+ } else {
102
+ onWindowClose();
103
+ }
104
+
105
+ const closeWindow = event => {
106
+ onWindowClose();
107
+ };
108
+
109
+ window.addEventListener('unload', closeWindow);
110
+ newWindow?.addEventListener('unload', closeWindow);
111
+
112
+ return () => {
113
+ window.removeEventListener('unload', closeWindow);
114
+ newWindow?.removeEventListener('unload', closeWindow);
115
+ newWindow?.close();
116
+ };
117
+ });
118
+
119
+ if (!portalElement) {
120
+ return null;
121
+ }
122
+
123
+ return ReactDOM.createPortal(<CanvasProvider>{children}</CanvasProvider>, portalElement);
124
+ };
125
+
126
+ const PopupExternalWindow = createSubcomponent()({
127
+ displayName: 'Popup.ExternalWindow',
128
+ modelHook: usePopupModel,
129
+ })<ExternalWindowPortalProps>(({children, ...elemProps}, Element, model) => {
130
+ if (model.state.visibility === 'visible') {
131
+ return (
132
+ <ExternalWindowPortal onWindowClose={model.events.hide} {...elemProps}>
133
+ {children}
134
+ </ExternalWindowPortal>
135
+ );
136
+ }
137
+
138
+ return null;
139
+ });
140
+
141
+ export default () => {
142
+ // useTheme is filling in the Canvas theme object if any keys are missing
143
+ const canvasTheme: PartialEmotionCanvasTheme = useTheme({
144
+ canvas: {
145
+ // Switch to `ContentDirection.RTL` to change direction
146
+ direction: ContentDirection.LTR,
147
+ },
148
+ });
149
+
150
+ const model = usePopupModel();
151
+
152
+ return (
153
+ <CanvasProvider theme={canvasTheme}>
154
+ <>
155
+ <main className={mainContentStyles}>
156
+ <p>Popup that opens a new Operating System Window</p>
157
+ <Popup model={model}>
158
+ <Tooltip title="Open External Window Tooltip">
159
+ <Popup.Target>Open External Window</Popup.Target>
160
+ </Tooltip>
161
+ <PopupExternalWindow>
162
+ <p>External Window Contents! Mouse over the info icon to get a tooltip</p>
163
+ <Flex gap="s">
164
+ <Tooltip title="More information">
165
+ <SecondaryButton icon={infoIcon} />
166
+ </Tooltip>
167
+ <Popup.CloseButton>Close Window</Popup.CloseButton>
168
+ </Flex>
169
+ </PopupExternalWindow>
170
+ </Popup>
171
+ <p>Popup visibility: {model.state.visibility}</p>
172
+ </main>
173
+ </>
174
+ </CanvasProvider>
175
+ );
176
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workday/canvas-kit-docs",
3
- "version": "11.1.0-833-next.0",
3
+ "version": "11.1.0",
4
4
  "description": "Documentation components of Canvas Kit components",
5
5
  "author": "Workday, Inc. (https://www.workday.com)",
6
6
  "license": "Apache-2.0",
@@ -44,13 +44,13 @@
44
44
  "dependencies": {
45
45
  "@emotion/styled": "^11.6.0",
46
46
  "@storybook/csf": "0.0.1",
47
- "@workday/canvas-kit-labs-react": "^11.1.0-833-next.0",
48
- "@workday/canvas-kit-preview-react": "^11.1.0-833-next.0",
49
- "@workday/canvas-kit-react": "^11.1.0-833-next.0",
50
- "@workday/canvas-kit-styling": "^11.1.0-833-next.0",
47
+ "@workday/canvas-kit-labs-react": "^11.1.0",
48
+ "@workday/canvas-kit-preview-react": "^11.1.0",
49
+ "@workday/canvas-kit-react": "^11.1.0",
50
+ "@workday/canvas-kit-styling": "^11.1.0",
51
51
  "@workday/canvas-system-icons-web": "^3.0.0",
52
52
  "@workday/canvas-tokens-web": "^2.0.0",
53
- "markdown-to-jsx": "^6.10.3",
53
+ "markdown-to-jsx": "^7.2.0",
54
54
  "ts-node": "^10.9.1"
55
55
  },
56
56
  "devDependencies": {
@@ -59,5 +59,5 @@
59
59
  "mkdirp": "^1.0.3",
60
60
  "typescript": "4.2"
61
61
  },
62
- "gitHead": "d810cce07772db36ba395b874bd25d90e6072b09"
62
+ "gitHead": "0b38e0b6ec6a0990e4bad0375dc57ecf15239d2c"
63
63
  }
@@ -1,30 +0,0 @@
1
- import React, {useState, useRef} from 'react';
2
- import {AriaLiveRegion, AccessibleHide} from '@workday/canvas-kit-react/common';
3
- import {PrimaryButton} from '@workday/canvas-kit-react/button';
4
- import {TextInput} from '@workday/canvas-kit-preview-react/text-input';
5
- import {Flex} from '@workday/canvas-kit-react/layout';
6
- import {system} from '@workday/canvas-tokens-web';
7
-
8
- export default () => {
9
- const [message, setMessage] = useState('This is an ARIA Live Region!');
10
- const inputRef = useRef();
11
- function handleSendMessage() {
12
- setMessage(inputRef.current.value);
13
- inputRef.current.value = '';
14
- }
15
-
16
- return (
17
- <>
18
- <Flex gap={`var(${system.space.x4})`} alignItems="flex-end">
19
- <TextInput orientation="vertical">
20
- <TextInput.Label>Type your message:</TextInput.Label>
21
- <TextInput.Field ref={inputRef} />
22
- </TextInput>
23
- <PrimaryButton onClick={handleSendMessage}>Send Message</PrimaryButton>
24
- </Flex>
25
- <AriaLiveRegion>
26
- <AccessibleHide>{message}</AccessibleHide>
27
- </AriaLiveRegion>
28
- </>
29
- );
30
- };
@@ -1,25 +0,0 @@
1
- import React, {useState, useRef} from 'react';
2
- import {TextInput} from '@workday/canvas-kit-preview-react/text-input';
3
- import {AriaLiveRegion, changeFocus} from '@workday/canvas-kit-react/common';
4
- import {PrimaryButton} from '@workday/canvas-kit-react/button';
5
-
6
- export default () => {
7
- const errMsg = 'Error: First name is required.';
8
- const [hasError, setHasError] = useState(false);
9
- const inputRef = useRef();
10
- const handleBlur = e => setHasError(e.target.value.trim().length === 0);
11
- const handleSubmit = () => hasError && changeFocus(inputRef.current);
12
-
13
- return (
14
- <>
15
- <TextInput orientation="vertical" hasError={hasError} isRequired={true}>
16
- <TextInput.Label>First Name:</TextInput.Label>
17
- <TextInput.Field onBlur={handleBlur} ref={inputRef} />
18
- <TextInput.Hint height={'16px'}>
19
- <AriaLiveRegion>{hasError && errMsg}</AriaLiveRegion>
20
- </TextInput.Hint>
21
- </TextInput>
22
- <PrimaryButton onClick={handleSubmit}>Continue</PrimaryButton>
23
- </>
24
- );
25
- };
@@ -1,40 +0,0 @@
1
- import React, {useState, useRef} from 'react';
2
- import {AriaLiveRegion} from '@workday/canvas-kit-react/common';
3
- import {PrimaryButton} from '@workday/canvas-kit-react/button';
4
- import {TextInput} from '@workday/canvas-kit-preview-react/text-input';
5
- import {Flex} from '@workday/canvas-kit-react/layout';
6
- import {Text} from '@workday/canvas-kit-react/text';
7
- import {system, base} from '@workday/canvas-tokens-web';
8
- import {createStyles, px2rem} from '@workday/canvas-kit-styling';
9
-
10
- const liveRegionStyle = createStyles({
11
- border: `${px2rem(1)} solid ${base.cantaloupe400}`,
12
- backgroundColor: base.cantaloupe100,
13
- padding: system.space.x4,
14
- display: 'block',
15
- margin: system.space.x4 + ' 0',
16
- });
17
-
18
- export default () => {
19
- const [message, setMessage] = useState('This is an ARIA Live Region!');
20
- const inputRef = useRef();
21
- function handleSendMessage() {
22
- setMessage(inputRef.current.value);
23
- inputRef.current.value = '';
24
- }
25
-
26
- return (
27
- <>
28
- <AriaLiveRegion>
29
- <Text cs={liveRegionStyle}>{message}</Text>
30
- </AriaLiveRegion>
31
- <Flex gap={`var(${system.space.x4})`} alignItems="flex-end">
32
- <TextInput orientation="vertical">
33
- <TextInput.Label>Type your message:</TextInput.Label>
34
- <TextInput.Field ref={inputRef} />
35
- </TextInput>
36
- <PrimaryButton onClick={handleSendMessage}>Send Message</PrimaryButton>
37
- </Flex>
38
- </>
39
- );
40
- };