@workday/canvas-kit-docs 16.0.0-alpha.0474-next.0 → 16.0.0-alpha.0475-next.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.
- package/dist/es6/lib/docs.js +22758 -2
- package/dist/mdx/16.0-UPGRADE-GUIDE.mdx +23 -0
- package/dist/mdx/preview-react/tabs/Tabs.mdx +136 -0
- package/dist/mdx/preview-react/tabs/examples/AlternativeTabStop.tsx +26 -0
- package/dist/mdx/preview-react/tabs/examples/Basic.tsx +24 -0
- package/dist/mdx/preview-react/tabs/examples/DisabledTab.tsx +20 -0
- package/dist/mdx/preview-react/tabs/examples/DynamicTabs.tsx +105 -0
- package/dist/mdx/preview-react/tabs/examples/HoistedModel.tsx +36 -0
- package/dist/mdx/preview-react/tabs/examples/Icons.tsx +35 -0
- package/dist/mdx/preview-react/tabs/examples/NamedTabs.tsx +24 -0
- package/dist/mdx/preview-react/tabs/examples/OutlinedTabs.tsx +24 -0
- package/dist/mdx/preview-react/tabs/examples/OverflowTabs.tsx +62 -0
- package/dist/mdx/preview-react/tabs/examples/RightToLeft.tsx +43 -0
- package/dist/mdx/preview-react/tabs/examples/SinglePanel.tsx +45 -0
- package/dist/mdx/react/tabs/Tabs.mdx +1 -1
- package/package.json +6 -6
|
@@ -14,6 +14,7 @@ Soon to be...
|
|
|
14
14
|
- [Instructions](#instructions)
|
|
15
15
|
- [New Components](#new-components)
|
|
16
16
|
- [KBD](#kbd)
|
|
17
|
+
- [Tabs](#tabs)
|
|
17
18
|
- [Component Updates](#component-updates)
|
|
18
19
|
- [Action Bar](#action-bar)
|
|
19
20
|
- [Banner](#banner)
|
|
@@ -138,6 +139,28 @@ import {KBD} from '@workday/canvas-kit-labs-react';
|
|
|
138
139
|
For more details and advanced usage, including accessibility guidance for symbolic keys and
|
|
139
140
|
functional shortcuts, refer to the storybook documentation and our example stories.
|
|
140
141
|
|
|
142
|
+
### Tabs
|
|
143
|
+
|
|
144
|
+
**PR:** [#4062](https://github.com/Workday/canvas-kit/pull/4062)
|
|
145
|
+
|
|
146
|
+
A new `Tabs` component has been added to `@workday/canvas-kit-preview-react`, aligned with the Sana
|
|
147
|
+
Canvas visual language. It supports `filled` and `outlined` variants.
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
import {Tabs} from '@workday/canvas-kit-preview-react/tabs';
|
|
151
|
+
|
|
152
|
+
<Tabs>
|
|
153
|
+
<Tabs.List>
|
|
154
|
+
<Tabs.Item>First Tab</Tabs.Item>
|
|
155
|
+
<Tabs.Item>Second Tab</Tabs.Item>
|
|
156
|
+
</Tabs.List>
|
|
157
|
+
<Tabs.Panels>
|
|
158
|
+
<Tabs.Panel>Contents of First Tab</Tabs.Panel>
|
|
159
|
+
<Tabs.Panel>Contents of Second Tab</Tabs.Panel>
|
|
160
|
+
</Tabs.Panels>
|
|
161
|
+
</Tabs>;
|
|
162
|
+
```
|
|
163
|
+
|
|
141
164
|
## Component Updates
|
|
142
165
|
|
|
143
166
|
### Action Bar
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import {ExampleCodeBlock, Specifications, SymbolDoc} from '@workday/canvas-kit-docs';
|
|
2
|
+
import AlternativeTabStop from './examples/AlternativeTabStop';
|
|
3
|
+
import Basic from './examples/Basic';
|
|
4
|
+
import DisabledTab from './examples/DisabledTab';
|
|
5
|
+
import DynamicTabs from './examples/DynamicTabs';
|
|
6
|
+
import HoistedModel from './examples/HoistedModel';
|
|
7
|
+
import Icons from './examples/Icons';
|
|
8
|
+
import NamedTabs from './examples/NamedTabs';
|
|
9
|
+
import OutlinedTabs from './examples/OutlinedTabs';
|
|
10
|
+
import OverflowTabs from './examples/OverflowTabs';
|
|
11
|
+
import RightToLeft from './examples/RightToLeft';
|
|
12
|
+
import SinglePanel from './examples/SinglePanel';
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Canvas Kit Tabs
|
|
16
|
+
|
|
17
|
+
`Tabs` is a [compound component](/get-started/for-developers/documentation/compound-components/)
|
|
18
|
+
that allows users to navigate between related views of content while remaining in context of the
|
|
19
|
+
page.
|
|
20
|
+
|
|
21
|
+
[> Workday Design Reference](https://design.workday.com/components/navigation/tabs)
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
yarn add @workday/canvas-kit-react
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
### Basic Example
|
|
32
|
+
|
|
33
|
+
`Tabs` includes a container `Tabs` component and the following subcomponents which can be composed
|
|
34
|
+
in a variety of ways: `Tabs.List`, `Tabs.Item` and `Tabs.Panel`. It follows the
|
|
35
|
+
[W3 Tabs specification](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/).
|
|
36
|
+
|
|
37
|
+
In this example, we set up a basic `Tabs` component with five tabs. This example uses a static API
|
|
38
|
+
that does not support overflow.
|
|
39
|
+
|
|
40
|
+
<ExampleCodeBlock code={Basic} />
|
|
41
|
+
|
|
42
|
+
### Outlined Tabs
|
|
43
|
+
|
|
44
|
+
Set the `variant` prop of `Tabs` to `outlined` to render an outlined style of tabs.
|
|
45
|
+
|
|
46
|
+
<ExampleCodeBlock code={OutlinedTabs} />
|
|
47
|
+
|
|
48
|
+
### Overflow Tabs
|
|
49
|
+
|
|
50
|
+
Tabs is a responsive component based on the width of its container. If the rendered tabs exceed the
|
|
51
|
+
width of the `Tabs.List`, an overflow menu will be rendered. This only works against the dynamic API
|
|
52
|
+
where you give the `TabsModel` an array of items to be rendered. The dynamic API handles the React
|
|
53
|
+
`key` for you based on the item's identifier. The dynamic API requires either an `id` on each item
|
|
54
|
+
object or a `getId` function that returns an identifier based on the item. The below example uses an
|
|
55
|
+
`id` property on each item.
|
|
56
|
+
|
|
57
|
+
The dynamic API takes in any object, but since nothing is known about your object, a
|
|
58
|
+
[render prop](https://reactjs.org/docs/render-props.html) is necessary to instruct a list how it
|
|
59
|
+
should render.
|
|
60
|
+
|
|
61
|
+
<ExampleCodeBlock code={OverflowTabs} />
|
|
62
|
+
|
|
63
|
+
### Hoisted Model
|
|
64
|
+
|
|
65
|
+
By default, `Tabs` will create and use its own [model](#model) internally. Alternatively, you may
|
|
66
|
+
configure your own model with `useTabsModel` and pass it to `Tabs` via the `model` prop. This
|
|
67
|
+
pattern is referred to as
|
|
68
|
+
[hoisting the model](/get-started/for-developers/documentation/compound-components/#configuring-a-model)
|
|
69
|
+
and provides direct access to its `state` and `events` outside of the `Tabs` component.
|
|
70
|
+
|
|
71
|
+
In this example, we set up external observation of the model state and create an external button to
|
|
72
|
+
trigger an event to change the active tab.
|
|
73
|
+
|
|
74
|
+
<ExampleCodeBlock code={HoistedModel} />
|
|
75
|
+
|
|
76
|
+
### Named Tabs
|
|
77
|
+
|
|
78
|
+
`Tabs.Item` and `Tabs.Panel` both take an optional `data-id` attribute that is used for the
|
|
79
|
+
`onActivate` callback. This example is identical to the Basic Example, but with tabs named using
|
|
80
|
+
`data-id` for the `Tabs.Item` and `Tabs.Panel` subcomponents.
|
|
81
|
+
|
|
82
|
+
<ExampleCodeBlock code={NamedTabs} />
|
|
83
|
+
|
|
84
|
+
### Right-to-Left (RTL)
|
|
85
|
+
|
|
86
|
+
`Tabs` supports right-to-left languages when specified in the `CanvasProvider` `theme`.
|
|
87
|
+
|
|
88
|
+
<ExampleCodeBlock code={RightToLeft} />
|
|
89
|
+
|
|
90
|
+
### Disabled Tab
|
|
91
|
+
|
|
92
|
+
Set the `disabled` prop of a `Tabs.Item` to `true` to disable it.
|
|
93
|
+
|
|
94
|
+
<ExampleCodeBlock code={DisabledTab} />
|
|
95
|
+
|
|
96
|
+
### Tab Icons
|
|
97
|
+
|
|
98
|
+
Tabs can have icons. Use the `Icon` and `Text` subcomponents.
|
|
99
|
+
|
|
100
|
+
<ExampleCodeBlock code={Icons} />
|
|
101
|
+
|
|
102
|
+
### Alternative Tab Stop
|
|
103
|
+
|
|
104
|
+
By default, tab panels are focusable for accessibility. If the contents of a tab panel have a
|
|
105
|
+
focusable element, you may disable this default behavior by setting the `tabIndex` prop of
|
|
106
|
+
`Tabs.Panel` to `undefined`. This example has a tab panel with a focusable button.
|
|
107
|
+
|
|
108
|
+
<ExampleCodeBlock code={AlternativeTabStop} />
|
|
109
|
+
|
|
110
|
+
### Single Tab Panel
|
|
111
|
+
|
|
112
|
+
The compound component pattern allows for advanced composition. For example, `Tabs` can be composed
|
|
113
|
+
to have only a single `Tabs.Panel` using attribute overrides and callbacks. More information about
|
|
114
|
+
attributes and callbacks can be found in the prop tables below for each subcomponent.
|
|
115
|
+
|
|
116
|
+
In this example, we use a hoisted model and the `activeTab` property of the state to show content
|
|
117
|
+
from the `contents` object.
|
|
118
|
+
|
|
119
|
+
<ExampleCodeBlock code={SinglePanel} />
|
|
120
|
+
|
|
121
|
+
### Dynamic Tabs
|
|
122
|
+
|
|
123
|
+
The `Tabs.Item` component takes in an optional `index` property if you want to specify the position
|
|
124
|
+
of a tab. If not defined, by default it will append tabs to the end. In this example, our tabs are
|
|
125
|
+
stored as an array in the state, and we have a fixed tab at the end that can add new tabs to that
|
|
126
|
+
array.
|
|
127
|
+
|
|
128
|
+
<ExampleCodeBlock code={DynamicTabs} />
|
|
129
|
+
|
|
130
|
+
## Component API
|
|
131
|
+
|
|
132
|
+
<SymbolDoc name="Tabs" fileName="/react/" />
|
|
133
|
+
|
|
134
|
+
## Specifications
|
|
135
|
+
|
|
136
|
+
<Specifications file="./cypress/component/Tabs.spec.tsx" name="Tabs" />
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {Tabs} from '@workday/canvas-kit-preview-react/tabs';
|
|
2
|
+
import {cssVar} from '@workday/canvas-kit-styling';
|
|
3
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
4
|
+
|
|
5
|
+
export default () => {
|
|
6
|
+
return (
|
|
7
|
+
<Tabs>
|
|
8
|
+
<Tabs.List>
|
|
9
|
+
<Tabs.Item>First Tab</Tabs.Item>
|
|
10
|
+
<Tabs.Item>Second Tab</Tabs.Item>
|
|
11
|
+
<Tabs.Item>Third Tab</Tabs.Item>
|
|
12
|
+
</Tabs.List>
|
|
13
|
+
<div style={{marginBlock: cssVar(system.gap.lg)}}>
|
|
14
|
+
<Tabs.Panel tabIndex={undefined}>
|
|
15
|
+
<button>Focusable button</button>
|
|
16
|
+
<br />
|
|
17
|
+
Contents of First Tab. The tab panel is no longer focusable, but the button is. It may be
|
|
18
|
+
desirable to disable focus on the tab panel and allow focus to flow into the tab panel to
|
|
19
|
+
the first focusable element.
|
|
20
|
+
</Tabs.Panel>
|
|
21
|
+
<Tabs.Panel>Contents of Second Tab</Tabs.Panel>
|
|
22
|
+
<Tabs.Panel>Contents of Third Tab</Tabs.Panel>
|
|
23
|
+
</div>
|
|
24
|
+
</Tabs>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {Tabs} from '@workday/canvas-kit-preview-react/tabs';
|
|
2
|
+
import {cssVar} from '@workday/canvas-kit-styling';
|
|
3
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
4
|
+
|
|
5
|
+
export default () => {
|
|
6
|
+
return (
|
|
7
|
+
<Tabs>
|
|
8
|
+
<Tabs.List>
|
|
9
|
+
<Tabs.Item>First Tab</Tabs.Item>
|
|
10
|
+
<Tabs.Item>Second Tab</Tabs.Item>
|
|
11
|
+
<Tabs.Item>Third Tab</Tabs.Item>
|
|
12
|
+
<Tabs.Item>Fourth Tab</Tabs.Item>
|
|
13
|
+
<Tabs.Item>Fifth Tab</Tabs.Item>
|
|
14
|
+
</Tabs.List>
|
|
15
|
+
<div style={{marginBlockStart: cssVar(system.gap.lg)}}>
|
|
16
|
+
<Tabs.Panel>Contents of First Tab</Tabs.Panel>
|
|
17
|
+
<Tabs.Panel>Contents of Second Tab</Tabs.Panel>
|
|
18
|
+
<Tabs.Panel>Contents of Third Tab</Tabs.Panel>
|
|
19
|
+
<Tabs.Panel>Contents of Fourth Tab</Tabs.Panel>
|
|
20
|
+
<Tabs.Panel>Contents of Fifth Tab</Tabs.Panel>
|
|
21
|
+
</div>
|
|
22
|
+
</Tabs>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {Tabs} from '@workday/canvas-kit-preview-react/tabs';
|
|
2
|
+
import {cssVar} from '@workday/canvas-kit-styling';
|
|
3
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
4
|
+
|
|
5
|
+
export default () => {
|
|
6
|
+
return (
|
|
7
|
+
<Tabs>
|
|
8
|
+
<Tabs.List>
|
|
9
|
+
<Tabs.Item>First Tab</Tabs.Item>
|
|
10
|
+
<Tabs.Item aria-disabled>Disabled Tab</Tabs.Item>
|
|
11
|
+
<Tabs.Item>Third Tab</Tabs.Item>
|
|
12
|
+
</Tabs.List>
|
|
13
|
+
<div style={{marginBlockStart: cssVar(system.gap.lg)}}>
|
|
14
|
+
<Tabs.Panel>Contents of First Tab</Tabs.Panel>
|
|
15
|
+
<Tabs.Panel>Contents of Disabled Tab</Tabs.Panel>
|
|
16
|
+
<Tabs.Panel>Contents of Third Tab</Tabs.Panel>
|
|
17
|
+
</div>
|
|
18
|
+
</Tabs>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {Tabs, useTabsModel} from '@workday/canvas-kit-preview-react/tabs';
|
|
4
|
+
import {isCursor} from '@workday/canvas-kit-react/collection';
|
|
5
|
+
import {slugify} from '@workday/canvas-kit-react/common';
|
|
6
|
+
import {px2rem} from '@workday/canvas-kit-styling';
|
|
7
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
8
|
+
|
|
9
|
+
type Tab = {
|
|
10
|
+
tab: string;
|
|
11
|
+
id: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default () => {
|
|
15
|
+
const [tabs, setTabs] = React.useState<Tab[]>([
|
|
16
|
+
{tab: 'Tab 1', id: 'tab-1'},
|
|
17
|
+
{tab: 'Tab 2', id: 'tab-2'},
|
|
18
|
+
{tab: 'Tab 3', id: 'tab-3'},
|
|
19
|
+
{tab: 'Add Tab', id: 'add'},
|
|
20
|
+
]);
|
|
21
|
+
const addedRef = React.useRef(tabs.length - 1);
|
|
22
|
+
const model = useTabsModel({
|
|
23
|
+
items: tabs,
|
|
24
|
+
getTextValue: item => item.tab,
|
|
25
|
+
shouldSelect: data => data.id !== 'add',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// A ref of the model for the render functions to work around the caching done to lists
|
|
29
|
+
const modelRef = React.useRef(model);
|
|
30
|
+
modelRef.current = model;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Helper function that should be called when an item is programmatically removed. The following
|
|
34
|
+
* side effects depend on state of the model:
|
|
35
|
+
* * **Item is focused**: Focus will be moved to next item in the list
|
|
36
|
+
* * **Item is selected**: Selection will be moved to the next item in the list
|
|
37
|
+
* @param id The id of the item that will be removed
|
|
38
|
+
*/
|
|
39
|
+
const removeItem = <T extends unknown>(id: string, model: ReturnType<typeof useTabsModel>) => {
|
|
40
|
+
const index = model.state.items.findIndex(item => isCursor(model.state, item.id));
|
|
41
|
+
const nextIndex = index === model.state.items.length - 1 ? index - 1 : index + 1;
|
|
42
|
+
const nextId = model.state.items[nextIndex].id;
|
|
43
|
+
if (model.state.selectedIds[0] === id) {
|
|
44
|
+
// We're removing the currently selected item. Select next item
|
|
45
|
+
model.events.select({id: nextId});
|
|
46
|
+
}
|
|
47
|
+
if (isCursor(model.state, id)) {
|
|
48
|
+
// We're removing the currently focused item. Focus next item
|
|
49
|
+
model.events.goTo({id: nextId});
|
|
50
|
+
|
|
51
|
+
// wait for stabilization of state
|
|
52
|
+
requestAnimationFrame(() => {
|
|
53
|
+
document
|
|
54
|
+
.querySelector<HTMLElement>(`[id="${slugify(`${model.state.id}-${nextId}`)}"]`)
|
|
55
|
+
?.focus();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const onKeyDown = (id: string) => (e: React.KeyboardEvent<HTMLElement>) => {
|
|
61
|
+
if ((e.key === 'Delete' || e.key === 'Backspace') && id !== 'add') {
|
|
62
|
+
setTabs(tabs.filter(item => item.id !== id));
|
|
63
|
+
const model = modelRef.current;
|
|
64
|
+
removeItem(id, model);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const onClick = (id: string) => (e: React.MouseEvent) => {
|
|
69
|
+
if (id === 'add') {
|
|
70
|
+
addedRef.current += 1;
|
|
71
|
+
setTabs(tabs => {
|
|
72
|
+
const newTabs = tabs.slice(0, tabs.length - 1);
|
|
73
|
+
const addTab = tabs.slice(-1);
|
|
74
|
+
return newTabs.concat(
|
|
75
|
+
{tab: `Tab ${addedRef.current}`, id: `tab-${addedRef.current}`},
|
|
76
|
+
addTab
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<Tabs model={model}>
|
|
84
|
+
<Tabs.List overflowButton={<Tabs.OverflowButton>More</Tabs.OverflowButton>}>
|
|
85
|
+
{(item: Tab) => (
|
|
86
|
+
<Tabs.Item onKeyDown={onKeyDown(item.id)} onClick={onClick(item.id)}>
|
|
87
|
+
{item.tab}
|
|
88
|
+
</Tabs.Item>
|
|
89
|
+
)}
|
|
90
|
+
</Tabs.List>
|
|
91
|
+
<Tabs.Menu.Popper>
|
|
92
|
+
<Tabs.Menu.Card cs={{maxWidth: px2rem(300), maxHeight: px2rem(200)}}>
|
|
93
|
+
<Tabs.Menu.List>
|
|
94
|
+
{(item: Tab) => <Tabs.Menu.Item>{item.tab}</Tabs.Menu.Item>}
|
|
95
|
+
</Tabs.Menu.List>
|
|
96
|
+
</Tabs.Menu.Card>
|
|
97
|
+
</Tabs.Menu.Popper>
|
|
98
|
+
<Tabs.Panels>
|
|
99
|
+
{(item: Tab) => (
|
|
100
|
+
<Tabs.Panel cs={{marginBlockStart: system.gap.lg}}>Contents of {item.tab}</Tabs.Panel>
|
|
101
|
+
)}
|
|
102
|
+
</Tabs.Panels>
|
|
103
|
+
</Tabs>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {Tabs, useTabsModel} from '@workday/canvas-kit-preview-react/tabs';
|
|
2
|
+
import {SecondaryButton} from '@workday/canvas-kit-react/button';
|
|
3
|
+
import {cssVar} from '@workday/canvas-kit-styling';
|
|
4
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
5
|
+
|
|
6
|
+
export default () => {
|
|
7
|
+
const model = useTabsModel({
|
|
8
|
+
onSelect(data, prevState) {
|
|
9
|
+
console.log('Selected Tab', data.id, prevState);
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<>
|
|
15
|
+
<Tabs model={model}>
|
|
16
|
+
<Tabs.List>
|
|
17
|
+
<Tabs.Item data-id="first">First Tab</Tabs.Item>
|
|
18
|
+
<Tabs.Item data-id="second">Second Tab</Tabs.Item>
|
|
19
|
+
<Tabs.Item data-id="third">Third Tab</Tabs.Item>
|
|
20
|
+
</Tabs.List>
|
|
21
|
+
<div style={{marginBlockStart: cssVar(system.gap.lg)}}>
|
|
22
|
+
<Tabs.Panel data-id="first">Contents of First Tab</Tabs.Panel>
|
|
23
|
+
<Tabs.Panel data-id="second">Contents of Second Tab</Tabs.Panel>
|
|
24
|
+
<Tabs.Panel data-id="third">Contents of Third Tab</Tabs.Panel>
|
|
25
|
+
</div>
|
|
26
|
+
</Tabs>
|
|
27
|
+
<SecondaryButton
|
|
28
|
+
onClick={() => {
|
|
29
|
+
model.events.select({id: 'third'});
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
Select Third Tab
|
|
33
|
+
</SecondaryButton>
|
|
34
|
+
</>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {Tabs} from '@workday/canvas-kit-preview-react/tabs';
|
|
2
|
+
import {cssVar} from '@workday/canvas-kit-styling';
|
|
3
|
+
import {searchIcon, selectIcon, shareIcon, starIcon} from '@workday/canvas-system-icons-web';
|
|
4
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
5
|
+
|
|
6
|
+
export default () => {
|
|
7
|
+
return (
|
|
8
|
+
<Tabs>
|
|
9
|
+
<Tabs.List>
|
|
10
|
+
<Tabs.Item>
|
|
11
|
+
<Tabs.Item.Icon icon={starIcon} />
|
|
12
|
+
<Tabs.Item.Text>First Tab</Tabs.Item.Text>
|
|
13
|
+
</Tabs.Item>
|
|
14
|
+
<Tabs.Item>
|
|
15
|
+
<Tabs.Item.Icon icon={searchIcon} />
|
|
16
|
+
<Tabs.Item.Text>Second Tab</Tabs.Item.Text>
|
|
17
|
+
</Tabs.Item>
|
|
18
|
+
<Tabs.Item>
|
|
19
|
+
<Tabs.Item.Icon icon={selectIcon} />
|
|
20
|
+
<Tabs.Item.Text>Third Tab</Tabs.Item.Text>
|
|
21
|
+
</Tabs.Item>
|
|
22
|
+
<Tabs.Item>
|
|
23
|
+
<Tabs.Item.Icon icon={shareIcon} />
|
|
24
|
+
<Tabs.Item.Text>Fourth Tab</Tabs.Item.Text>
|
|
25
|
+
</Tabs.Item>
|
|
26
|
+
</Tabs.List>
|
|
27
|
+
<div style={{marginBlockStart: cssVar(system.gap.lg)}}>
|
|
28
|
+
<Tabs.Panel>Contents of First Tab</Tabs.Panel>
|
|
29
|
+
<Tabs.Panel>Contents of Second Tab</Tabs.Panel>
|
|
30
|
+
<Tabs.Panel>Contents of Third Tab</Tabs.Panel>
|
|
31
|
+
<Tabs.Panel>Contents of Fourth Tab</Tabs.Panel>
|
|
32
|
+
</div>
|
|
33
|
+
</Tabs>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {Tabs} from '@workday/canvas-kit-preview-react/tabs';
|
|
2
|
+
import {cssVar} from '@workday/canvas-kit-styling';
|
|
3
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
4
|
+
|
|
5
|
+
export default () => {
|
|
6
|
+
return (
|
|
7
|
+
<Tabs>
|
|
8
|
+
<Tabs.List>
|
|
9
|
+
<Tabs.Item data-id="first">First Tab</Tabs.Item>
|
|
10
|
+
<Tabs.Item data-id="second">Second Tab</Tabs.Item>
|
|
11
|
+
<Tabs.Item data-id="third">Third Tab</Tabs.Item>
|
|
12
|
+
<Tabs.Item data-id="fourth">Fourth Tab</Tabs.Item>
|
|
13
|
+
<Tabs.Item data-id="fifth">Fifth Tab</Tabs.Item>
|
|
14
|
+
</Tabs.List>
|
|
15
|
+
<div style={{marginBlockStart: cssVar(system.gap.lg)}}>
|
|
16
|
+
<Tabs.Panel data-id="first">Contents of First Tab</Tabs.Panel>
|
|
17
|
+
<Tabs.Panel data-id="second">Contents of Second Tab</Tabs.Panel>
|
|
18
|
+
<Tabs.Panel data-id="third">Contents of Third Tab</Tabs.Panel>
|
|
19
|
+
<Tabs.Panel data-id="fourth">Contents of Fourth Tab</Tabs.Panel>
|
|
20
|
+
<Tabs.Panel data-id="fifth">Contents of Fifth Tab</Tabs.Panel>
|
|
21
|
+
</div>
|
|
22
|
+
</Tabs>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {Tabs} from '@workday/canvas-kit-preview-react/tabs';
|
|
2
|
+
import {cssVar} from '@workday/canvas-kit-styling';
|
|
3
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
4
|
+
|
|
5
|
+
export default () => {
|
|
6
|
+
return (
|
|
7
|
+
<Tabs variant="outlined">
|
|
8
|
+
<Tabs.List>
|
|
9
|
+
<Tabs.Item>First Tab</Tabs.Item>
|
|
10
|
+
<Tabs.Item>Second Tab</Tabs.Item>
|
|
11
|
+
<Tabs.Item>Third Tab</Tabs.Item>
|
|
12
|
+
<Tabs.Item>Fourth Tab</Tabs.Item>
|
|
13
|
+
<Tabs.Item>Fifth Tab</Tabs.Item>
|
|
14
|
+
</Tabs.List>
|
|
15
|
+
<div style={{marginBlockStart: cssVar(system.gap.lg)}}>
|
|
16
|
+
<Tabs.Panel>Contents of First Tab</Tabs.Panel>
|
|
17
|
+
<Tabs.Panel>Contents of Second Tab</Tabs.Panel>
|
|
18
|
+
<Tabs.Panel>Contents of Third Tab</Tabs.Panel>
|
|
19
|
+
<Tabs.Panel>Contents of Fourth Tab</Tabs.Panel>
|
|
20
|
+
<Tabs.Panel>Contents of Fifth Tab</Tabs.Panel>
|
|
21
|
+
</div>
|
|
22
|
+
</Tabs>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {Tabs, useTabsModel} from '@workday/canvas-kit-preview-react/tabs';
|
|
4
|
+
import {Box} from '@workday/canvas-kit-react/layout';
|
|
5
|
+
import {SegmentedControl} from '@workday/canvas-kit-react/segmented-control';
|
|
6
|
+
import {px2rem} from '@workday/canvas-kit-styling';
|
|
7
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
8
|
+
|
|
9
|
+
type MyTabItem = {
|
|
10
|
+
id: string;
|
|
11
|
+
text: React.ReactNode;
|
|
12
|
+
contents: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default () => {
|
|
16
|
+
const [items] = React.useState<MyTabItem[]>([
|
|
17
|
+
{id: 'first', text: 'First Tab', contents: 'Contents of First Tab'},
|
|
18
|
+
{id: 'second', text: 'Second Tab', contents: 'Contents of Second Tab'},
|
|
19
|
+
{id: 'third', text: 'Third Tab', contents: 'Contents of Third Tab'},
|
|
20
|
+
{id: 'fourth', text: 'Fourth Tab', contents: 'Contents of Fourth Tab'},
|
|
21
|
+
{id: 'fifth', text: 'Fifth Tab', contents: 'Contents of Fifth Tab'},
|
|
22
|
+
{id: 'sixth', text: 'Sixth Tab', contents: 'Contents of Sixth Tab'},
|
|
23
|
+
{id: 'seventh', text: 'Seventh Tab', contents: 'Contents of Seventh Tab'},
|
|
24
|
+
]);
|
|
25
|
+
const model = useTabsModel({
|
|
26
|
+
items,
|
|
27
|
+
});
|
|
28
|
+
const [containerWidth, setContainerWidth] = React.useState('100%');
|
|
29
|
+
return (
|
|
30
|
+
<div>
|
|
31
|
+
<Box cs={{width: containerWidth, marginBlockEnd: system.gap.xl}}>
|
|
32
|
+
<Tabs model={model}>
|
|
33
|
+
<Tabs.List overflowButton={<Tabs.OverflowButton>More</Tabs.OverflowButton>}>
|
|
34
|
+
{(item: MyTabItem) => <Tabs.Item>{item.text}</Tabs.Item>}
|
|
35
|
+
</Tabs.List>
|
|
36
|
+
<Tabs.Menu.Popper>
|
|
37
|
+
<Tabs.Menu.Card cs={{maxWidth: px2rem(300), maxHeight: px2rem(200)}}>
|
|
38
|
+
<Tabs.Menu.List>
|
|
39
|
+
{(item: MyTabItem) => <Tabs.Menu.Item>{item.text}</Tabs.Menu.Item>}
|
|
40
|
+
</Tabs.Menu.List>
|
|
41
|
+
</Tabs.Menu.Card>
|
|
42
|
+
</Tabs.Menu.Popper>
|
|
43
|
+
<Tabs.Panels>
|
|
44
|
+
{(item: MyTabItem) => (
|
|
45
|
+
<Tabs.Panel cs={{marginBlockStart: system.gap.lg}}>{item.contents}</Tabs.Panel>
|
|
46
|
+
)}
|
|
47
|
+
</Tabs.Panels>
|
|
48
|
+
</Tabs>
|
|
49
|
+
</Box>
|
|
50
|
+
<hr />
|
|
51
|
+
<h4>Change Tabs container size</h4>
|
|
52
|
+
<SegmentedControl onSelect={data => setContainerWidth(data.id)}>
|
|
53
|
+
<SegmentedControl.List aria-label="container width control">
|
|
54
|
+
<SegmentedControl.Item data-id="100%">100%</SegmentedControl.Item>
|
|
55
|
+
<SegmentedControl.Item data-id="500px">500px</SegmentedControl.Item>
|
|
56
|
+
<SegmentedControl.Item data-id="360px">360px</SegmentedControl.Item>
|
|
57
|
+
<SegmentedControl.Item data-id="150px">150px</SegmentedControl.Item>
|
|
58
|
+
</SegmentedControl.List>
|
|
59
|
+
</SegmentedControl>
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {Tabs} from '@workday/canvas-kit-preview-react/tabs';
|
|
2
|
+
import {CanvasProvider} from '@workday/canvas-kit-react/common';
|
|
3
|
+
import {cssVar} from '@workday/canvas-kit-styling';
|
|
4
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
5
|
+
|
|
6
|
+
export default () => {
|
|
7
|
+
return (
|
|
8
|
+
<CanvasProvider dir="rtl">
|
|
9
|
+
<Tabs>
|
|
10
|
+
<Tabs.List>
|
|
11
|
+
<Tabs.Item>ראשון</Tabs.Item>
|
|
12
|
+
<Tabs.Item>שְׁנִיָה</Tabs.Item>
|
|
13
|
+
<Tabs.Item>שְׁלִישִׁי</Tabs.Item>
|
|
14
|
+
<Tabs.Item>רביעי</Tabs.Item>
|
|
15
|
+
<Tabs.Item>חמישי</Tabs.Item>
|
|
16
|
+
</Tabs.List>
|
|
17
|
+
<div style={{marginBlock: cssVar(system.gap.lg)}}>
|
|
18
|
+
<Tabs.Panel>תוכן הראשון</Tabs.Panel>
|
|
19
|
+
<Tabs.Panel>תוכן השני</Tabs.Panel>
|
|
20
|
+
<Tabs.Panel>תוכן השלישי</Tabs.Panel>
|
|
21
|
+
<Tabs.Panel>תוכן הרביעי</Tabs.Panel>
|
|
22
|
+
<Tabs.Panel>תוכן החמישי</Tabs.Panel>
|
|
23
|
+
</div>
|
|
24
|
+
</Tabs>
|
|
25
|
+
<Tabs variant="outlined">
|
|
26
|
+
<Tabs.List>
|
|
27
|
+
<Tabs.Item>ראשון</Tabs.Item>
|
|
28
|
+
<Tabs.Item>שְׁנִיָה</Tabs.Item>
|
|
29
|
+
<Tabs.Item>שְׁלִישִׁי</Tabs.Item>
|
|
30
|
+
<Tabs.Item>רביעי</Tabs.Item>
|
|
31
|
+
<Tabs.Item>חמישי</Tabs.Item>
|
|
32
|
+
</Tabs.List>
|
|
33
|
+
<div style={{marginBlock: cssVar(system.gap.lg)}}>
|
|
34
|
+
<Tabs.Panel>תוכן הראשון</Tabs.Panel>
|
|
35
|
+
<Tabs.Panel>תוכן השני</Tabs.Panel>
|
|
36
|
+
<Tabs.Panel>תוכן השלישי</Tabs.Panel>
|
|
37
|
+
<Tabs.Panel>תוכן הרביעי</Tabs.Panel>
|
|
38
|
+
<Tabs.Panel>תוכן החמישי</Tabs.Panel>
|
|
39
|
+
</div>
|
|
40
|
+
</Tabs>
|
|
41
|
+
</CanvasProvider>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {Tabs, useTabsModel} from '@workday/canvas-kit-preview-react/tabs';
|
|
2
|
+
import {slugify} from '@workday/canvas-kit-react/common';
|
|
3
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
4
|
+
|
|
5
|
+
export default () => {
|
|
6
|
+
const model = useTabsModel();
|
|
7
|
+
|
|
8
|
+
const message = (
|
|
9
|
+
<p>
|
|
10
|
+
This example shows how to use a single tab panel. You must manually set the{' '}
|
|
11
|
+
<code>hidden</code>, <code>aria-controls</code>, and <code>id</code> attributes of Tab item
|
|
12
|
+
and Tab panel components
|
|
13
|
+
</p>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const contents = {
|
|
17
|
+
first: <div>Contents of First Tab {message}</div>,
|
|
18
|
+
second: <div>Contents of Second Tab {message}</div>,
|
|
19
|
+
third: <div>Contents of Third Tab {message}</div>,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Tabs model={model}>
|
|
24
|
+
<Tabs.List>
|
|
25
|
+
<Tabs.Item data-id="first" aria-controls="mytab-panel">
|
|
26
|
+
First Tab
|
|
27
|
+
</Tabs.Item>
|
|
28
|
+
<Tabs.Item data-id="second" aria-controls="mytab-panel">
|
|
29
|
+
Second Tab
|
|
30
|
+
</Tabs.Item>
|
|
31
|
+
<Tabs.Item data-id="third" aria-controls="mytab-panel">
|
|
32
|
+
Third Tab
|
|
33
|
+
</Tabs.Item>
|
|
34
|
+
</Tabs.List>
|
|
35
|
+
<Tabs.Panel
|
|
36
|
+
cs={{marginBlockStart: system.gap.lg}}
|
|
37
|
+
hidden={undefined}
|
|
38
|
+
id="mytab-panel"
|
|
39
|
+
aria-labelledby={slugify(`${model.state.id}-${model.state.selectedIds[0]}`)}
|
|
40
|
+
>
|
|
41
|
+
{contents[model.state.selectedIds[0]]}
|
|
42
|
+
</Tabs.Panel>
|
|
43
|
+
</Tabs>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
@@ -69,7 +69,7 @@ trigger an event to change the active tab.
|
|
|
69
69
|
### Named Tabs
|
|
70
70
|
|
|
71
71
|
`Tabs.Item` and `Tabs.Panel` both take an optional `data-id` attribute that is used for the
|
|
72
|
-
`
|
|
72
|
+
`onSelect` callback. This example is identical to the Basic Example, but with tabs named using
|
|
73
73
|
`data-id` for the `Tabs.Item` and `Tabs.Panel` subcomponents.
|
|
74
74
|
|
|
75
75
|
<ExampleCodeBlock code={NamedTabs} />
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workday/canvas-kit-docs",
|
|
3
|
-
"version": "16.0.0-alpha.
|
|
3
|
+
"version": "16.0.0-alpha.0475-next.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",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"@stackblitz/sdk": "^1.11.0",
|
|
48
48
|
"@storybook/csf": "0.0.1",
|
|
49
49
|
"@workday/canvas-expressive-icons-web": "1.0.2",
|
|
50
|
-
"@workday/canvas-kit-labs-react": "^16.0.0-alpha.
|
|
51
|
-
"@workday/canvas-kit-preview-react": "^16.0.0-alpha.
|
|
52
|
-
"@workday/canvas-kit-react": "^16.0.0-alpha.
|
|
53
|
-
"@workday/canvas-kit-styling": "^16.0.0-alpha.
|
|
50
|
+
"@workday/canvas-kit-labs-react": "^16.0.0-alpha.0475-next.0",
|
|
51
|
+
"@workday/canvas-kit-preview-react": "^16.0.0-alpha.0475-next.0",
|
|
52
|
+
"@workday/canvas-kit-react": "^16.0.0-alpha.0475-next.0",
|
|
53
|
+
"@workday/canvas-kit-styling": "^16.0.0-alpha.0475-next.0",
|
|
54
54
|
"@workday/canvas-system-icons-web": "4.0.4",
|
|
55
55
|
"@workday/canvas-tokens-web": "4.4.0-beta.6",
|
|
56
56
|
"markdown-to-jsx": "^7.2.0",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"mkdirp": "^1.0.3",
|
|
64
64
|
"typescript": "5.0"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "82422d46f689844113866ba99ffad38956bde57c"
|
|
67
67
|
}
|