Skip to content

Commit

Permalink
feat(design): create DaffTabsComponent (#3134)
Browse files Browse the repository at this point in the history
This adds a new tab component! You can use it like:

```html
<daff-tabs aria-label="List of tabs">
	<daff-tab>
		<daff-tab-label>Tab 1</daff-tab-label>
		<daff-tab-panel>
			Tab 1 Panel
		</daff-tab-panel>
	</daff-tab>
</daff-tabs>
```
---------

Co-authored-by: Damien Retzinger <[email protected]>
  • Loading branch information
xelaint and damienwebdev authored Oct 28, 2024
1 parent d1c71af commit ffe6c19
Show file tree
Hide file tree
Showing 35 changed files with 1,495 additions and 0 deletions.
2 changes: 2 additions & 0 deletions apps/design-land/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { PROGRESS_BAR_EXAMPLES } from '@daffodil/design/progress-bar/examples';
import { QUANTITY_FIELD_EXAMPLES } from '@daffodil/design/quantity-field/examples';
import { RADIO_EXAMPLES } from '@daffodil/design/radio/examples';
import { SIDEBAR_EXAMPLES } from '@daffodil/design/sidebar/examples';
import { TABS_EXAMPLES } from '@daffodil/design/tabs/examples';
import { TOAST_EXAMPLES } from '@daffodil/design/toast/examples';
import { TREE_EXAMPLES } from '@daffodil/design/tree/examples';

Expand Down Expand Up @@ -68,6 +69,7 @@ export class DesignLandAppComponent {
...SIDEBAR_EXAMPLES,
...TOAST_EXAMPLES,
...TREE_EXAMPLES,
...TABS_EXAMPLES,
].map((componentExample) => createCustomElementFromExample(componentExample, injector))
.map((customElement) => {
// Register the custom element with the browser.
Expand Down
2 changes: 2 additions & 0 deletions libs/design/scss/theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
@use '../sidebar/src/sidebar-theme' as sidebar;
@use '../progress-bar/src/progress-bar-theme' as progress-bar;
@use '../scss/state/skeleton/mixins' as skeleton;
@use '../tabs/src/tabs-theme' as tabs;
@use '../tree/src/tree-theme' as tree;
@use '../toast/src/toast-theme' as toast;

Expand Down Expand Up @@ -83,6 +84,7 @@
@include notification.daff-notification-theme($theme);
@include paginator.daff-paginator-theme($theme);
@include sidebar.daff-sidebar-theme($theme);
@include tabs.daff-tabs-theme($theme);
@include tree.daff-tree-theme($theme);
@include toast.daff-toast-theme($theme);
}
19 changes: 19 additions & 0 deletions libs/design/tabs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Tabs
Tabs provide a way to navigate between panels that display related content.

## Overview
Tabs allow for users to navigate between related content without having to leave the page. They can be used within components like modals or cards.

## Accessbility
Tabs follow the [ARIA Tabs design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/). Tabs compose of `tablist`, `tab`, and `tabpanel` elements, each with its appropriate role and integrated keyboard interactions.

### Label
A meaningful `aria-label` should be set on `<daff-tabs>` by using the `aria-label` property. This will set the `aria-label` on the `tablist` element.

### Keyboard Interactions
| Key | Action |
| --- | ------ |
| Left Arrow | Moves focus and activates previous tab. If focus is on the first tab, moves focus to the last tab. |
| Right Arrow | Moves focus and activates next tab. If focus is on the last tab, moves focus to the first tab. |
| Home | Moves focus and activates first tab. |
| End | Moves focus and activates last tab. |
7 changes: 7 additions & 0 deletions libs/design/tabs/examples/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "../../../../node_modules/ng-packagr/ng-entrypoint.schema.json",
"lib": {
"entryFile": "src/index.ts",
"styleIncludePaths": ["../../scss"]
}
}
52 changes: 52 additions & 0 deletions libs/design/tabs/examples/src/basic-tabs/basic-tabs.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<daff-tabs aria-label="List of tabs">
<daff-tab>
<daff-tab-label>
<fa-icon [icon]="faInfoCircle" daffPrefix></fa-icon>
Tab 1
</daff-tab-label>
<daff-tab-panel>
Tab 1 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
Tab 2
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 2 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
<fa-icon [icon]="faInfoCircle" daffPrefix></fa-icon>
Tab 3
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 3 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
Tab 4
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 4 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
Tab 5
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 5 Panel
</daff-tab-panel>
</daff-tab>
</daff-tabs>
23 changes: 23 additions & 0 deletions libs/design/tabs/examples/src/basic-tabs/basic-tabs.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
ChangeDetectionStrategy,
Component,
} from '@angular/core';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';

