@workday/canvas-kit-docs 12.3.1 → 12.3.3

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.
@@ -41,9 +41,12 @@ logic or styling for bidirecitonal support.
41
41
 
42
42
  ### Hidden Name
43
43
 
44
- `SidePanel` should always have an accessible label. Often this is the heading element with an `id`
45
- attribute. However, as seen in the example below, you can apply a `hidden` attribute to your label
46
- if you do not want it to be visible.
44
+ `SidePanel` must always have an accessible label for both the HTML `<section>` container and the
45
+ `ToggleButton`. The `labelProps` component must always be present in the DOM in order for the
46
+ `panelProps` and `controlProps` component labels to be assigned properly. A `hidden` attribute can
47
+ be applied to the `labelProps` component. In the example below, we are demonstrating the
48
+ `AccessibleHide` component that relies on CSS properties to visually hide text for screen readers
49
+ only.
47
50
 
48
51
  <ExampleCodeBlock code={HiddenName} />
49
52
 
@@ -60,6 +63,28 @@ used (this case is covered in the Examples section).
60
63
  Sometimes you'll want to control `SidePanel`'s' expand / collapse behavior from outside the
61
64
  component. In that case, you can use the `controlProps` supplied by the `useSidePanel` hook.
62
65
 
66
+ #### Notes about accessibility
67
+
68
+ The `controlProps` object delivers ARIA attributes to a component under the following assumptions:
69
+
70
+ 1. The control is an icon button that does not already have an accessible name
71
+ 2. The control appears at (or near) the top of the expandable content in the `SidePanel`
72
+
73
+ Spreading the `controlProps` onto an external control can introduce serious accessibility issues:
74
+
75
+ - `aria-labelledby` HTML `id` reference may become invalid when the SidePanel is collapsed, or when
76
+ the `labelProps` component isn't present in the DOM.
77
+ - `aria-labelledby` will change the name of `controlProps` component to the title of the
78
+ `SidePanel`. (This may be undesirable. For example, the "Show Side Panel" button will be
79
+ overwritten with the "Tasks Panel" heading.)
80
+ - `aria-expanded` won't make sense to screen reader users when the expanded `SidePanel` content
81
+ isn't logically following the control.
82
+ - `aria-controls` is unsupported by screen readers and will not allow users to navigate to the
83
+ controlled content.
84
+
85
+ In the following example, the `controlProps` click handler function is passed down to the
86
+ `SecondaryButton` and a toggle state was added to the button using the `aria-pressed` property.
87
+
63
88
  <ExampleCodeBlock code={ExternalControl} />
64
89
 
65
90
  ### Right Origin
@@ -1,35 +1,54 @@
1
1
  import * as React from 'react';
2
- import {styled} from '@workday/canvas-kit-react/common';
3
- import {space} from '@workday/canvas-kit-react/tokens';
4
2
  import {AccentIcon} from '@workday/canvas-kit-react/icon';
5
3
  import {rocketIcon} from '@workday/canvas-accent-icons-web';
6
4
  import {SidePanel, useSidePanel} from '@workday/canvas-kit-preview-react/side-panel';
7
5
  import {Flex} from '@workday/canvas-kit-react/layout';
8
- import {Text} from '@workday/canvas-kit-react/text';
6
+ import {Heading, Text} from '@workday/canvas-kit-react/text';
7
+ import {base, system} from '@workday/canvas-tokens-web';
8
+ import {createStyles, px2rem} from '@workday/canvas-kit-styling';
9
9
 
10
- const StyledAccentIcon = styled(AccentIcon)({
11
- marginRight: space.s,
12
- });
10
+ const stylesOverride = {
11
+ accentIcon: createStyles({
12
+ marginRight: system.space.x4,
13
+ }),
14
+ pageContainer: createStyles({
15
+ gap: system.space.x4,
16
+ height: px2rem(320),
17
+ }),
18
+ panelContainer: createStyles({
19
+ alignItems: 'center',
20
+ paddingY: system.space.x4,
21
+ paddingX: system.space.x4,
22
+ }),
23
+ panelHeading: createStyles({
24
+ color: base.licorice500,
25
+ }),
26
+ mainContent: createStyles({
27
+ alignItems: 'center',
28
+ justifyContent: 'center',
29
+ flexBasis: 'auto',
30
+ flex: 1,
31
+ }),
32
+ };
13
33
 
14
34
  export default () => {
15
35
  const {panelProps, labelProps} = useSidePanel();
16
36
 
17
37
  return (
18
- <Flex gap="s" height={320}>
38
+ <Flex cs={stylesOverride.pageContainer}>
19
39
  <SidePanel {...panelProps}>
20
- <Flex alignItems="center" paddingY="s" paddingX="s">
21
- <StyledAccentIcon icon={rocketIcon} />
22
- <Text
23
- as="h3"
24
- typeLevel="body.large"
25
- color="licorice500"
26
- fontWeight="bold"
27
- {...labelProps}
28
- >
40
+ <Flex cs={stylesOverride.panelContainer}>
41
+ <AccentIcon icon={rocketIcon} cs={stylesOverride.accentIcon} />
42
+ <Heading size="small" cs={stylesOverride.panelHeading} {...labelProps}>
29
43
  Tasks Panel
30
- </Text>
44
+ </Heading>
31
45
  </Flex>
32
46
  </SidePanel>
47
+ <Flex as="main" cs={stylesOverride.mainContent}>
48
+ <Text as="p" typeLevel="body.large">
49
+ This is the main content section.
50
+ </Text>
51
+ </Flex>
33
52
  </Flex>
34
53
  );
35
54
  };
@@ -6,54 +6,60 @@ import {
6
6
  SidePanelTransitionStates,
7
7
  } from '@workday/canvas-kit-preview-react/side-panel';
