@workday/canvas-kit-mcp 15.1.6 → 15.1.7
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/apps/action-bar.html +1 -1
- package/dist/apps/breadcrumbs.html +1 -1
- package/dist/apps/tabs.html +29 -28
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -18,7 +18,7 @@ import { z } from "zod";
|
|
|
18
18
|
// package.json
|
|
19
19
|
var package_default = {
|
|
20
20
|
name: "@workday/canvas-kit-mcp",
|
|
21
|
-
version: "15.1.
|
|
21
|
+
version: "15.1.7",
|
|
22
22
|
description: "MCP package for Canvas Kit",
|
|
23
23
|
author: "Workday, Inc. (https://www.workday.com)",
|
|
24
24
|
license: "Apache-2.0",
|
|
@@ -378,7 +378,7 @@ var stories_config_default = {
|
|
|
378
378
|
title: "Components/Containers/Tabs",
|
|
379
379
|
storybookUrl: "https://workday.github.io/canvas-kit/?path=/docs/components-containers-tabs--docs",
|
|
380
380
|
mdxPath: "modules/react/tabs/stories/Tabs.mdx",
|
|
381
|
-
mdxProse: "# Canvas Kit Tabs\n\n`Tabs` is a [compound component](/get-started/for-developers/documentation/compound-components/)\nthat allows users to navigate between related views of content while remaining in context of the\npage.\n\n[> Workday Design Reference](https://design.workday.com/components/navigation/tabs)\n\n## Installation\n\n```sh\nyarn add @workday/canvas-kit-react\n```\n\n## Usage\n\n### Basic Example\n\n`Tabs` includes a container `Tabs` component and the following subcomponents which can be composed\nin a variety of ways: `Tabs.List`, `Tabs.Item` and `Tabs.Panel`. It follows the\n[W3 Tabs specification](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/).\n\nIn this example, we set up a basic `Tabs` component with five tabs. This example uses a static API\nthat does not support overflow.\n```tsx\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const Basic = () => {\n return (\n <Tabs>\n <Tabs.List>\n <Tabs.Item>First Tab</Tabs.Item>\n <Tabs.Item>Second Tab</Tabs.Item>\n <Tabs.Item>Third Tab</Tabs.Item>\n <Tabs.Item>Fourth Tab</Tabs.Item>\n <Tabs.Item>Fifth Tab</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel>Contents of First Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Second Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Third Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Fourth Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Fifth Tab</Tabs.Panel>\n </div>\n </Tabs>\n );\n};\n```\n\n### Overflow Tabs\n\nTabs is a responsive component based on the width of its container. If the rendered tabs exceed the\nwidth of the `Tabs.List`, an overflow menu will be rendered. This only works against the dynamic API\nwhere you give the `TabsModel` an array of items to be rendered. The dynamic API handles the React\n`key` for you based on the item's identifier. The dynamic API requires either an `id` on each item\nobject or a `getId` function that returns an identifier based on the item. The below example uses an\n`id` property on each item.\n\nThe dynamic API takes in any object, but since nothing is known about your object, a\n[render prop](https://reactjs.org/docs/render-props.html) is necessary to instruct a list how it\nshould render.\n```tsx\nimport React from 'react';\n\nimport {Box} from '@workday/canvas-kit-react/layout';\nimport {SegmentedControl} from '@workday/canvas-kit-react/segmented-control';\nimport {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';\nimport {px2rem} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\ntype MyTabItem = {\n id: string;\n text: React.ReactNode;\n contents: string;\n};\n\nexport const OverflowTabs = () => {\n const [items] = React.useState<MyTabItem[]>([\n {id: 'first', text: 'First Tab', contents: 'Contents of First Tab'},\n {id: 'second', text: 'Second Tab', contents: 'Contents of Second Tab'},\n {id: 'third', text: 'Third Tab', contents: 'Contents of Third Tab'},\n {id: 'fourth', text: 'Fourth Tab', contents: 'Contents of Fourth Tab'},\n {id: 'fifth', text: 'Fifth Tab', contents: 'Contents of Fifth Tab'},\n {id: 'sixth', text: 'Sixth Tab', contents: 'Contents of Sixth Tab'},\n {id: 'seventh', text: 'Seventh Tab', contents: 'Contents of Seventh Tab'},\n ]);\n const model = useTabsModel({\n items,\n });\n const [containerWidth, setContainerWidth] = React.useState('100%');\n return (\n <div>\n <Box cs={{width: containerWidth, marginBlockEnd: system.gap.xl}}>\n <Tabs model={model}>\n <Tabs.List overflowButton={<Tabs.OverflowButton>More</Tabs.OverflowButton>}>\n {(item: MyTabItem) => <Tabs.Item>{item.text}</Tabs.Item>}\n </Tabs.List>\n <Tabs.Menu.Popper>\n <Tabs.Menu.Card cs={{maxWidth: px2rem(300), maxHeight: px2rem(200)}}>\n <Tabs.Menu.List>\n {(item: MyTabItem) => <Tabs.Menu.Item>{item.text}</Tabs.Menu.Item>}\n </Tabs.Menu.List>\n </Tabs.Menu.Card>\n </Tabs.Menu.Popper>\n <Tabs.Panels>\n {(item: MyTabItem) => (\n <Tabs.Panel cs={{marginBlockStart: system.gap.lg}}>{item.contents}</Tabs.Panel>\n )}\n </Tabs.Panels>\n </Tabs>\n </Box>\n <hr />\n <h4>Change Tabs container size</h4>\n <SegmentedControl onSelect={data => setContainerWidth(data.id)}>\n <SegmentedControl.List aria-label=\"container width control\">\n <SegmentedControl.Item data-id=\"100%\">100%</SegmentedControl.Item>\n <SegmentedControl.Item data-id=\"500px\">500px</SegmentedControl.Item>\n <SegmentedControl.Item data-id=\"360px\">360px</SegmentedControl.Item>\n <SegmentedControl.Item data-id=\"150px\">150px</SegmentedControl.Item>\n </SegmentedControl.List>\n </SegmentedControl>\n </div>\n );\n};\n```\n\n### Hoisted Model\n\nBy default, `Tabs` will create and use its own [model](#model) internally. Alternatively, you may\nconfigure your own model with `useTabsModel` and pass it to `Tabs` via the `model` prop. This\npattern is referred to as\n[hoisting the model](/get-started/for-developers/documentation/compound-components/#configuring-a-model)\nand provides direct access to its `state` and `events` outside of the `Tabs` component.\n\nIn this example, we set up external observation of the model state and create an external button to\ntrigger an event to change the active tab.\n```tsx\nimport {SecondaryButton} from '@workday/canvas-kit-react/button';\nimport {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const HoistedModel = () => {\n const model = useTabsModel({\n onSelect(data, prevState) {\n console.log('Selected Tab', data.id, prevState);\n },\n });\n\n return (\n <>\n <Tabs model={model}>\n <Tabs.List>\n <Tabs.Item data-id=\"first\">First Tab</Tabs.Item>\n <Tabs.Item data-id=\"second\">Second Tab</Tabs.Item>\n <Tabs.Item data-id=\"third\">Third Tab</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel data-id=\"first\">Contents of First Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"second\">Contents of Second Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"third\">Contents of Third Tab</Tabs.Panel>\n </div>\n </Tabs>\n <SecondaryButton\n onClick={() => {\n model.events.select({id: 'third'});\n }}\n >\n Select Third Tab\n </SecondaryButton>\n </>\n );\n};\n```\n\n### Named Tabs\n\n`Tabs.Item` and `Tabs.Panel` both take an optional `data-id` attribute that is used for the\n`onActivate` callback. This example is identical to the Basic Example, but with tabs named using\n`data-id` for the `Tabs.Item` and `Tabs.Panel` subcomponents.\n```tsx\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const NamedTabs = () => {\n return (\n <Tabs>\n <Tabs.List>\n <Tabs.Item data-id=\"first\">First Tab</Tabs.Item>\n <Tabs.Item data-id=\"second\">Second Tab</Tabs.Item>\n <Tabs.Item data-id=\"third\">Third Tab</Tabs.Item>\n <Tabs.Item data-id=\"fourth\">Fourth Tab</Tabs.Item>\n <Tabs.Item data-id=\"fifth\">Fifth Tab</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel data-id=\"first\">Contents of First Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"second\">Contents of Second Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"third\">Contents of Third Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"fourth\">Contents of Fourth Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"fifth\">Contents of Fifth Tab</Tabs.Panel>\n </div>\n </Tabs>\n );\n};\n```\n\n### Right-to-Left (RTL)\n\n`Tabs` supports right-to-left languages when specified in the `CanvasProvider` `theme`.\n```tsx\nimport {CanvasProvider} from '@workday/canvas-kit-react/common';\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const RightToLeft = () => {\n return (\n <CanvasProvider dir=\"rtl\">\n <Tabs>\n <Tabs.List>\n <Tabs.Item>\u05E8\u05D0\u05E9\u05D5\u05DF</Tabs.Item>\n <Tabs.Item>\u05E9\u05C1\u05B0\u05E0\u05B4\u05D9\u05B8\u05D4</Tabs.Item>\n <Tabs.Item>\u05E9\u05C1\u05B0\u05DC\u05B4\u05D9\u05E9\u05C1\u05B4\u05D9</Tabs.Item>\n <Tabs.Item>\u05E8\u05D1\u05D9\u05E2\u05D9</Tabs.Item>\n <Tabs.Item>\u05D7\u05DE\u05D9\u05E9\u05D9</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel>\u05EA\u05D5\u05DB\u05DF \u05D4\u05E8\u05D0\u05E9\u05D5\u05DF</Tabs.Panel>\n <Tabs.Panel>\u05EA\u05D5\u05DB\u05DF \u05D4\u05E9\u05E0\u05D9</Tabs.Panel>\n <Tabs.Panel>\u05EA\u05D5\u05DB\u05DF \u05D4\u05E9\u05DC\u05D9\u05E9\u05D9</Tabs.Panel>\n <Tabs.Panel>\u05EA\u05D5\u05DB\u05DF \u05D4\u05E8\u05D1\u05D9\u05E2\u05D9</Tabs.Panel>\n <Tabs.Panel>\u05EA\u05D5\u05DB\u05DF \u05D4\u05D7\u05DE\u05D9\u05E9\u05D9</Tabs.Panel>\n </div>\n </Tabs>\n </CanvasProvider>\n );\n};\n```\n\n### Disabled Tab\n\nSet the `disabled` prop of a `Tabs.Item` to `true` to disable it.\n```tsx\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const DisabledTab = () => {\n return (\n <Tabs>\n <Tabs.List>\n <Tabs.Item>First Tab</Tabs.Item>\n <Tabs.Item aria-disabled>Disabled Tab</Tabs.Item>\n <Tabs.Item>Third Tab</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel>Contents of First Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Disabled Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Third Tab</Tabs.Panel>\n </div>\n </Tabs>\n );\n};\n```\n\n### Tab Icons\n\nTabs can have icons. Use the `Icon` and `Text` subcomponents.\n```tsx\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {searchIcon, selectIcon, shareIcon, starIcon} from '@workday/canvas-system-icons-web';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const Icons = () => {\n return (\n <Tabs>\n <Tabs.List>\n <Tabs.Item>\n <Tabs.Item.Icon icon={starIcon} />\n <Tabs.Item.Text>First Tab</Tabs.Item.Text>\n </Tabs.Item>\n <Tabs.Item>\n <Tabs.Item.Icon icon={searchIcon} />\n <Tabs.Item.Text>Second Tab</Tabs.Item.Text>\n </Tabs.Item>\n <Tabs.Item>\n <Tabs.Item.Icon icon={selectIcon} />\n <Tabs.Item.Text>Third Tab</Tabs.Item.Text>\n </Tabs.Item>\n <Tabs.Item>\n <Tabs.Item.Icon icon={shareIcon} />\n <Tabs.Item.Text>Fourth Tab</Tabs.Item.Text>\n </Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel>Contents of First Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Second Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Third Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Fourth Tab</Tabs.Panel>\n </div>\n </Tabs>\n );\n};\n```\n\n### Alternative Tab Stop\n\nBy default, tab panels are focusable for accessibility. If the contents of a tab panel have a\nfocusable element, you may disable this default behavior by setting the `tabIndex` prop of\n`Tabs.Panel` to `undefined`. This example has a tab panel with a focusable button.\n```tsx\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const AlternativeTabStop = () => {\n return (\n <Tabs>\n <Tabs.List>\n <Tabs.Item>First Tab</Tabs.Item>\n <Tabs.Item>Second Tab</Tabs.Item>\n <Tabs.Item>Third Tab</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel tabIndex={undefined}>\n <button>Focusable button</button>\n <br />\n Contents of First Tab. The tab panel is no longer focusable, but the button is. It may be\n desirable to disable focus on the tab panel and allow focus to flow into the tab panel to\n the first focusable element.\n </Tabs.Panel>\n <Tabs.Panel>Contents of Second Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Third Tab</Tabs.Panel>\n </div>\n </Tabs>\n );\n};\n```\n\n### Single Tab Panel\n\nThe compound component pattern allows for advanced composition. For example, `Tabs` can be composed\nto have only a single `Tabs.Panel` using attribute overrides and callbacks. More information about\nattributes and callbacks can be found in the prop tables below for each subcomponent.\n\nIn this example, we use a hoisted model and the `activeTab` property of the state to show content\nfrom the `contents` object.\n```tsx\nimport {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const SinglePanel = () => {\n const model = useTabsModel();\n\n const message = (\n <p>\n This example shows how to use a single tab panel. You must manually set the{' '}\n <code>hidden</code>, <code>aria-controls</code>, and <code>id</code> attributes of Tab item\n and Tab panel components\n </p>\n );\n\n const contents = {\n first: <div>Contents of First Tab {message}</div>,\n second: <div>Contents of Second Tab {message}</div>,\n third: <div>Contents of Third Tab {message}</div>,\n };\n\n return (\n <Tabs model={model}>\n <Tabs.List>\n <Tabs.Item data-id=\"first\" aria-controls=\"mytab-panel\">\n First Tab\n </Tabs.Item>\n <Tabs.Item data-id=\"second\" aria-controls=\"mytab-panel\">\n Second Tab\n </Tabs.Item>\n <Tabs.Item data-id=\"third\" aria-controls=\"mytab-panel\">\n Third Tab\n </Tabs.Item>\n </Tabs.List>\n <Tabs.Panel cs={{marginBlockStart: system.gap.lg}} hidden={undefined} id=\"mytab-panel\">\n {contents[model.state.selectedIds[0]]}\n </Tabs.Panel>\n </Tabs>\n );\n};\n```\n\n### Dynamic Tabs\n\nThe `Tabs.Item` component takes in an optional `index` property if you want to specify the position\nof a tab. If not defined, by default it will append tabs to the end. In this example, our tabs are\nstored as an array in the state, and we have a fixed tab at the end that can add new tabs to that\narray.\n```tsx\nimport React from 'react';\n\nimport {isCursor} from '@workday/canvas-kit-react/collection';\nimport {slugify} from '@workday/canvas-kit-react/common';\nimport {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';\nimport {px2rem} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\ntype Tab = {\n tab: string;\n id: string;\n};\n\nexport const DynamicTabs = () => {\n const [tabs, setTabs] = React.useState<Tab[]>([\n {tab: 'Tab 1', id: 'tab-1'},\n {tab: 'Tab 2', id: 'tab-2'},\n {tab: 'Tab 3', id: 'tab-3'},\n {tab: 'Add Tab', id: 'add'},\n ]);\n const addedRef = React.useRef(tabs.length - 1);\n const model = useTabsModel({\n items: tabs,\n getTextValue: item => item.tab,\n shouldSelect: data => data.id !== 'add',\n });\n\n // A ref of the model for the render functions to work around the caching done to lists\n const modelRef = React.useRef(model);\n modelRef.current = model;\n\n /**\n * Helper function that should be called when an item is programmatically removed. The following\n * side effects depend on state of the model:\n * * **Item is focused**: Focus will be moved to next item in the list\n * * **Item is selected**: Selection will be moved to the next item in the list\n * @param id The id of the item that will be removed\n */\n const removeItem = <T extends unknown>(id: string, model: ReturnType<typeof useTabsModel>) => {\n const index = model.state.items.findIndex(item => isCursor(model.state, item.id));\n const nextIndex = index === model.state.items.length - 1 ? index - 1 : index + 1;\n const nextId = model.state.items[nextIndex].id;\n if (model.state.selectedIds[0] === id) {\n // We're removing the currently selected item. Select next item\n model.events.select({id: nextId});\n }\n if (isCursor(model.state, id)) {\n // We're removing the currently focused item. Focus next item\n model.events.goTo({id: nextId});\n\n // wait for stabilization of state\n requestAnimationFrame(() => {\n document\n .querySelector<HTMLElement>(`[id=\"${slugify(`${model.state.id}-${nextId}`)}\"]`)\n ?.focus();\n });\n }\n };\n\n const onKeyDown = (id: string) => (e: React.KeyboardEvent<HTMLElement>) => {\n if ((e.key === 'Delete' || e.key === 'Backspace') && id !== 'add') {\n setTabs(tabs.filter(item => item.id !== id));\n const model = modelRef.current;\n removeItem(id, model);\n }\n };\n\n const onClick = (id: string) => (e: React.MouseEvent) => {\n if (id === 'add') {\n addedRef.current += 1;\n setTabs(tabs => {\n const newTabs = tabs.slice(0, tabs.length - 1);\n const addTab = tabs.slice(-1);\n return newTabs.concat(\n {tab: `Tab ${addedRef.current}`, id: `tab-${addedRef.current}`},\n addTab\n );\n });\n }\n };\n\n return (\n <Tabs model={model}>\n <Tabs.List overflowButton={<Tabs.OverflowButton>More</Tabs.OverflowButton>}>\n {(item: Tab) => (\n <Tabs.Item onKeyDown={onKeyDown(item.id)} onClick={onClick(item.id)}>\n {item.tab}\n </Tabs.Item>\n )}\n </Tabs.List>\n <Tabs.Menu.Popper>\n <Tabs.Menu.Card cs={{maxWidth: px2rem(300), maxHeight: px2rem(200)}}>\n <Tabs.Menu.List>\n {(item: Tab) => <Tabs.Menu.Item>{item.tab}</Tabs.Menu.Item>}\n </Tabs.Menu.List>\n </Tabs.Menu.Card>\n </Tabs.Menu.Popper>\n <Tabs.Panels>\n {(item: Tab) => (\n <Tabs.Panel cs={{marginBlockStart: system.gap.lg}}>Contents of {item.tab}</Tabs.Panel>\n )}\n </Tabs.Panels>\n </Tabs>\n );\n};\n```\n\n## Component API\n\n## Specifications\n\n",
|
|
381
|
+
mdxProse: "# Canvas Kit Tabs\n\n`Tabs` is a [compound component](/get-started/for-developers/documentation/compound-components/)\nthat allows users to navigate between related views of content while remaining in context of the\npage.\n\n[> Workday Design Reference](https://design.workday.com/components/navigation/tabs)\n\n## Installation\n\n```sh\nyarn add @workday/canvas-kit-react\n```\n\n## Usage\n\n### Basic Example\n\n`Tabs` includes a container `Tabs` component and the following subcomponents which can be composed\nin a variety of ways: `Tabs.List`, `Tabs.Item` and `Tabs.Panel`. It follows the\n[W3 Tabs specification](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/).\n\nIn this example, we set up a basic `Tabs` component with five tabs. This example uses a static API\nthat does not support overflow.\n```tsx\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const Basic = () => {\n return (\n <Tabs>\n <Tabs.List>\n <Tabs.Item>First Tab</Tabs.Item>\n <Tabs.Item>Second Tab</Tabs.Item>\n <Tabs.Item>Third Tab</Tabs.Item>\n <Tabs.Item>Fourth Tab</Tabs.Item>\n <Tabs.Item>Fifth Tab</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel>Contents of First Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Second Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Third Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Fourth Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Fifth Tab</Tabs.Panel>\n </div>\n </Tabs>\n );\n};\n```\n\n### Overflow Tabs\n\nTabs is a responsive component based on the width of its container. If the rendered tabs exceed the\nwidth of the `Tabs.List`, an overflow menu will be rendered. This only works against the dynamic API\nwhere you give the `TabsModel` an array of items to be rendered. The dynamic API handles the React\n`key` for you based on the item's identifier. The dynamic API requires either an `id` on each item\nobject or a `getId` function that returns an identifier based on the item. The below example uses an\n`id` property on each item.\n\nThe dynamic API takes in any object, but since nothing is known about your object, a\n[render prop](https://reactjs.org/docs/render-props.html) is necessary to instruct a list how it\nshould render.\n```tsx\nimport React from 'react';\n\nimport {Box} from '@workday/canvas-kit-react/layout';\nimport {SegmentedControl} from '@workday/canvas-kit-react/segmented-control';\nimport {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';\nimport {px2rem} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\ntype MyTabItem = {\n contextId: string;\n text: React.ReactNode;\n contents: string;\n};\n\nexport const OverflowTabs = () => {\n const [items] = React.useState<MyTabItem[]>([\n {contextId: 'first', text: 'First Tab', contents: 'Contents of First Tab'},\n {contextId: 'second', text: 'Second Tab', contents: 'Contents of Second Tab'},\n {contextId: 'third', text: 'Third Tab', contents: 'Contents of Third Tab'},\n {contextId: 'fourth', text: 'Fourth Tab', contents: 'Contents of Fourth Tab'},\n {contextId: 'fifth', text: 'Fifth Tab', contents: 'Contents of Fifth Tab'},\n {contextId: 'sixth', text: 'Sixth Tab', contents: 'Contents of Sixth Tab'},\n {contextId: 'seventh', text: 'Seventh Tab', contents: 'Contents of Seventh Tab'},\n ]);\n const model = useTabsModel({\n items,\n getId: (item: MyTabItem) => item.contextId,\n });\n const [containerWidth, setContainerWidth] = React.useState('100%');\n return (\n <div>\n <Box cs={{width: containerWidth, marginBlockEnd: system.gap.xl}}>\n <Tabs model={model}>\n <Tabs.List overflowButton={<Tabs.OverflowButton>More</Tabs.OverflowButton>}>\n {(item: MyTabItem) => <Tabs.Item>{item.text}</Tabs.Item>}\n </Tabs.List>\n <Tabs.Menu.Popper>\n <Tabs.Menu.Card cs={{maxWidth: px2rem(300), maxHeight: px2rem(200)}}>\n <Tabs.Menu.List>\n {(item: MyTabItem) => <Tabs.Menu.Item>{item.text}</Tabs.Menu.Item>}\n </Tabs.Menu.List>\n </Tabs.Menu.Card>\n </Tabs.Menu.Popper>\n <Tabs.Panels>\n {(item: MyTabItem) => (\n <Tabs.Panel cs={{marginBlockStart: system.gap.lg}}>{item.contents}</Tabs.Panel>\n )}\n </Tabs.Panels>\n </Tabs>\n </Box>\n <hr />\n <h4>Change Tabs container size</h4>\n <SegmentedControl onSelect={data => setContainerWidth(data.id)}>\n <SegmentedControl.List aria-label=\"container width control\">\n <SegmentedControl.Item data-id=\"100%\">100%</SegmentedControl.Item>\n <SegmentedControl.Item data-id=\"500px\">500px</SegmentedControl.Item>\n <SegmentedControl.Item data-id=\"360px\">360px</SegmentedControl.Item>\n <SegmentedControl.Item data-id=\"150px\">150px</SegmentedControl.Item>\n </SegmentedControl.List>\n </SegmentedControl>\n </div>\n );\n};\n```\n\n### Hoisted Model\n\nBy default, `Tabs` will create and use its own [model](#model) internally. Alternatively, you may\nconfigure your own model with `useTabsModel` and pass it to `Tabs` via the `model` prop. This\npattern is referred to as\n[hoisting the model](/get-started/for-developers/documentation/compound-components/#configuring-a-model)\nand provides direct access to its `state` and `events` outside of the `Tabs` component.\n\nIn this example, we set up external observation of the model state and create an external button to\ntrigger an event to change the active tab.\n```tsx\nimport {SecondaryButton} from '@workday/canvas-kit-react/button';\nimport {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const HoistedModel = () => {\n const model = useTabsModel({\n onSelect(data, prevState) {\n console.log('Selected Tab', data.id, prevState);\n },\n });\n\n return (\n <>\n <Tabs model={model}>\n <Tabs.List>\n <Tabs.Item data-id=\"first\">First Tab</Tabs.Item>\n <Tabs.Item data-id=\"second\">Second Tab</Tabs.Item>\n <Tabs.Item data-id=\"third\">Third Tab</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel data-id=\"first\">Contents of First Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"second\">Contents of Second Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"third\">Contents of Third Tab</Tabs.Panel>\n </div>\n </Tabs>\n <SecondaryButton\n onClick={() => {\n model.events.select({id: 'third'});\n }}\n >\n Select Third Tab\n </SecondaryButton>\n </>\n );\n};\n```\n\n### Named Tabs\n\n`Tabs.Item` and `Tabs.Panel` both take an optional `data-id` attribute that is used for the\n`onActivate` callback. This example is identical to the Basic Example, but with tabs named using\n`data-id` for the `Tabs.Item` and `Tabs.Panel` subcomponents.\n```tsx\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const NamedTabs = () => {\n return (\n <Tabs>\n <Tabs.List>\n <Tabs.Item data-id=\"first\">First Tab</Tabs.Item>\n <Tabs.Item data-id=\"second\">Second Tab</Tabs.Item>\n <Tabs.Item data-id=\"third\">Third Tab</Tabs.Item>\n <Tabs.Item data-id=\"fourth\">Fourth Tab</Tabs.Item>\n <Tabs.Item data-id=\"fifth\">Fifth Tab</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel data-id=\"first\">Contents of First Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"second\">Contents of Second Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"third\">Contents of Third Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"fourth\">Contents of Fourth Tab</Tabs.Panel>\n <Tabs.Panel data-id=\"fifth\">Contents of Fifth Tab</Tabs.Panel>\n </div>\n </Tabs>\n );\n};\n```\n\n### Right-to-Left (RTL)\n\n`Tabs` supports right-to-left languages when specified in the `CanvasProvider` `theme`.\n```tsx\nimport {CanvasProvider} from '@workday/canvas-kit-react/common';\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const RightToLeft = () => {\n return (\n <CanvasProvider dir=\"rtl\">\n <Tabs>\n <Tabs.List>\n <Tabs.Item>\u05E8\u05D0\u05E9\u05D5\u05DF</Tabs.Item>\n <Tabs.Item>\u05E9\u05C1\u05B0\u05E0\u05B4\u05D9\u05B8\u05D4</Tabs.Item>\n <Tabs.Item>\u05E9\u05C1\u05B0\u05DC\u05B4\u05D9\u05E9\u05C1\u05B4\u05D9</Tabs.Item>\n <Tabs.Item>\u05E8\u05D1\u05D9\u05E2\u05D9</Tabs.Item>\n <Tabs.Item>\u05D7\u05DE\u05D9\u05E9\u05D9</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel>\u05EA\u05D5\u05DB\u05DF \u05D4\u05E8\u05D0\u05E9\u05D5\u05DF</Tabs.Panel>\n <Tabs.Panel>\u05EA\u05D5\u05DB\u05DF \u05D4\u05E9\u05E0\u05D9</Tabs.Panel>\n <Tabs.Panel>\u05EA\u05D5\u05DB\u05DF \u05D4\u05E9\u05DC\u05D9\u05E9\u05D9</Tabs.Panel>\n <Tabs.Panel>\u05EA\u05D5\u05DB\u05DF \u05D4\u05E8\u05D1\u05D9\u05E2\u05D9</Tabs.Panel>\n <Tabs.Panel>\u05EA\u05D5\u05DB\u05DF \u05D4\u05D7\u05DE\u05D9\u05E9\u05D9</Tabs.Panel>\n </div>\n </Tabs>\n </CanvasProvider>\n );\n};\n```\n\n### Disabled Tab\n\nSet the `disabled` prop of a `Tabs.Item` to `true` to disable it.\n```tsx\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const DisabledTab = () => {\n return (\n <Tabs>\n <Tabs.List>\n <Tabs.Item>First Tab</Tabs.Item>\n <Tabs.Item aria-disabled>Disabled Tab</Tabs.Item>\n <Tabs.Item>Third Tab</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel>Contents of First Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Disabled Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Third Tab</Tabs.Panel>\n </div>\n </Tabs>\n );\n};\n```\n\n### Tab Icons\n\nTabs can have icons. Use the `Icon` and `Text` subcomponents.\n```tsx\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {searchIcon, selectIcon, shareIcon, starIcon} from '@workday/canvas-system-icons-web';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const Icons = () => {\n return (\n <Tabs>\n <Tabs.List>\n <Tabs.Item>\n <Tabs.Item.Icon icon={starIcon} />\n <Tabs.Item.Text>First Tab</Tabs.Item.Text>\n </Tabs.Item>\n <Tabs.Item>\n <Tabs.Item.Icon icon={searchIcon} />\n <Tabs.Item.Text>Second Tab</Tabs.Item.Text>\n </Tabs.Item>\n <Tabs.Item>\n <Tabs.Item.Icon icon={selectIcon} />\n <Tabs.Item.Text>Third Tab</Tabs.Item.Text>\n </Tabs.Item>\n <Tabs.Item>\n <Tabs.Item.Icon icon={shareIcon} />\n <Tabs.Item.Text>Fourth Tab</Tabs.Item.Text>\n </Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel>Contents of First Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Second Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Third Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Fourth Tab</Tabs.Panel>\n </div>\n </Tabs>\n );\n};\n```\n\n### Alternative Tab Stop\n\nBy default, tab panels are focusable for accessibility. If the contents of a tab panel have a\nfocusable element, you may disable this default behavior by setting the `tabIndex` prop of\n`Tabs.Panel` to `undefined`. This example has a tab panel with a focusable button.\n```tsx\nimport {Tabs} from '@workday/canvas-kit-react/tabs';\nimport {cssVar} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const AlternativeTabStop = () => {\n return (\n <Tabs>\n <Tabs.List>\n <Tabs.Item>First Tab</Tabs.Item>\n <Tabs.Item>Second Tab</Tabs.Item>\n <Tabs.Item>Third Tab</Tabs.Item>\n </Tabs.List>\n <div style={{marginBlockStart: cssVar(system.gap.lg)}}>\n <Tabs.Panel tabIndex={undefined}>\n <button>Focusable button</button>\n <br />\n Contents of First Tab. The tab panel is no longer focusable, but the button is. It may be\n desirable to disable focus on the tab panel and allow focus to flow into the tab panel to\n the first focusable element.\n </Tabs.Panel>\n <Tabs.Panel>Contents of Second Tab</Tabs.Panel>\n <Tabs.Panel>Contents of Third Tab</Tabs.Panel>\n </div>\n </Tabs>\n );\n};\n```\n\n### Single Tab Panel\n\nThe compound component pattern allows for advanced composition. For example, `Tabs` can be composed\nto have only a single `Tabs.Panel` using attribute overrides and callbacks. More information about\nattributes and callbacks can be found in the prop tables below for each subcomponent.\n\nIn this example, we use a hoisted model and the `activeTab` property of the state to show content\nfrom the `contents` object.\n```tsx\nimport {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';\nimport {system} from '@workday/canvas-tokens-web';\n\nexport const SinglePanel = () => {\n const model = useTabsModel();\n\n const message = (\n <p>\n This example shows how to use a single tab panel. You must manually set the{' '}\n <code>hidden</code>, <code>aria-controls</code>, and <code>id</code> attributes of Tab item\n and Tab panel components\n </p>\n );\n\n const contents = {\n first: <div>Contents of First Tab {message}</div>,\n second: <div>Contents of Second Tab {message}</div>,\n third: <div>Contents of Third Tab {message}</div>,\n };\n\n return (\n <Tabs model={model}>\n <Tabs.List>\n <Tabs.Item data-id=\"first\" aria-controls=\"mytab-panel\">\n First Tab\n </Tabs.Item>\n <Tabs.Item data-id=\"second\" aria-controls=\"mytab-panel\">\n Second Tab\n </Tabs.Item>\n <Tabs.Item data-id=\"third\" aria-controls=\"mytab-panel\">\n Third Tab\n </Tabs.Item>\n </Tabs.List>\n <Tabs.Panel cs={{marginBlockStart: system.gap.lg}} hidden={undefined} id=\"mytab-panel\">\n {contents[model.state.selectedIds[0]]}\n </Tabs.Panel>\n </Tabs>\n );\n};\n```\n\n### Dynamic Tabs\n\nThe `Tabs.Item` component takes in an optional `index` property if you want to specify the position\nof a tab. If not defined, by default it will append tabs to the end. In this example, our tabs are\nstored as an array in the state, and we have a fixed tab at the end that can add new tabs to that\narray.\n```tsx\nimport React from 'react';\n\nimport {isCursor} from '@workday/canvas-kit-react/collection';\nimport {slugify} from '@workday/canvas-kit-react/common';\nimport {Tabs, useTabsModel} from '@workday/canvas-kit-react/tabs';\nimport {px2rem} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\ntype Tab = {\n tab: string;\n id: string;\n};\n\nexport const DynamicTabs = () => {\n const [tabs, setTabs] = React.useState<Tab[]>([\n {tab: 'Tab 1', id: 'tab-1'},\n {tab: 'Tab 2', id: 'tab-2'},\n {tab: 'Tab 3', id: 'tab-3'},\n {tab: 'Add Tab', id: 'add'},\n ]);\n const addedRef = React.useRef(tabs.length - 1);\n const model = useTabsModel({\n items: tabs,\n getTextValue: item => item.tab,\n shouldSelect: data => data.id !== 'add',\n });\n\n // A ref of the model for the render functions to work around the caching done to lists\n const modelRef = React.useRef(model);\n modelRef.current = model;\n\n /**\n * Helper function that should be called when an item is programmatically removed. The following\n * side effects depend on state of the model:\n * * **Item is focused**: Focus will be moved to next item in the list\n * * **Item is selected**: Selection will be moved to the next item in the list\n * @param id The id of the item that will be removed\n */\n const removeItem = <T extends unknown>(id: string, model: ReturnType<typeof useTabsModel>) => {\n const index = model.state.items.findIndex(item => isCursor(model.state, item.id));\n const nextIndex = index === model.state.items.length - 1 ? index - 1 : index + 1;\n const nextId = model.state.items[nextIndex].id;\n if (model.state.selectedIds[0] === id) {\n // We're removing the currently selected item. Select next item\n model.events.select({id: nextId});\n }\n if (isCursor(model.state, id)) {\n // We're removing the currently focused item. Focus next item\n model.events.goTo({id: nextId});\n\n // wait for stabilization of state\n requestAnimationFrame(() => {\n document\n .querySelector<HTMLElement>(`[id=\"${slugify(`${model.state.id}-${nextId}`)}\"]`)\n ?.focus();\n });\n }\n };\n\n const onKeyDown = (id: string) => (e: React.KeyboardEvent<HTMLElement>) => {\n if ((e.key === 'Delete' || e.key === 'Backspace') && id !== 'add') {\n setTabs(tabs.filter(item => item.id !== id));\n const model = modelRef.current;\n removeItem(id, model);\n }\n };\n\n const onClick = (id: string) => (e: React.MouseEvent) => {\n if (id === 'add') {\n addedRef.current += 1;\n setTabs(tabs => {\n const newTabs = tabs.slice(0, tabs.length - 1);\n const addTab = tabs.slice(-1);\n return newTabs.concat(\n {tab: `Tab ${addedRef.current}`, id: `tab-${addedRef.current}`},\n addTab\n );\n });\n }\n };\n\n return (\n <Tabs model={model}>\n <Tabs.List overflowButton={<Tabs.OverflowButton>More</Tabs.OverflowButton>}>\n {(item: Tab) => (\n <Tabs.Item onKeyDown={onKeyDown(item.id)} onClick={onClick(item.id)}>\n {item.tab}\n </Tabs.Item>\n )}\n </Tabs.List>\n <Tabs.Menu.Popper>\n <Tabs.Menu.Card cs={{maxWidth: px2rem(300), maxHeight: px2rem(200)}}>\n <Tabs.Menu.List>\n {(item: Tab) => <Tabs.Menu.Item>{item.tab}</Tabs.Menu.Item>}\n </Tabs.Menu.List>\n </Tabs.Menu.Card>\n </Tabs.Menu.Popper>\n <Tabs.Panels>\n {(item: Tab) => (\n <Tabs.Panel cs={{marginBlockStart: system.gap.lg}}>Contents of {item.tab}</Tabs.Panel>\n )}\n </Tabs.Panels>\n </Tabs>\n );\n};\n```\n\n## Component API\n\n## Specifications\n\n",
|
|
382
382
|
accessibilityProse: ""
|
|
383
383
|
},
|
|
384
384
|
table: {
|