Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(design): create DaffTabsComponent #3134

Merged
merged 12 commits into from
Oct 28, 2024
Merged
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"]
}
}
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>
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
Loading