8
8
  import {Flex} from '@workday/canvas-kit-react/layout';
9
- import {Text} from '@workday/canvas-kit-react/text';
9
+ import {Heading, Text} from '@workday/canvas-kit-react/text';
10
10
  import {CanvasProvider} from '@workday/canvas-kit-react/common';
11
11
  import {AccentIcon} from '@workday/canvas-kit-react/icon';
12
12
  import {rocketIcon} from '@workday/canvas-accent-icons-web';
13
- // local helper hook for setting content direction;
14
13
  import {useDirection} from './useDirection';
14
+ import {createStyles, px2rem} from '@workday/canvas-kit-styling';
15
+ import {system, base} from '@workday/canvas-tokens-web';
16
+
17
+ const stylesOverride = {
18
+ viewPortContainer: createStyles({
19
+ height: px2rem(320),
20
+ }),
21
+ panel: createStyles({
22
+ alignItems: 'center',
23
+ paddingY: system.space.x4,
24
+ paddingX: system.space.x4,
25
+ }),
26
+ accentIcon: createStyles({
27
+ marginInlineEnd: system.space.x4,
28
+ }),
29
+ mainContent: createStyles({
30
+ alignItems: 'center',
31
+ justifyContent: 'center',
32
+ flexDirection: 'column',
33
+ flex: 1,
34
+ flexBasis: 'auto',
35
+ }),
36
+ };
15
37
 
