From 0f2bd38489ea91b510f2a1227aa91b5912c9a77b Mon Sep 17 00:00:00 2001 From: TaylorJ76 Date: Fri, 29 Nov 2024 08:03:32 +0000 Subject: [PATCH 1/6] chore: tabs docs page --- apps/docs/content/_data/components.json | 16 +- libs/components/src/lib/tabs/ACCESSIBILITY.md | 14 + libs/components/src/lib/tabs/GUIDELINES.md | 0 libs/components/src/lib/tabs/README.md | 388 ++++++++---------- libs/components/src/lib/tabs/USE-CASES.md | 54 +++ libs/components/src/lib/tabs/VARIATIONS.md | 262 ++++++++++++ 6 files changed, 498 insertions(+), 236 deletions(-) create mode 100644 libs/components/src/lib/tabs/ACCESSIBILITY.md create mode 100644 libs/components/src/lib/tabs/GUIDELINES.md create mode 100644 libs/components/src/lib/tabs/USE-CASES.md create mode 100644 libs/components/src/lib/tabs/VARIATIONS.md diff --git a/apps/docs/content/_data/components.json b/apps/docs/content/_data/components.json index 71c70cd91b..01377371bc 100644 --- a/apps/docs/content/_data/components.json +++ b/apps/docs/content/_data/components.json @@ -259,15 +259,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/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..cdceb047ec 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 - - - - - - -
-
    -
  1. Stuffed artichokes
  2. -
  3. Bruschetta
  4. -
  5. Oven-baked polenta
  6. -
  7. Salami and Fig Crostini with Ricotta
  8. -
  9. Rosemary-Potato Focaccia with Goat Cheese
  10. -
  11. Stuffed artichokes
  12. -
  13. Bruschetta
  14. -
  15. Oven-baked polenta
  16. -
  17. Salami and Fig Crostini with Ricotta
  18. -
  19. Rosemary-Potato Focaccia with Goat Cheese
  20. -
-
-
- Tab two content - Tab three content -
+```html + + ``` -#### Vertical - -```html preview full - - - - - - -
-
    -
  1. Stuffed artichokes
  2. -
  3. Bruschetta
  4. -
  5. Oven-baked polenta
  6. -
  7. Salami and Fig Crostini with Ricotta
  8. -
  9. Rosemary-Potato Focaccia with Goat Cheese
  10. -
  11. Stuffed artichokes
  12. -
  13. Bruschetta
  14. -
  15. Oven-baked polenta
  16. -
  17. Salami and Fig Crostini with Ricotta
  18. -
  19. Rosemary-Potato Focaccia with Goat Cheese
  20. -
-
-
- 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` (default), `small` | 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-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..157bb22f29 --- /dev/null +++ b/libs/components/src/lib/tabs/VARIATIONS.md @@ -0,0 +1,262 @@ +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 + +``` + +## 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. Below it is set to `none`. + +```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 + + + + + +
    +
  1. Stuffed artichokes
  2. +
  3. Bruschetta
  4. +
  5. Oven-baked polenta
  6. +
  7. Salami and Fig Crostini with Ricotta
  8. +
  9. Rosemary-Potato Focaccia with Goat Cheese
  10. +
  11. Stuffed artichokes
  12. +
  13. Bruschetta
  14. +
  15. Oven-baked polenta
  16. +
  17. Salami and Fig Crostini with Ricotta
  18. +
  19. Rosemary-Potato Focaccia with Goat Cheese
  20. +
+
+ Tab Panel two + Tab Panel three +
+ + +``` + +### Vertical + +```html preview full + + + + + +
    +
  1. Stuffed artichokes
  2. +
  3. Bruschetta
  4. +
  5. Oven-baked polenta
  6. +
  7. Salami and Fig Crostini with Ricotta
  8. +
  9. Rosemary-Potato Focaccia with Goat Cheese
  10. +
  11. Stuffed artichokes
  12. +
  13. Bruschetta
  14. +
  15. Oven-baked polenta
  16. +
  17. Salami and Fig Crostini with Ricotta
  18. +
  19. Rosemary-Potato Focaccia with Goat Cheese
  20. +
+
+ 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 + +``` From ba44b23e98da06701b0d8981d976ed723af6948e Mon Sep 17 00:00:00 2001 From: TaylorJ76 Date: Fri, 29 Nov 2024 08:54:20 +0000 Subject: [PATCH 2/6] chore: updates ui test --- libs/components/src/lib/tabs/ui.test.ts | 160 ++++++++++++++++++++++-- 1 file changed, 153 insertions(+), 7 deletions(-) diff --git a/libs/components/src/lib/tabs/ui.test.ts b/libs/components/src/lib/tabs/ui.test.ts index 93237b7c27..879cb499d0 100644 --- a/libs/components/src/lib/tabs/ui.test.ts +++ b/libs/components/src/lib/tabs/ui.test.ts @@ -54,13 +54,159 @@ 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 + +
+
+ + + + + + +
+
    +
  1. Stuffed artichokes
  2. +
  3. Bruschetta
  4. +
  5. Oven-baked polenta
  6. +
  7. Salami and Fig Crostini with Ricotta
  8. +
  9. Rosemary-Potato Focaccia with Goat Cheese
  10. +
  11. Stuffed artichokes
  12. +
  13. Bruschetta
  14. +
  15. Oven-baked polenta
  16. +
  17. Salami and Fig Crostini with Ricotta
  18. +
  19. Rosemary-Potato Focaccia with Goat Cheese
  20. +
+
+
+ Tab two content + Tab three content +
+
+
+ + + + + + +
+
    +
  1. Stuffed artichokes
  2. +
  3. Bruschetta
  4. +
  5. Oven-baked polenta
  6. +
  7. Salami and Fig Crostini with Ricotta
  8. +
  9. Rosemary-Potato Focaccia with Goat Cheese
  10. +
  11. Stuffed artichokes
  12. +
  13. Bruschetta
  14. +
  15. Oven-baked polenta
  16. +
  17. Salami and Fig Crostini with Ricotta
  18. +
  19. Rosemary-Potato Focaccia with Goat Cheese
  20. +
+
+
+ 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 + +
+ `; await loadComponents({ page, From 8ef2811c9d2211e2a716a4657fca9bee231ea23e Mon Sep 17 00:00:00 2001 From: TaylorJ76 Date: Fri, 29 Nov 2024 09:14:29 +0000 Subject: [PATCH 3/6] chore: updates ui test --- libs/components/src/lib/tabs/ui.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/components/src/lib/tabs/ui.test.ts b/libs/components/src/lib/tabs/ui.test.ts index 879cb499d0..2b8a7ad713 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'; From 1951c609b93d5e39380636999cf4a70a8176c3fa Mon Sep 17 00:00:00 2001 From: TaylorJ76 Date: Fri, 29 Nov 2024 09:53:23 +0000 Subject: [PATCH 4/6] chore: updates ui tests --- libs/components/src/lib/tabs/ui.test.ts | 34 +++++++++++++++++-------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libs/components/src/lib/tabs/ui.test.ts b/libs/components/src/lib/tabs/ui.test.ts index 2b8a7ad713..6d1920c755 100644 --- a/libs/components/src/lib/tabs/ui.test.ts +++ b/libs/components/src/lib/tabs/ui.test.ts @@ -177,17 +177,6 @@ test('should show the component', async ({ page }: { page: Page }) => { onclick="addTab()" >
- -