@workday/canvas-kit-docs 16.0.0-alpha.0465-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/es6/lib/stackblitzFiles/packageJSONFile.js +5 -5
- package/dist/es6/lib/stackblitzFiles/packageJSONFile.ts +5 -5
- package/dist/mdx/16.0-UPGRADE-GUIDE.mdx +46 -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
|
@@ -18,11 +18,11 @@ export const packageJSONFile = `{
|
|
|
18
18
|
"@emotion/react": "11.11.4",
|
|
19
19
|
"@types/react": "18.2.60",
|
|
20
20
|
"@types/react-dom": "18.2.19",
|
|
21
|
-
"@workday/canvas-kit-labs-react": "15.1.
|
|
22
|
-
"@workday/canvas-kit-preview-react": "15.1.
|
|
23
|
-
"@workday/canvas-kit-react": "15.1.
|
|
24
|
-
"@workday/canvas-kit-react-fonts": "^15.1.
|
|
25
|
-
"@workday/canvas-kit-styling": "15.1.
|
|
21
|
+
"@workday/canvas-kit-labs-react": "15.1.3",
|
|
22
|
+
"@workday/canvas-kit-preview-react": "15.1.3",
|
|
23
|
+
"@workday/canvas-kit-react": "15.1.3",
|
|
24
|
+
"@workday/canvas-kit-react-fonts": "^15.1.3",
|
|
25
|
+
"@workday/canvas-kit-styling": "15.1.3",
|
|
26
26
|
"@workday/canvas-system-icons-web": "4.0.2",
|
|
27
27
|
"@workday/canvas-expressive-icons-web": "1.0.1",
|
|
28
28
|
"@workday/canvas-tokens-web": "4.2.0"
|
|
@@ -19,11 +19,11 @@ export const packageJSONFile = `{
|
|
|
19
19
|
"@emotion/react": "11.11.4",
|
|
20
20
|
"@types/react": "18.2.60",
|
|
21
21
|
"@types/react-dom": "18.2.19",
|
|
22
|
-
"@workday/canvas-kit-labs-react": "15.1.
|
|
23
|
-
"@workday/canvas-kit-preview-react": "15.1.
|
|
24
|
-
"@workday/canvas-kit-react": "15.1.
|
|
25
|
-
"@workday/canvas-kit-react-fonts": "^15.1.
|
|
26
|
-
"@workday/canvas-kit-styling": "15.1.
|
|
22
|
+
"@workday/canvas-kit-labs-react": "15.1.3",
|
|
23
|
+
"@workday/canvas-kit-preview-react": "15.1.3",
|
|
24
|
+
"@workday/canvas-kit-react": "15.1.3",
|
|
25
|
+
"@workday/canvas-kit-react-fonts": "^15.1.3",
|
|
26
|
+
"@workday/canvas-kit-styling": "15.1.3",
|
|
27
27
|
"@workday/canvas-system-icons-web": "4.0.2",
|
|
28
28
|
"@workday/canvas-expressive-icons-web": "1.0.1",
|
|
29
29
|
"@workday/canvas-tokens-web": "4.2.0"
|
|
@@ -14,8 +14,10 @@ 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)
|
|
20
|
+
- [Banner](#banner)
|
|
19
21
|
- [Avatar](#avatar)
|
|
20
22
|
- [Buttons](#buttons)
|
|
21
23
|
- [Delete Button Outline Variant](#delete-button-outline-variant)
|
|
@@ -32,6 +34,8 @@ Soon to be...
|
|
|
32
34
|
- [Text Area](#text-area)
|
|
33
35
|
- [Text Input](#text-input)
|
|
34
36
|
- [Menu](#menu)
|
|
37
|
+
- [Modal](#modal)
|
|
38
|
+
- [Popup](#popup)
|
|
35
39
|
- [Segmented Control](#segmented-control)
|
|
36
40
|
- [Toast](#toast)
|
|
37
41
|
- [Tooltip](#tooltip)
|
|
@@ -135,6 +139,28 @@ import {KBD} from '@workday/canvas-kit-labs-react';
|
|
|
135
139
|
For more details and advanced usage, including accessibility guidance for symbolic keys and
|
|
136
140
|
functional shortcuts, refer to the storybook documentation and our example stories.
|
|
137
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
|
+
|
|
138
164
|
## Component Updates
|
|
139
165
|
|
|
140
166
|
### Action Bar
|
|
@@ -145,6 +171,12 @@ functional shortcuts, refer to the storybook documentation and our example stori
|
|
|
145
171
|
|
|
146
172
|
- `ActionBar` padding has been updated to `padding.md` (16px).
|
|
147
173
|
|
|
174
|
+
### Banner
|
|
175
|
+
|
|
176
|
+
#### Visual Updates
|
|
177
|
+
|
|
178
|
+
- `Banner` now uses `system.depth[5]` for box-shadow (previously had no box-shadow).
|
|
179
|
+
|
|
148
180
|
### Avatar
|
|
149
181
|
|
|
150
182
|
**PR:** [#3981](https://github.com/Workday/canvas-kit/pull/3981)
|
|
@@ -355,6 +387,7 @@ If you customize `brand.success.base` in your theme, please verify the following
|
|
|
355
387
|
`Toast.Body` and `Toast.Icon`.
|
|
356
388
|
- Gap between the icon, body, and close icon is now `base.size150` (12px).
|
|
357
389
|
- Shape uses `system.shape.xl`.
|
|
390
|
+
- Box-shadow updated from `system.depth[3]` to `system.depth[5]`.
|
|
358
391
|
- `Toast.Body` no longer has a gap between text and link.
|
|
359
392
|
- `Toast.CloseIcon` is set to have absolute positioning and aligned with the top-right corner (in
|
|
360
393
|
LTR).
|
|
@@ -372,9 +405,22 @@ If you customize `brand.success.base` in your theme, please verify the following
|
|
|
372
405
|
- Tooltip boundaries remain visible in Windows High Contrast mode: when High Contrast is detected,
|
|
373
406
|
Tooltip uses a solid outline (`outline: solid 1px CanvasText`) to ensure clear visibility.
|
|
374
407
|
- Shape is now fully rounded using `system.shape.full`.
|
|
408
|
+
- Box-shadow updated from `system.depth[2]` to `system.depth[3]`.
|
|
375
409
|
- Type level is now `subtext.lg` (previously `subtext.md`).
|
|
376
410
|
- Padding and spacing have been adjusted to accommodate the new styling.
|
|
377
411
|
|
|
412
|
+
### Modal
|
|
413
|
+
|
|
414
|
+
#### Visual Updates
|
|
415
|
+
|
|
416
|
+
- `Modal.Card` box-shadow updated from `system.depth[5]` to `system.depth[6]`.
|
|
417
|
+
|
|
418
|
+
### Popup
|
|
419
|
+
|
|
420
|
+
#### Visual Updates
|
|
421
|
+
|
|
422
|
+
- `Popup.Card` box-shadow updated from `system.depth[3]` to `system.depth[4]`.
|
|
423
|
+
|
|
378
424
|
### Menu
|
|
379
425
|
|
|
380
426
|
**PR:** [#3987](https://github.com/Workday/canvas-kit/pull/3987)
|
|
@@ -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
|
+
};
|