16
38
  export default () => {
17
39
  const {direction, toggleDirection} = useDirection();
18
40
  const {expanded, panelProps, labelProps, controlProps} = useSidePanel();
19
- const [panelState, setPanelState] = React.useState<SidePanelTransitionStates>(
20
- expanded ? 'expanded' : 'collapsed'
21
- );
22
-
23
- const expandedContent = (
24
- <Flex alignItems="center" paddingY="s" paddingX="s">
25
- <Flex marginInlineEnd="s">
26
- <AccentIcon icon={rocketIcon} />
27
- </Flex>
28
- <Text as="h3" typeLevel="body.large" color="licorice500" fontWeight="bold" {...labelProps}>
29
- Tasks Panel
30
- </Text>
31
- </Flex>
32
- );
33
41
 
34
42
  return (
35
43
  <CanvasProvider theme={{canvas: {direction}}}>
36
- <Flex height={320}>
37
- <SidePanel {...panelProps} onStateTransition={setPanelState}>
44
+ <Flex cs={stylesOverride.viewPortContainer}>
45
+ <SidePanel {...panelProps}>
38
46
  <SidePanel.ToggleButton {...controlProps} />
39
- {panelState === 'expanded' ? (
40
- expandedContent
41
- ) : (
42
- <Text hidden {...labelProps}>
47
+ <Flex cs={stylesOverride.panel}>
48
+ {expanded && (
49
+ <Flex cs={stylesOverride.accentIcon}>
50
+ <AccentIcon icon={rocketIcon} />
51
+ </Flex>
52
+ )}
53
+ <Heading size="small" {...labelProps} hidden={!expanded ? true : undefined}>
43
54
  Tasks Panel
44
- </Text>
45
- )}
55
+ </Heading>
56
+ </Flex>
46
57
  </SidePanel>
47
- <Flex
48
- as="main"
49
- alignItems="center"
50
- justifyContent="center"
51
- flexDirection="column"
52
- flex={1}
53
- flexBasis="auto"
54
- >
55
- <p>Toggle the content direction</p>
56
- <SecondaryButton onClick={toggleDirection} role="button">
58
+ <Flex as="main" cs={stylesOverride.mainContent}>
59
+ <Text as="p" typeLevel="body.large">
60
+ Toggle the content direction
61
+ </Text>
62
+ <SecondaryButton onClick={toggleDirection}>
57
63
  Set to {direction === 'ltr' ? 'Right-to-Left' : 'Left-to-Right'}
58
64
  </SecondaryButton>
59
65
  </Flex>
@@ -5,9 +5,45 @@ import {
5
5
  SidePanelTransitionStates,
6
6
  } from '@workday/canvas-kit-preview-react/side-panel';
7
7
  import {Flex} from '@workday/canvas-kit-react/layout';
8
- import {Text} from '@workday/canvas-kit-react/text';
8
+ import {Heading, Text} from '@workday/canvas-kit-react/text';
9
9
  import {SecondaryButton} from '@workday/canvas-kit-react/button';
10
+ import {createStyles, px2rem} from '@workday/canvas-kit-styling';
11
+ import {base, system} from '@workday/canvas-tokens-web';
10
12
 
13
+ const stylesOverride = {
14
+ viewport: createStyles({
15
+ height: px2rem(320),
16
+ }),
17
+ panel: createStyles({
18
+ alignItems: 'center',
19
+ paddingY: system.space.x4,
20
+ paddingX: system.space.x4,
21
+ }),
22
+ panelHeading: createStyles({
23
+ color: base.licorice500,
24
+ }),
25
+ main: createStyles({
26
+ alignItems: 'center',
27
+ justifyContent: 'center',
28
+ flexDirection: 'column',
29
+ flex: 1,
30
+ flexBasis: 'auto',
31
+ }),
32
+ };
33
+
34
+ /*
35
+ * NOTE TO DEV:
36
+ * Spreading the `controlProps` onto an external control creates serious accessibility issues.
37
+ * - `aria-labelledby` id reference is invalid when the SidePanel is collapsed
38
+ * - `aria-labelledby` will change the name of "Toggle Side Panel" button to "Tasks Panel"
39
+ * - `aria-expanded` won't make sense to screen reader users when the expanded SidePanel content isn't following the control
40
+ * - `aria-controls` is unsupported by screen readers and will not allow users to navigate to the controlled content
41
+ *
42
+ * SOLUTION:
43
+ * - Pass the `controlProps` click handler function down to the external control component.
44
+ * - Add a toggle state to Button components with `aria-pressed` for screen readers,
45
+ * - OR use a similar toggle input like Checkbox or Switch.
46
+ */
11
47
  export default () => {
12
48
  const {expanded, panelProps, labelProps, controlProps} = useSidePanel({initialExpanded: false});
13
49
  const [panelState, setPanelState] = React.useState<SidePanelTransitionStates>(
@@ -15,9 +51,8 @@ export default () => {
15
51
  );
16
52
 
17
53
  return (
18
- <Flex height={320}>
54
+ <Flex cs={stylesOverride.viewport}>
19
55
  <SidePanel
20
- as="aside"
21
56
  {...panelProps}
22
57
  onExpandedChange={expanded => {
23
58
  console.log(`expanded prop is: ${expanded ? 'true' : 'false'}`);
@@ -25,30 +60,19 @@ export default () => {
25
60
  onStateTransition={setPanelState}
26
61
  >
27
62
  {panelState === 'expanded' && (
28
- <Flex alignItems="center" paddingY="s" paddingX="s">
29
- <Text
30
- as="h3"
31
- typeLevel="body.large"
32
- color="licorice500"
33
- fontWeight="bold"
34
- {...labelProps}
35
- >
63
+ <Flex cs={stylesOverride.panel}>
64
+ <Heading size="small" cs={stylesOverride.panelHeading} {...labelProps}>
36
65
  Tasks Panel
37
- </Text>
66
+ </Heading>
38
67
  </Flex>
39
68
  )}
40
69
  </SidePanel>
41
- <Flex
42
- as="main"
43
- alignItems="center"
44
- justifyContent="center"
45
- flexDirection="column"
46
- flex={1}
47
- flexBasis="auto"
48
- >
49
- <p>Control the panel externally</p>
50
- <SecondaryButton {...controlProps} role="button">
51
- Toggle Side Panel
70
+ <Flex as="main" cs={stylesOverride.main}>
71
+ <Text as="p" typeLevel="body.large">
72
+ Control the panel externally
73
+ </Text>
74
+ <SecondaryButton onClick={controlProps.onClick} aria-pressed={expanded}>
75
+ Show Side Panel
52
76
  </SecondaryButton>
53
77
  </Flex>
54
78
  </Flex>
@@ -1,13 +1,29 @@
1
1
  import * as React from 'react';
2
2
  import {SidePanel, useSidePanel} from '@workday/canvas-kit-preview-react/side-panel';
3
3
  import {Flex} from '@workday/canvas-kit-react/layout';
4
+ import {AccessibleHide} from '@workday/canvas-kit-react/common';
5
+ import {Text} from '@workday/canvas-kit-react/text';
6
+ import {createStyles, px2rem} from '@workday/canvas-kit-styling';
7
+
8
+ const stylesOverride = {
9
+ viewport: createStyles({
10
+ height: px2rem(320),
11
+ }),
12
+ main: createStyles({
13
+ alignItems: 'center',
14
+ justifyContent: 'center',
15
+ flexDirection: 'column',
16
+ flex: 1,
17
+ flexBasis: 'auto',
18
+ }),
19
+ };
4
20
 
5
21
  export default () => {
6
22
  const {panelProps, labelProps, controlProps} = useSidePanel();
23
+
7
24
  return (
8
- <Flex height={320}>
25
+ <Flex cs={stylesOverride.viewport}>
9
26
  <SidePanel
10
- as="aside"
11
27
  {...panelProps}
12
28
  onExpandedChange={expanded => {
13
29
  console.log(`expanded prop is: ${expanded ? 'true' : 'false'}`);
@@ -17,10 +33,13 @@ export default () => {
17
33
  }}
18
34
  >
19
35
  <SidePanel.ToggleButton {...controlProps} />
20
- <span hidden {...labelProps}>
21
- Side Panel with a hidden label
22
- </span>
36
+ <AccessibleHide {...labelProps}>Hidden Title</AccessibleHide>
23
37
  </SidePanel>
38
+ <Flex as="main" cs={stylesOverride.main}>
39
+ <Text as="p" typeLevel="body.large">
40
+ Side Panel with a hidden title text.
41
+ </Text>
42
+ </Flex>
24
43
  </Flex>
25
44
  );
26
45
  };
@@ -1,6 +1,22 @@
1
1
  import * as React from 'react';
2
2
  import {Flex} from '@workday/canvas-kit-react/layout';
3
3
  import {SidePanel, useSidePanel} from '@workday/canvas-kit-preview-react/side-panel';
4
+ import {Text} from '@workday/canvas-kit-react/text';
5
+ import {AccessibleHide} from '@workday/canvas-kit-react/common';
6
+ import {createStyles, px2rem} from '@workday/canvas-kit-styling';
7
+
8
+ const stylesOverride = {
9
+ viewport: createStyles({
10
+ height: px2rem(320),
11
+ }),
12
+ main: createStyles({
13
+ alignItems: 'center',
14
+ justifyContent: 'center',
15
+ flexDirection: 'column',
16
+ flex: 1,
17
+ flexBasis: 'auto',
18
+ }),
19
+ };
4
20
 
5
21
  export default () => {
6
22
  const {expanded, panelProps, labelProps, controlProps} = useSidePanel();
@@ -10,15 +26,15 @@ export default () => {
10
26
  };
11
27
 
12
28
  return (
13
- <Flex height={320}>
29
+ <Flex cs={stylesOverride.viewport}>
14
30
  <SidePanel {...panelProps} onExpandedChange={handleExpandedChange}>
15
31
  <SidePanel.ToggleButton {...controlProps} />
16
- <span hidden {...labelProps}>
17
- custom side panel
18
- </span>
32
+ <AccessibleHide {...labelProps}>Hidden Title</AccessibleHide>
19
33
  </SidePanel>
20
- <Flex as="main" alignItems="center" justifyContent="center" flex={1} flexBasis="auto">
21
- <p>Side panel is {expanded ? 'expanded' : 'collapsed'}.</p>
34
+ <Flex as="main" cs={stylesOverride.main}>
35
+ <Text as="p" typeLevel="body.large">
36
+ Side panel is {expanded ? 'expanded' : 'collapsed'}.
37
+ </Text>
22
38
  </Flex>
23
39
  </Flex>
24
40
  );
@@ -5,27 +5,42 @@ import {
5
5
  useSidePanel,
6
6
  SidePanelTransitionStates,
7
7
  } from '@workday/canvas-kit-preview-react/side-panel';
8
+ import {AccessibleHide} from '@workday/canvas-kit-react/common';
9
+ import {Text} from '@workday/canvas-kit-react/text';
10
+ import {createStyles, px2rem} from '@workday/canvas-kit-styling';
11
+
12
+ const stylesOverride = {
13
+ viewport: createStyles({
14
+ height: px2rem(320),
15
+ }),
16
+ main: createStyles({
17
+ alignItems: 'center',
18
+ justifyContent: 'center',
19
+ flexDirection: 'column',
20
+ flex: 1,
21
+ flexBasis: 'auto',
22
+ }),
23
+ };
8
24
 
9
25
  export default () => {
10
26
  const {panelProps, labelProps, controlProps} = useSidePanel();
11
- const [transitionState, setTransitionState] = React.useState<SidePanelTransitionStates>(
12
- 'expanded'
13
- );
27
+ const [transitionState, setTransitionState] =
28
+ React.useState<SidePanelTransitionStates>('expanded');
14
29
 
15
30
  const handleStateTransition = (transition: SidePanelTransitionStates) => {
16
31
  setTransitionState(transition);
17
32
  };
18
33
 
19
34
  return (
20
- <Flex height={320}>
35
+ <Flex cs={stylesOverride.viewport}>
21
36
  <SidePanel {...panelProps} onStateTransition={handleStateTransition}>
22
37
  <SidePanel.ToggleButton {...controlProps} />
23
- <span hidden {...labelProps}>
24
- custom side panel
25
- </span>
38
+ <AccessibleHide {...labelProps}>Hidden Title</AccessibleHide>
26
39
  </SidePanel>
27
- <Flex as="main" alignItems="center" justifyContent="center" flex={1} flexBasis="auto">
28
- <p>Side panel is {transitionState}.</p>
40
+ <Flex as="main" cs={stylesOverride.main}>
41
+ <Text as="p" typeLevel="body.large">
42
+ Side panel is {transitionState}.
43
+ </Text>
29
44
  </Flex>
30
45
  </Flex>
31
46
  );
@@ -1,45 +1,49 @@
1
1
  import * as React from 'react';
2
2
  import {SecondaryButton} from '@workday/canvas-kit-react/button';
3
- import {
4
- SidePanel,
5
- useSidePanel,
6
- SidePanelTransitionStates,
7
- } from '@workday/canvas-kit-preview-react/side-panel';
3
+ import {SidePanel, useSidePanel} from '@workday/canvas-kit-preview-react/side-panel';
8
4
  import {Flex} from '@workday/canvas-kit-react/layout';
9
- import {Text} from '@workday/canvas-kit-react/text';
10
- import {CanvasProvider, styled} from '@workday/canvas-kit-react/common';
5
+ import {Heading, Text} from '@workday/canvas-kit-react/text';
6
+ import {CanvasProvider} from '@workday/canvas-kit-react/common';
7
+ import {createStyles, px2rem} from '@workday/canvas-kit-styling';
8
+ import {system} from '@workday/canvas-tokens-web';
9
+
11
10
  // local helper hook for setting content direction;
12
11
  import {useDirection} from './useDirection';
13
12
 
14
- const StyledSidePanel = styled(SidePanel)({
15
- marginLeft: 'auto',
16
- });
13
+ const stylesOverride = {
14
+ viewport: createStyles({
15
+ height: px2rem(320),
16
+ }),
17
+ panelContainer: createStyles({
18
+ marginLeft: 'auto',
19
+ }),
20
+ panel: createStyles({
21
+ alignItems: 'center',
22
+ justifyContent: 'flex-end',
23
+ paddingY: system.space.x4,
24
+ paddingX: system.space.x4,
25
+ }),
26
+ main: createStyles({
27
+ alignItems: 'center',
28
+ justifyContent: 'center',
29
+ flexDirection: 'column',
30
+ flex: 1,
31
+ flexBasis: 'auto',
32
+ }),
33
+ };
17
34
 
18
35
  const RightPanel = () => {
19
36
  const {expanded, panelProps, labelProps, controlProps} = useSidePanel();
20
- const [panelState, setPanelState] = React.useState<SidePanelTransitionStates>(
21
- expanded ? 'expanded' : 'collapsed'
22
- );
23
-
24
- const expandedContent = (
25
- <Flex alignItems="center" justifyContent="flex-end" paddingY="s" paddingX="s">
26
- <Text as="h3" typeLevel="body.large" color="licorice500" fontWeight="bold" {...labelProps}>
27
- Tasks Panel
28
- </Text>
29
- </Flex>
30
- );
31
37
 
32
38
  return (
33
- <StyledSidePanel {...panelProps} onStateTransition={setPanelState} origin="right">
39
+ <SidePanel {...panelProps} origin="right" className={stylesOverride.panelContainer}>
34
40
  <SidePanel.ToggleButton {...controlProps} />
35
- {panelState === 'expanded' ? (
36
- expandedContent
37
- ) : (
38
- <Text hidden {...labelProps}>
41
+ <Flex cs={stylesOverride.panel}>
42
+ <Heading size="small" hidden={!expanded ? true : undefined} {...labelProps}>
39
43
  Tasks Panel
40
- </Text>
41
- )}
42
- </StyledSidePanel>
44
+ </Heading>
45
+ </Flex>
46
+ </SidePanel>
43
47
  );
44
48
  };
45
49
 
@@ -48,17 +52,12 @@ export default () => {
48
52
 
49
53
  return (
50
54
  <CanvasProvider theme={{canvas: {direction}}}>
51
- <Flex height={320}>
52
- <Flex
53
- as="main"
54
- alignItems="center"
55
- justifyContent="center"
56
- flexDirection="column"
57
- flex={1}
58
- flexBasis="auto"
59
- >
60
- <p>Toggle the content direction</p>
61
- <SecondaryButton onClick={toggleDirection} role="button">
55
+ <Flex cs={stylesOverride.viewport}>
56
+ <Flex as="main" cs={stylesOverride.main}>
57
+ <Text as="p" typeLevel="body.large">
58
+ Toggle the content direction
59
+ </Text>
60
+ <SecondaryButton onClick={toggleDirection}>
62
61
  Set to {direction === 'ltr' ? 'Right-to-Left' : 'Left-to-Right'}
63
62
  </SecondaryButton>
64
63
  </Flex>
@@ -1,54 +1,54 @@
1
1
  import * as React from 'react';
2
2
  import {SecondaryButton} from '@workday/canvas-kit-react/button';
3
- import {
4
- SidePanel,
5
- useSidePanel,
6
- SidePanelTransitionStates,
7
- } from '@workday/canvas-kit-preview-react/side-panel';
3
+ import {SidePanel, useSidePanel} from '@workday/canvas-kit-preview-react/side-panel';
8
4
  import {Flex} from '@workday/canvas-kit-react/layout';
9
- import {Text} from '@workday/canvas-kit-react/text';
5
+ import {Heading, Text} from '@workday/canvas-kit-react/text';
10
6
  import {CanvasProvider} from '@workday/canvas-kit-react/common';
7
+ import {createStyles, px2rem} from '@workday/canvas-kit-styling';
8
+ import {base, system} from '@workday/canvas-tokens-web';
9
+
11
10
  // local helper hook for setting content direction;
12
11
  import {useDirection} from './useDirection';
13
12
 
13
+ const stylesOverride = {
14
+ viewport: createStyles({
15
+ height: px2rem(320),
16
+ backgroundColor: base.soap100,
17
+ }),
18
+ panel: createStyles({
19
+ alignItems: 'center',
20
+ paddingY: system.space.x4,
21
+ paddingX: system.space.x4,
22
+ }),
23
+ main: createStyles({
24
+ alignItems: 'center',
25
+ justifyContent: 'center',
26
+ flexDirection: 'column',
27
+ flex: 1,
28
+ flexBasis: 'auto',
29
+ }),
30
+ };
31
+
14
32
  export default () => {
15
33
  const {direction, toggleDirection} = useDirection();
16
34
  const {expanded, panelProps, labelProps, controlProps} = useSidePanel();
17
- const [panelState, setPanelState] = React.useState<SidePanelTransitionStates>(
18
- expanded ? 'expanded' : 'collapsed'
19
- );
20
-
21
- const expandedContent = (
22
- <Flex alignItems="center" paddingY="s" paddingX="s">
23
- <Text as="h3" typeLevel="body.large" color="licorice500" fontWeight="bold" {...labelProps}>
24
- Alternate Panel
25
- </Text>
26
- </Flex>
27
- );
28
35
 
29
36
  return (
30
37
  <CanvasProvider theme={{canvas: {direction}}}>
31
- <Flex height={320} backgroundColor="soap100">
32
- <SidePanel {...panelProps} onStateTransition={setPanelState} variant="alternate">
38
+ <Flex cs={stylesOverride.viewport}>
39
+ <SidePanel {...panelProps} variant="alternate">
33
40
  <SidePanel.ToggleButton {...controlProps} />
34
- {panelState === 'expanded' ? (
35
- expandedContent
36
- ) : (
37
- <Text hidden {...labelProps}>
38
- Tasks Panel
39
- </Text>
40
- )}
41
+ <Flex cs={stylesOverride.panel}>
42
+ <Heading size="small" hidden={!expanded ? true : undefined} {...labelProps}>
43
+ Alternate Panel
44
+ </Heading>
45
+ </Flex>
41
46
  </SidePanel>
42
- <Flex
43
- as="main"
44
- alignItems="center"
45
- justifyContent="center"
46
- flexDirection="column"
47
- flex={1}
48
- flexBasis="auto"
49
- >
50
- <p>Toggle the content direction</p>
51
- <SecondaryButton onClick={toggleDirection} role="button">
47
+ <Flex as="main" cs={stylesOverride.main}>
48
+ <Text as="p" typeLevel="body.large">
49
+ Toggle the content direction
50
+ </Text>
51
+ <SecondaryButton onClick={toggleDirection}>
52
52
  Set to {direction === 'ltr' ? 'Right-to-Left' : 'Left-to-Right'}
53
53
  </SecondaryButton>
54
54
  </Flex>
@@ -5,7 +5,24 @@ import WithOverlay from './examples/SidePanelWithOverlay';
5
5
 
6
6
  # Canvas Kit Examples
7
7
 
8
- ## Side Panel With Navigation
8
+ ## Side Panel As Navigation
9
+
10
+ This example demonstrates SidePanel as a navigation system that can be reduced into a "compact view"
11
+ to save horizontal space on screen. It combines semantic HTML nested list markup with Canvas Kit's
12
+ `<Expandable>` component to create an accordion. When in compact view, the Canvas Kit `<Menu>`
13
+ component is used to create the fly-out menus. Both of these components are implemented according to
14
+ the [W3C ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/patterns/) to provide a
15
+ wide range of support for accessibility.
16
+
17
+ - The `<SidePanel>` uses the `as` prop to render with a semantic HTML `<nav>` element
18
+ - The SidePanel's heading element with the `labelProps` must remain in the DOM even while the
19
+ component is in compact view, else the `aria-labelledby` reference for the toggle button will
20
+ become invalid. The `hidden` attribute is conditionally set on the heading based on the `expanded`
21
+ state of the SidePanel provided by the `useSidePanel` hook.
22
+ - The semantic HTML nested list markup helps support non-visual screen reader users understand the
23
+ nested hierarchy of the elements inside the expandable containers
24
+ - In the compact view, the `<Tooltip>` component is used to provide an accessible name to the icon
25
+ button menu targets
9
26
 
10
27
  <ExampleCodeBlock code={WithNavigation} />
11
28
 
@@ -1,130 +1,168 @@
1
1
  import * as React from 'react';
2
- import {styled, StyledType} from '@workday/canvas-kit-react/common';
3
- import {colors, space, gradients, type} from '@workday/canvas-kit-react/tokens';
4
- import {SidePanel} from '@workday/canvas-kit-preview-react/side-panel';
5
- import {Flex, Box} from '@workday/canvas-kit-react/layout';
6
- import {BodyText, Subtext} from '@workday/canvas-kit-react/text';
2
+ import {base, system} from '@workday/canvas-tokens-web';
3
+ import {SidePanel, useSidePanel} from '@workday/canvas-kit-preview-react/side-panel';
4
+ import {Flex} from '@workday/canvas-kit-react/layout';
5
+ import {Heading, Subtext, Text} from '@workday/canvas-kit-react/text';
7
6
  import {Expandable} from '@workday/canvas-kit-labs-react/expandable';
8
7
  import {SystemIcon} from '@workday/canvas-kit-react/icon';
9
- import {birthdayIcon, ribbonIcon} from '@workday/canvas-system-icons-web';
8
+ import {Hyperlink, TertiaryButton} from '@workday/canvas-kit-react/button';
9
+ import {Menu} from '@workday/canvas-kit-react/menu';
10
+ import {birthdayIcon, checkIcon, ribbonIcon} from '@workday/canvas-system-icons-web';
11
+ import {createStyles, px2rem} from '@workday/canvas-kit-styling';
12
+ import {Tooltip} from '../../../../tooltip';
10
13
 
11
- const StyledPanel = styled(SidePanel.as('nav'))({
12
- backgroundColor: colors.soap200,
13
- zIndex: 1,
14
- });
15
-
16
- const StyledExpandable = styled(Expandable.Target)({
17
- borderRadius: 0,
18
- ':hover': {
19
- backgroundColor: colors.soap500,
14
+ const data = {
15
+ bestsellers: {
16
+ icon: ribbonIcon,
17
+ title: 'Best Sellers',
18
+ subtitle: 'Award winning sweet treats',
19
+ items: ['Mango Coco Sago', 'Matcha Creme Pie', 'Key Lime Cheesecake', 'Tiramisu'],
20
20
  },
21
- });
22
-
23
- const StyledLink = styled(Subtext.as('a'))<StyledType>({
24
- color: colors.blackPepper300,
25
- ':hover': {
26
- backgroundColor: colors.soap500,
21
+ cakes: {
22
+ icon: birthdayIcon,
23
+ title: 'Custom Cakes',
24
+ subtitle: 'To celebrate your life milestones',
25
+ items: ['Anniversary', 'Birthday', 'Graduation', 'Wedding'],
27
26
  },
28
- });
27
+ };
28
+
29
+ const stylesOverride = {
30
+ navContainer: createStyles({
31
+ height: px2rem(800),
32
+ positio: 'relative',
33
+ backgroundColor: base.frenchVanilla100,
34
+ }),
35
+ accordionContainer: createStyles({
36
+ flexDirection: 'column',
37
+ rowGap: system.space.zero,
38
+ paddingInlineStart: system.space.zero,
39
+ }),
40
+ accordionIcon: createStyles({
41
+ verticalAlign: 'middle',
42
+ padding: system.space.x1,
43
+ }),
44
+ accordionSubText: createStyles({
45
+ margin: system.space.zero,
46
+ }),
47
+ listContainer: createStyles({
48
+ listStyle: 'none',
49
+ padding: system.space.x4,
50
+ paddingTop: system.space.x16,
51
+ flexDirection: 'column',
52
+ }),
53
+ links: createStyles({
54
+ textDecoration: 'none',
55
+ padding: system.space.x4,
56
+ }),
57
+ linkCheck: createStyles({
58
+ marginLeft: 'auto',
59
+ }),
60
+ flyOut: createStyles({
61
+ marginTop: '8rem',
62
+ }),
63
+ };
64
+
65
+ const Accordion = ({config}) => {
66
+ const [currentPage, setCurrentPage] = React.useState('');
29
67
 
30
- const cakes = [
31
- {value: 'Anniversary', linkValue: '#AnniversaryCakes'},
32
- {value: 'Birthday', linkValue: '#BirthdayCakes'},
33
- {value: 'Graduation', linkValue: '#GraduationCakes'},
34
- {value: 'Wedding', linkValue: 'WeddingCakes'},
35
- ];
68
+ const handleClick = e => {
69
+ e.preventDefault();
70
+ setCurrentPage(e.target.textContent);
71
+ };
36
72
 
37
- const bestsellers = [
38
- {value: 'Mango Coco Sago', linkValue: '#LemonRhubarbBars'},
39
- {value: 'Matcha Creme Pie', linkValue: '#MatchaCremePie'},
40
- {value: 'Key Lime Cheesecake', linkValue: '#KeyLimeCheesecake'},
41
- {value: 'Tiramisu', linkValue: '#Tiramisu'},
42
- ];
73
+ return (
74
+ <Expandable>
75
+ <Expandable.Target>
76
+ <SystemIcon cs={stylesOverride.accordionIcon} icon={config.icon} />
77
+ <Expandable.Title>
78
+ {config.title}
79
+ <Subtext size="medium" cs={stylesOverride.accordionSubText}>
80
+ {config.subtitle}
81
+ </Subtext>
82
+ </Expandable.Title>
83
+ <Expandable.Icon iconPosition="end" />
84
+ </Expandable.Target>
85
+ <Expandable.Content as="ul" cs={stylesOverride.listContainer}>
86
+ {config.items.map(i => {
87
+ return (
88
+ <li key={i}>
89
+ <Flex
90
+ as="a"
91
+ href="#"
92
+ aria-current={i === currentPage ? 'true' : undefined}
93
+ className={stylesOverride.links}
94
+ onClick={handleClick}
95
+ >
96
+ {i}
97
+ {i === currentPage && <SystemIcon icon={checkIcon} cs={stylesOverride.linkCheck} />}
98
+ </Flex>
99
+ </li>
100
+ );
101
+ })}
102
+ </Expandable.Content>
103
+ </Expandable>
104
+ );
105
+ };
43
106
 
44
- const gettingStarted = [
45
- 'Extended Systems',
46
- 'Canvas Glossary',
47
- 'Frequently Asked Questions',
48
- 'Canvas Support',
49
- ];
107
+ const IconButtonMenu = ({config}) => {
108
+ return (
109
+ <Menu>
110
+ <Tooltip title={config.title} placement="right">
111
+ <Menu.Target as={TertiaryButton}>
112
+ <SystemIcon icon={config.icon} />
113
+ </Menu.Target>
114
+ </Tooltip>
115
+ <Menu.Popper placement="right">
116
+ <Menu.Card cs={stylesOverride.flyOut}>
117
+ <Menu.List>
118
+ {config.items.map(i => (
119
+ <Menu.Item>{i}</Menu.Item>
120
+ ))}
121
+ </Menu.List>
122
+ </Menu.Card>
123
+ </Menu.Popper>
124
+ </Menu>
125
+ );
126
+ };
127
+
128
+ const CompactView = () => {
129
+ return (
130
+ <Flex as="ul" cs={stylesOverride.listContainer}>
131
+ <Flex.Item as="li">
132
+ <IconButtonMenu config={data.bestsellers} />
133
+ </Flex.Item>
134
+ <Flex.Item as="li">
135
+ <IconButtonMenu config={data.cakes} />
136
+ </Flex.Item>
137
+ </Flex>
138
+ );
139
+ };
140
+
141
+ const ExpandedView = () => {
142
+ return (
143
+ <Flex as="ul" cs={stylesOverride.accordionContainer}>
144
+ <Flex.Item as="li">
145
+ <Accordion config={data.bestsellers} />
146
+ </Flex.Item>
147
+ <Flex.Item as="li">
148
+ <Accordion config={data.cakes} />
149
+ </Flex.Item>
150
+ </Flex>
151
+ );
152
+ };
50
153
 
51
154
  export default () => {
155
+ const {expanded, panelProps, labelProps, controlProps} = useSidePanel();
156
+
52
157
  return (
53
- <Flex height={800} position="relative" backgroundColor="frenchVanilla100">
54
- <StyledPanel touched={true} variant="alternate">
55
- <Flex as="ul" flexDirection="column" rowGap="zero" paddingInlineStart="zero">
56
- <Flex.Item as="li" listStyle="none">
57
- <Expandable padding="zero">
58
- <StyledExpandable paddingTop="m" paddingBottom="xxs" paddingX="m" textAlign="center">
59
- <SystemIcon icon={ribbonIcon} paddingRight="s" />
60
- <Expandable.Title padding="zero">
61
- <BodyText size="small" fontWeight="bold" color="blackpepper300" marginY="zero">
62
- Bestsellers
63
- </BodyText>
64
- <Subtext size="medium" color="blackpepper300" marginY="zero">
65
- Award winning sweet treats
66
- </Subtext>
67
- </Expandable.Title>
68
- <Expandable.Icon iconPosition="end" />
69
- </StyledExpandable>
70
- <Expandable.Content paddingY="zero" paddingX="zero" as="ul">
71
- {bestsellers.map(item => {
72
- return (
73
- <li>
74
- <StyledLink
75
- size="large"
76
- display="flex"
77
- textDecoration="none"
78
- paddingLeft="xxl"
79
- paddingTop="xxs"
80
- paddingBottom="zero"
81
- href={item.linkValue}
82
- >
83
- {item.value}
84
- </StyledLink>
85
- </li>
86
- );
87
- })}
88
- </Expandable.Content>
89
- </Expandable>
90
- </Flex.Item>
91
- <Flex.Item as="li" listStyle="none">
92
- <Expandable padding="zero">
93
- <StyledExpandable paddingTop="m" paddingBottom="xxs" paddingX="m" textAlign="center">
94
- <SystemIcon icon={birthdayIcon} paddingRight="s" />
95
- <Expandable.Title padding="zero">
96
- <BodyText size="small" fontWeight="bold" color="blackpepper300" marginY="zero">
97
- Custom Cakes
98
- </BodyText>
99
- <Subtext size="medium" color="blackpepper300" marginY="zero">
100
- To celebrate your life milestones
101
- </Subtext>
102
- </Expandable.Title>
103
- <Expandable.Icon iconPosition="end" />
104
- </StyledExpandable>
105
- <Expandable.Content paddingY="zero" paddingX="zero" as="ul">
106
- {cakes.map(item => {
107
- return (
108
- <li>
109
- <StyledLink
110
- size="large"
111
- display="flex"
112
- textDecoration="none"
113
- paddingLeft="xxl"
114
- paddingTop="xxs"
115
- paddingBottom="zero"
116
- href={item.linkValue}
117
- >
118
- {item.value}
119
- </StyledLink>
120
- </li>
121
- );
122
- })}
123
- </Expandable.Content>
124
- </Expandable>
125
- </Flex.Item>
126
- </Flex>
127
- </StyledPanel>
158
+ <Flex cs={stylesOverride.navContainer}>
159
+ <SidePanel as="nav" {...panelProps}>
160
+ <Heading size="small" {...labelProps} hidden={!expanded ? true : undefined}>
161
+ Cake or Death Bakery
162
+ </Heading>
163
+ <SidePanel.ToggleButton {...controlProps} />
164
+ {expanded ? <ExpandedView /> : <CompactView />}
165
+ </SidePanel>
128
166
  </Flex>
129
167
  );
130
168
  };
@@ -1,28 +1,46 @@
1
1
  import * as React from 'react';
2
- import {styled} from '@workday/canvas-kit-react/common';
3
- import {depth} from '@workday/canvas-kit-react/tokens';
4
2
  import {SidePanel, useSidePanel} from '@workday/canvas-kit-preview-react/side-panel';
5
3
  import {Flex, Box} from '@workday/canvas-kit-react/layout';
6
- import {Text} from '@workday/canvas-kit-react/text';
4
+ import {Heading} from '@workday/canvas-kit-react/text';
5
+ import {createStyles, px2rem} from '@workday/canvas-kit-styling';
6
+ import {system, base} from '@workday/canvas-tokens-web';
7
7
 
8
- const StyledPanel = styled(SidePanel)({
9
- ...depth[6],
10
- zIndex: 1,
11
- });
8
+ const stylesOverride = {
9
+ panelContainer: createStyles({
10
+ height: px2rem(320),
11
+ backgroundColor: base.soap100,
12
+ position: 'relative',
13
+ }),
14
+ panelContent: createStyles({
15
+ alignItems: 'center',
16
+ paddingY: system.space.x4,
17
+ paddingX: system.space.x4,
18
+ }),
19
+ panel: createStyles({
20
+ zIndex: 1,
21
+ }),
22
+ overlay: createStyles({
23
+ position: 'absolute',
24
+ background: system.color.bg.overlay,
25
+ height: '100%',
26
+ width: '100%',
27
+ }),
28
+ };
12
29
 
13
30
  export default () => {
14
- const {labelProps} = useSidePanel();
31
+ const {expanded, panelProps, labelProps, controlProps} = useSidePanel();
15
32
 
16
33
  return (
17
- <Flex height={320} backgroundColor="soap100" position="relative">
18
- <StyledPanel touched={true} variant="alternate">
19
- <Flex alignItems="center" paddingY="s" paddingX="s">
20
- <Text as="h3" typeLevel="body.large" fontWeight="bold" color="licorice500">
34
+ <Flex cs={stylesOverride.panelContainer}>
35
+ <SidePanel className={stylesOverride.panel} {...panelProps} variant="alternate">
36
+ <Flex cs={stylesOverride.panelContainer}>
37
+ <Heading size="small" {...labelProps} hidden={!expanded ? true : undefined}>
21
38
  Alternate Panel
22
- </Text>
39
+ </Heading>
40
+ <SidePanel.ToggleButton {...controlProps} />
23
41
  </Flex>
24
- </StyledPanel>
25
- <Box position="absolute" background="rgba(0,0,0,0.65)" height="100%" width="100%" />
42
+ </SidePanel>
43
+ {expanded && <Box cs={stylesOverride.overlay} />}
26
44
  </Flex>
27
45
  );
28
46
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workday/canvas-kit-docs",
3
- "version": "12.3.1",
3
+ "version": "12.3.3",
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,10 +44,10 @@
44
44
  "dependencies": {
45
45
  "@emotion/styled": "^11.6.0",
46
46
  "@storybook/csf": "0.0.1",
47
- "@workday/canvas-kit-labs-react": "^12.3.1",
48
- "@workday/canvas-kit-preview-react": "^12.3.1",
49
- "@workday/canvas-kit-react": "^12.3.1",
50
- "@workday/canvas-kit-styling": "^12.3.1",
47
+ "@workday/canvas-kit-labs-react": "^12.3.3",
48
+ "@workday/canvas-kit-preview-react": "^12.3.3",
49
+ "@workday/canvas-kit-react": "^12.3.3",
50
+ "@workday/canvas-kit-styling": "^12.3.3",
51
51
  "@workday/canvas-system-icons-web": "^3.0.0",
52
52
  "@workday/canvas-tokens-web": "^2.1.0",
53
53
  "markdown-to-jsx": "^7.2.0",
@@ -60,5 +60,5 @@
60
60
  "mkdirp": "^1.0.3",
61
61
  "typescript": "5.0"
62
62
  },
63
- "gitHead": "8f197dfdb262f224d73c602d6811d24302e6154c"
63
+ "gitHead": "813b84599c30a0c575cbdd5f958fbf5321412c90"
64
64
  }