diff --git a/apps/docs/content/_data/components.json b/apps/docs/content/_data/components.json
index 042e4cce5e..b241cc02c0 100644
--- a/apps/docs/content/_data/components.json
+++ b/apps/docs/content/_data/components.json
@@ -264,15 +264,13 @@
},
{
"title": "Tabs",
- "page": "legacy",
- "markdown": "./libs/components/src/lib/tabs/README.md",
- "children": ["Tab"]
- },
- {
- "title": "Tab",
- "page": "legacy",
- "markdown": "./libs/components/src/lib/tab/README.md",
- "parent": "Tabs"
+ "description": "Tabs are interactive elements that work alongside Tab and Tab Panel to organise content into separate sections or views.",
+ "variations": "./libs/components/src/lib/tabs/VARIATIONS.md",
+ "guidelines": "./libs/components/src/lib/tabs/GUIDELINES.md",
+ "hideGuidelines": "true",
+ "code": "./libs/components/src/lib/tabs/README.md",
+ "accessibility": "./libs/components/src/lib/tabs/ACCESSIBILITY.md",
+ "useCases": "./libs/components/src/lib/tabs/USE-CASES.md"
},
{
"title": "Combobox",
diff --git a/libs/components/src/lib/accordion/README.md b/libs/components/src/lib/accordion/README.md
index fc107c6405..dbc3edb4f5 100644
--- a/libs/components/src/lib/accordion/README.md
+++ b/libs/components/src/lib/accordion/README.md
@@ -435,14 +435,15 @@ Use the `--accordion-item-meta-inline-size` to control the width of the `meta-da
-| Name | Type | Description |
-| ----------------- | -------------------------------------- | ---------------------------------------------------------------- |
-| **heading** | `string` | Determines if multiple items or a single item can opened at once |
-| **heading-level** | `1`, `2` (default), `3`, `4`, `5`, `6` | Determines the heading level |
-| **expanded** | `boolean` | Sets the open state |
-| **meta** | `string` | Sets the meta text for the heading |
-| **no-indicator** | `boolean` | Hides the open state indicator icon (chevron) |
-| **size** | `normal` (default), `condensed` | Sets the size |
+| Name | Type | Description |
+| ----------------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
+| **heading** | `string` | Determines if multiple items or a single item can opened at once |
+| **heading-level** | `1`, `2` (default), `3`, `4`, `5`, `6` | Determines the heading level |
+| **icon** | Enum: `[icon-name]` | A decorative icon the custom element should have. See the Vivid Icon Gallery for available icons and icon-names |
+| **expanded** | `boolean` | Sets the open state |
+| **meta** | `string` | Sets the meta text for the heading |
+| **no-indicator** | `boolean` | Hides the open state indicator icon (chevron) |
+| **size** | `normal` (default), `condensed` | Sets the size |
diff --git a/libs/components/src/lib/tabs/ACCESSIBILITY.md b/libs/components/src/lib/tabs/ACCESSIBILITY.md
new file mode 100644
index 0000000000..aeba17f114
--- /dev/null
+++ b/libs/components/src/lib/tabs/ACCESSIBILITY.md
@@ -0,0 +1,14 @@
+## Implementation
+
+- **Icons:** ideally the [icon should be accompanied by a label](https://www.nngroup.com/articles/icon-usability/), but if this is not the case, be sure to supply the **Tab** component with an `aria-label` attribute so that screen reader user will know the purpose of the tab.
+
+## Best Practice
+
+- **Write short, descriptive tab labels**. Tab labels should usually be 1-2 words. Short labels are more scannable; if you need longer labels, it’s a sign that the choices are too complicated for tabs and maybe an [Accordion](/components/accordion/) is a better choice.
+- **Avoid tab list scrolling**. Make sure there is enough horizontal space to encorporate the amount of tabs you are presenting.
+
+## Resources
+
+- [Vivid Tabs: Manual accessibility test](https://docs.google.com/spreadsheets/d/1otYxVmPqu2YcPHWBNIJg73W7xNXF4amoTZBuN_6D8C0/edit?gid=1175911860#gid=1175911860)
+- We follow the [W3C Tabs Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/)
+- [Tabs used right](https://www.nngroup.com/articles/tabs-used-right/)
diff --git a/libs/components/src/lib/tabs/GUIDELINES.md b/libs/components/src/lib/tabs/GUIDELINES.md
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/libs/components/src/lib/tabs/README.md b/libs/components/src/lib/tabs/README.md
index 6e29a6a506..a812c209f6 100644
--- a/libs/components/src/lib/tabs/README.md
+++ b/libs/components/src/lib/tabs/README.md
@@ -1,194 +1,105 @@
-# Tabs
+## Usage
-Represents a tabs custom element.
-The vwc-tabs accepts [vwc-tab](/components/tab/) and `vwc-tab-panel` elements as children. Read more about `tabs` [here](https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel/).
+
+
+
```js
-
+import '@vonage/vivid/tabs';
+import '@vonage/vivid/tab';
+import '@vonage/vivid/tab-panel';
```
-## Members
-
-### Gutters
-
-Use the `gutters` attribute to control the tabs panel padding.
-
-- Type: `'small'` | `'none'`
+or, if you need to use a unique prefix:
-- Default: `small`
-
-```html preview full
-
-
-
-
- Tab one content
- Tab two content
- Tab three content
-
-```
-
-### Orientation
-
-Add a `orientation` attribute to control the orientation.
-
-- Type: `'horizontal'`, `'vertical'`
-- Default: `'horizontal'`
-
-```html preview full
-
-
-
-
- Tab one content
- Tab two content
- Tab three content
-
-```
-
-### Connotation
-
-- Type: `'accent' | 'cta'`
-- Default: `accent`
-
-Setting a connotation will only affect the active tab
+```js
+import { registerTabs, registerTab, registerTabPanel } from '@vonage/vivid';
-```html preview full
-
-
-
-
- Tab one content
- Tab two content
- Tab three content
-
+registerTabs('your-prefix');
+registerTab('your-prefix');
+registerTabPanel('your-prefix');
```
-### Activeid
-
-Add an `activeid` attribute of the active tab.
-
-- Type: `string`
-- Default: `''`
+```html preview
+
-```html preview full
-
-
-
-
- Tab one content
- Tab two content
- Tab three content
-
+
+
+
+
+ Tab Panel one
+ Tab Panel two
+ Tab Panel three
+
```
-### Panel Scroll
-
-Add `scrollable-panel` to allow scroll.
-Add `block-size` to `vwc-tabs` to make it scroll.
+
+
+
-#### horizontal
-
-```html preview full
-
-
-
-
-
-
-
-
- - Stuffed artichokes
- - Bruschetta
- - Oven-baked polenta
- - Salami and Fig Crostini with Ricotta
- - Rosemary-Potato Focaccia with Goat Cheese
- - Stuffed artichokes
- - Bruschetta
- - Oven-baked polenta
- - Salami and Fig Crostini with Ricotta
- - Rosemary-Potato Focaccia with Goat Cheese
-
-
-
- Tab two content
- Tab three content
-
+```html
+
+
+
+
+
+
+ Tab Panel one
+ Tab Panel two
+ Tab Panel three
+
+
```
-#### Vertical
-
-```html preview full
-
-
-
-
-
-
-
-
- - Stuffed artichokes
- - Bruschetta
- - Oven-baked polenta
- - Salami and Fig Crostini with Ricotta
- - Rosemary-Potato Focaccia with Goat Cheese
- - Stuffed artichokes
- - Bruschetta
- - Oven-baked polenta
- - Salami and Fig Crostini with Ricotta
- - Rosemary-Potato Focaccia with Goat Cheese
-
-
-
- Tab two content
- Tab three content
+
-```
-### Tabs Layout
+## Slots
-Add `tabs-layout` attribute to control the tabs layout. When set to `stretch`, the tabs will stretch to fill the available space. It will have no effect when the tabs are in a vertical orientation.
+### Icon Slot
-- Type: `'align-start' | 'stretch'`
-- Default: `align-start`
+The `icon` slot on the **Tab** component can be used to display a custom icon. If set, the `icon` attribute is ignored.
-```html preview full
-
-
-
-
- Tab one content
- Tab two content
- Tab three content
+```html preview
+
+
+
+
+
+
+
+ Tab Panel one
+ Tab Panel two
```
-## Slots
-
-### Default
-
-The default slot holds the [Tabs](/components/tab/) and Tab Panels of the component.
-
-Tabs and Tab Panels are associated with each other by the order in which they are placed in the DOM.
+### Action Items Slot
-### Action Items
+The `action-items` slot on the **Tabs** component can be used to add action items after the last Tab in the tabs bar.
-You can use the `action-items` slot to add action items at the end of the tabs bar.
+In the example below, a Button is provided that adds a new Tab when clicked.
```html preview full
- Tab one content
- Tab two content
+ Tab Panel one
+ Tab Panel two
+
+
+
+ Tab Panel one
+ Tab Panel two
+ Tab Panel three
+
+
-
-
-
-
- Tab one content
- Tab two content
- Tab three content
-
```
-## Events
+## API Reference
+
+### Tabs
+
+#### Properties
-| Name | Type | Bubbles | Composed | Description |
-| -------- | -------------------------- | ------- | -------- | --------------------------------------------------------------------------------- |
-| `change` | `CustomEvent` | Yes | Yes | Fires a custom 'change' event when a tab is clicked or during keyboard navigation |
+| Name | Type | Description |
+| -------------------- | ---------------------------------- | -------------------------------------------------------------------------------------- |
+| **activeid** | `string` | Match with an `id` set on a Tab to mark it as active on initial load |
+| **connotation** | `accent` (default), `cta` | Sets the connotation color of the active tab |
+| **gutters** | `none`, `small` (default) | Sets the spacing inside the Tab Panels |
+| **orientation** | `horizontal` (default), `vertical` | Sets axis on which the tabs are aligned |
+| **scrollable-panel** | `boolean` | Sets whether the Tab Panel will be scrollable (if content height exceeds `block-size`) |
-## Use cases
+#### Slots
-### Removable tabs
+
-```html preview 300px
-
-
- Task content
-
- Event content
-
-
-
-
-
-
+| Name | Description |
+| ---------------- | ------------------------------------------------------ |
+| **default** | For **Tab** and **Tab Panel** components |
+| **action-items** | To add action items after the last Tab in the tabs bar |
-
-```
+
+
+#### Events
+
+
+
+| Name | Type | Bubbles | Composed | Description |
+| -------- | -------------------------- | ------- | -------- | --------------------------------------------------------- |
+| `change` | `CustomEvent` | Yes | Yes | Fired when a tab is clicked or during keyboard navigation |
+
+
+
+### Tab
+
+#### Properties
+
+
+
+| Name | Type | Description |
+| ----------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------- |
+| **disabled** | `boolean` | Sets the disabled state |
+| **icon** | Enum: `[icon-name]` | A decorative icon the custom element should have. See the Vivid Icon Gallery for available icons and icon-names |
+| **icon-trailing** | `boolean` | Places the icon after the label text |
+| **label** | `string` | Sets the label text |
+| **removable** | `boolean` | Adds a close button |
+| **shape** | `rounded` (default), `sharp` | Shape of the background when hovered |
+
+
+
+#### Slots
+
+
+
+| Name | Description |
+| -------- | ---------------- |
+| **icon** | For custom icons |
+
+
+
+#### Events
+
+
+
+| Name | Type | Bubbles | Composed | Description |
+| ------- | ------------- | ------- | -------- | ---------------------------------------------------------------------------------------------- |
+| `close` | `CustomEvent` | Yes | Yes | When `removable` is set, fired when the close button is clicked or the `DELETE` key is pressed |
+
+
+
+### Tab Panel
+
+#### Slots
+
+
+
+| Name | Description |
+| ----------- | --------------------- |
+| **default** | For Tab Panel content |
+
+
diff --git a/libs/components/src/lib/tabs/USE-CASES.md b/libs/components/src/lib/tabs/USE-CASES.md
new file mode 100644
index 0000000000..8e3178e05e
--- /dev/null
+++ b/libs/components/src/lib/tabs/USE-CASES.md
@@ -0,0 +1,54 @@
+## Dynamic Tabs
+
+The `removable` attribute on the **Tab** component can used along with the `action-items` slot on the **Tabs** component to create functionality where Tabs can be added and removed by the user.
+
+```html preview 300px
+
+
+ Task content
+
+ Event content
+
+
+
+
+
+
+
+
+```
diff --git a/libs/components/src/lib/tabs/VARIATIONS.md b/libs/components/src/lib/tabs/VARIATIONS.md
new file mode 100644
index 0000000000..cf5cc51e62
--- /dev/null
+++ b/libs/components/src/lib/tabs/VARIATIONS.md
@@ -0,0 +1,266 @@
+For **Tabs** to function correctly they must include corresponding **[Tab](/components/tabs/code/#tab)** and **[Tab Panel](/components/tabs/code/#tab-panel)** components.
+
+## Label
+
+The `label` attribute on the **Tab** component provides the Tab with label text.
+
+```html preview full
+
+
+
+
+ Tab Panel one
+ Tab Panel two
+ Tab Panel three
+
+```
+
+## Icon
+
+The `icon` attribute on the **Tab** component displays an icon from the [icon library](/icons/icons-gallery/) on the Tab.
+
+Custom icons can be provided using the [icon slot](/components/tabs/code/#icon-slot).
+
+```html preview full
+
+
+
+
+ Comments
+ Playlist
+ Favourites
+
+```
+
+
+ It is bad UX to hide content that is essential for users to complete their tasks.
But, if a label
is not supplied, be sure to provide an aria-label
which will be announced by a screen reader.
+
+
+### Icon Trailing
+
+The `icon-trailing` attribute on the **Tab** component positions the icon after the label text.
+
+```html preview full
+
+
+
+
+ Comments
+ Playlist
+ Favourites
+
+```
+
+## Removable
+
+The `removable` attribute on the **Tab** component adds a close button to the tab.
+
+Clicking the close button or pressing the `DELETE` key when focussed on the tab will emit the `close` event.
+
+```html preview full
+
+
+
+
+ Tab one content
+ Tab two content
+ Tab three content
+
+
+
+```
+
+
+ Triggering the close
event does not automatically close the tab and tab panel. This needs to be handled in the consuming application as in the example below.
+ The consuming application must also handle whether the user can close all the tabs or not.
+
+
+## Disabled
+
+The `disabled` attribute on the **Tab** component disables the Tab.
+
+```html preview full
+
+
+
+
+ Tab Panel one
+ Tab Panel two
+ Tab Panel three
+
+```
+
+## Shape
+
+The `shape` attribute on the **Tab** component controls the style of the background in hover state. It can be `rounded` or `shape`.
+
+```html preview full
+
+
+
+ Tab Panel one
+ Tab Panel two
+
+```
+
+
+ The `shape` variations should not be used in the tab set of tabs. The example above is for demonstration purposes only.
+
+
+## Orientation
+
+The `orientation` attribute on the **Tabs** component controls which axis the tabs are aligned. Below is an example of vertical alignment.
+
+```html preview full
+
+
+
+
+ Tab Panel one
+ Tab Panel two
+ Tab Panel three
+
+```
+
+## Connotation
+
+Use the `connotation` attribute on the **Tabs** component to control the color of the active tab. Below it is set to `cta`.
+
+```html preview full
+
+
+
+
+ Tab Panel one
+ Tab Panel two
+ Tab Panel three
+
+```
+
+## Active ID
+
+Use the `activeid` attribute on the **Tabs** component to control which tab is active on first render. The `activeid` attribute must match an `id` given to the **Tab** component.
+
+```html preview full
+
+
+
+
+ Tab Panel one
+ Tab Panel two
+ Tab Panel three
+
+```
+
+## Gutters
+
+Use the `gutters` attribute on the **Tabs** component to control the spacing inside the Tab Panels. It can be set to `small` (default) or `none` (demonstrated in the example below).
+
+```html preview full
+
+
+
+
+ Tab Panel one
+ Tab Panel two
+ Tab Panel three
+
+```
+
+## Scrollable Panel
+
+Use the `scrollable-panel` attribute combined with setting a `block-size` style to the **Tabs** component to make the content scrollable.
+
+### Horizontal
+
+```html preview full
+
+
+
+
+
+
+ - Stuffed artichokes
+ - Bruschetta
+ - Oven-baked polenta
+ - Salami and Fig Crostini with Ricotta
+ - Rosemary-Potato Focaccia with Goat Cheese
+ - Stuffed artichokes
+ - Bruschetta
+ - Oven-baked polenta
+ - Salami and Fig Crostini with Ricotta
+ - Rosemary-Potato Focaccia with Goat Cheese
+
+
+ Tab Panel two
+ Tab Panel three
+
+
+
+```
+
+### Vertical
+
+```html preview full
+
+
+
+
+
+
+ - Stuffed artichokes
+ - Bruschetta
+ - Oven-baked polenta
+ - Salami and Fig Crostini with Ricotta
+ - Rosemary-Potato Focaccia with Goat Cheese
+ - Stuffed artichokes
+ - Bruschetta
+ - Oven-baked polenta
+ - Salami and Fig Crostini with Ricotta
+ - Rosemary-Potato Focaccia with Goat Cheese
+
+
+ Tab Panel two
+ Tab Panel three
+
+
+
+```
+
+## Tabs Layout
+
+The `tabs-layout` attribute on the **Tabs** component controls the tabs layout. When set to `stretch`, the tabs will stretch to fill the available space. It will have no effect when the tabs are in a vertical orientation.
+
+```html preview full
+
+
+
+
+ Tab Panel one
+ Tab Panel two
+ Tab Panel three
+
+```
diff --git a/libs/components/src/lib/tabs/ui.test.ts b/libs/components/src/lib/tabs/ui.test.ts
index 93237b7c27..6d1920c755 100644
--- a/libs/components/src/lib/tabs/ui.test.ts
+++ b/libs/components/src/lib/tabs/ui.test.ts
@@ -1,8 +1,6 @@
-import * as path from 'path';
import { expect, test } from '@playwright/test';
import type { Page } from '@playwright/test';
import {
- extractHTMLBlocksFromReadme,
loadComponents,
loadTemplate,
} from '../../visual-tests/visual-tests-utils.js';
@@ -54,13 +52,171 @@ async function testScroll({ page }: { page: Page }) {
);
}
test('should show the component', async ({ page }: { page: Page }) => {
- const template = extractHTMLBlocksFromReadme(
- path.join(new URL('.', import.meta.url).pathname, 'README.md')
- ).reduce(
- (htmlString: string, block: string) =>
- `${htmlString} ${block}
`,
- ''
- );
+ const template = `
+
+
+
+
+
+ Tab one content
+ Tab two content
+ Tab three content
+
+
+
+
+
+
+
+ Tab one content
+ Tab two content
+ Tab three content
+
+
+
+
+
+
+
+ Tab one content
+ Tab two content
+ Tab three content
+
+
+
+
+
+
+
+ Tab one content
+ Tab two content
+ Tab three content
+
+
+
+
+
+
+
+
+
+
+
+ - Stuffed artichokes
+ - Bruschetta
+ - Oven-baked polenta
+ - Salami and Fig Crostini with Ricotta
+ - Rosemary-Potato Focaccia with Goat Cheese
+ - Stuffed artichokes
+ - Bruschetta
+ - Oven-baked polenta
+ - Salami and Fig Crostini with Ricotta
+ - Rosemary-Potato Focaccia with Goat Cheese
+
+
+
+ Tab two content
+ Tab three content
+
+
+
+
+
+
+
+
+
+
+
+ - Stuffed artichokes
+ - Bruschetta
+ - Oven-baked polenta
+ - Salami and Fig Crostini with Ricotta
+ - Rosemary-Potato Focaccia with Goat Cheese
+ - Stuffed artichokes
+ - Bruschetta
+ - Oven-baked polenta
+ - Salami and Fig Crostini with Ricotta
+ - Rosemary-Potato Focaccia with Goat Cheese
+
+
+
+ Tab two content
+ Tab three content
+
+
+
+
+
+
+
+ Tab one content
+ Tab two content
+ Tab three content
+
+
+
+
+
+
+ Tab one content
+ Tab two content
+
+
+
+
+
+
+
+
+
+ Tab one content
+ Tab two content
+ Tab three content
+
+
+
+
+
+ Task content
+
+ Event content
+
+
+
+
+
+
+
+ `;
await loadComponents({
page,