import { DAFF_TABS_COMPONENTS } from '@daffodil/design/tabs';

@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'basic-tabs',
templateUrl: './basic-tabs.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
DAFF_TABS_COMPONENTS,
FaIconComponent,
],
})
export class BasicTabsComponent {
faInfoCircle = faInfoCircle;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<div class="custom-select-tabs__buttons">
<button daff-button size="sm" (click)="selectTabThree()">
Select Tab 3
</button>

<button daff-button size="sm" (click)="selectTabFive()">
Select Tab 5
</button>
</div>

<daff-tabs aria-label="List of tabs">
<daff-tab>
<daff-tab-label>
<fa-icon [icon]="faInfoCircle" daffPrefix></fa-icon>
Tab 1
</daff-tab-label>
<daff-tab-panel>
Tab 1 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
Tab 2
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 2 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab id="tab-3">
<daff-tab-label>
<fa-icon [icon]="faInfoCircle" daffPrefix></fa-icon>
Tab 3
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 3 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
Tab 4
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 4 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab id="tab-5">
<daff-tab-label>
Tab 5
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 5 Panel
</daff-tab-panel>
</daff-tab>

</daff-tabs>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.custom-select-tabs {
&__buttons {
display: flex;
gap: 8px;
margin: 0 0 16px;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {
ChangeDetectionStrategy,
Component,
ViewChild,
} from '@angular/core';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';

import { DAFF_BUTTON_COMPONENTS } from '@daffodil/design/button';
import {
DAFF_TABS_COMPONENTS,
DaffTabsComponent,
} from '@daffodil/design/tabs';

@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'custom-select-tabs',
templateUrl: './custom-select-tabs.component.html',
styleUrl: './custom-select-tabs.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
DAFF_TABS_COMPONENTS,
DAFF_BUTTON_COMPONENTS,
FaIconComponent,
],
})
export class CustomSelectTabsComponent {
faInfoCircle = faInfoCircle;

selectedTab = 'tab-3';

@ViewChild(DaffTabsComponent) _tab: DaffTabsComponent;

selectTabThree() {
this._tab.select('tab-3');
}

selectTabFive() {
this._tab.select('tab-5');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<daff-tabs aria-label="List of tabs">
<daff-tab>
<daff-tab-label>
<fa-icon [icon]="faInfoCircle" daffPrefix></fa-icon>
Tab 1
</daff-tab-label>
<daff-tab-panel>
Tab 1 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
Tab 2
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 2 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
<fa-icon [icon]="faInfoCircle" daffPrefix></fa-icon>
Tab 3
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 3 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
Tab 4
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 4 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab [disabled]="true">
<daff-tab-label>
Tab 5
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 5 Panel
</daff-tab-panel>
</daff-tab>

</daff-tabs>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
ChangeDetectionStrategy,
Component,
} from '@angular/core';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';

import { DAFF_TABS_COMPONENTS } from '@daffodil/design/tabs';

@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'disabled-tabs',
templateUrl: './disabled-tabs.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
DAFF_TABS_COMPONENTS,
FaIconComponent,
],
})
export class DisabledTabsComponent {
faInfoCircle = faInfoCircle;
}
1 change: 1 addition & 0 deletions libs/design/tabs/examples/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './public_api';
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<daff-tabs aria-label="List of tabs" [initiallySelected]="'tab-4'">
<daff-tab>
<daff-tab-label>
<fa-icon [icon]="faInfoCircle" daffPrefix></fa-icon>
Tab 1
</daff-tab-label>
<daff-tab-panel>
Tab 1 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
Tab 2
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 2 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
<fa-icon [icon]="faInfoCircle" daffPrefix></fa-icon>
Tab 3
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 3 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab id="tab-4">
<daff-tab-label>
Tab 4
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 4 Panel
</daff-tab-panel>
</daff-tab>

<daff-tab>
<daff-tab-label>
Tab 5
<fa-icon [icon]="faInfoCircle" daffSuffix></fa-icon>
</daff-tab-label>
<daff-tab-panel>
Tab 5 Panel
</daff-tab-panel>
</daff-tab>

</daff-tabs>
Loading

0 comments on commit ffe6c19

Please sign in to comment.