-
Notifications
You must be signed in to change notification settings - Fork 4
feat(tabs): add tab-card and tabs-vertical #14 #402
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
base: rc
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <tedi-card> | ||
| <tedi-card-content class="tedi-tab-card__content"> | ||
| <h3>{{ title() }}</h3> | ||
| <div tedi-button variant="neutral"> | ||
| <tedi-icon name="arrow_forward" class="tedi-tab-card__action-icon" [size]="18"/> | ||
| </div> | ||
| </tedi-card-content> | ||
| </tedi-card> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| .tedi-tab-card { | ||
| width: 100%; | ||
|
|
||
| &__content.tedi-card-content { | ||
| display: flex; | ||
| justify-content: space-between; | ||
| align-items: center; | ||
| gap: var(--dimensions-13); | ||
| color: var(--tab-item-active-text); | ||
| width: 100%; | ||
| } | ||
|
|
||
| &__action-icon { | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| &--disabled { | ||
| pointer-events: none; | ||
|
|
||
| .tedi-card-content { | ||
| color: var(--general-text-disabled); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| import {booleanAttribute, ChangeDetectionStrategy, Component, input, model, ViewEncapsulation} from '@angular/core'; | ||
| import {ButtonComponent, IconComponent} from "@tedi-design-system/angular/tedi"; | ||
| import {CardComponent, CardContentComponent} from "@tedi-design-system/angular/community"; | ||
|
|
||
| @Component({ | ||
| selector: '[tedi-tab-card]', | ||
| imports: [ | ||
| ButtonComponent, | ||
| CardComponent, | ||
| CardContentComponent, | ||
| IconComponent | ||
| ], | ||
| templateUrl: './tab-card.component.html', | ||
| styleUrl: './tab-card.component.scss', | ||
| encapsulation: ViewEncapsulation.None, | ||
| changeDetection: ChangeDetectionStrategy.OnPush, | ||
| host: { | ||
| "[class.tedi-tab-card]": "true", | ||
| "[class.tedi-tab-card--disabled]": "disabledInput()", | ||
| "[attr.role]": "'tab'", | ||
| "[attr.aria-selected]": "selected()", | ||
| "[attr.aria-disabled]": "disabledInput()", | ||
| "(click)": "selectTab()", | ||
| }, | ||
|
Comment on lines
+6
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keyboard activation and tab-pattern semantics are incomplete. With Suggestions:
|
||
| }) | ||
| export class TabCardComponent { | ||
| readonly tabId = input.required<string>(); | ||
| readonly title = input.required<string>(); | ||
| readonly selected = model(false); | ||
|
|
||
| readonly disabledInput = input(false, { | ||
| transform: booleanAttribute, | ||
| // eslint-disable-next-line @angular-eslint/no-input-rename | ||
| alias: "disabled", | ||
| }); | ||
|
|
||
| selectTab() { | ||
| if (this.disabledInput()) { | ||
| return; | ||
| } | ||
|
|
||
| this.selected.set(true); | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
Comment on lines
+29
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
fd -e ts 'tabs-vertical\.component\.ts$' | xargs rg -nC3 "selected|activeTab|contentChildren"Repository: TEDI-Design-System/angular Length of output: 1028 🏁 Script executed: #!/bin/bash
# Find the complete TabsVerticalComponent to see if there are effects or outputs managing selection
fd -e ts 'tabs-vertical\.component\.ts$' -exec cat -n {} \;Repository: TEDI-Design-System/angular Length of output: 300 🏁 Script executed: #!/bin/bash
# Search for calls to unselectAllTabs or any selection-related logic
rg -r 'unselectAllTabs|selectTab' --type ts -B2 -A2Repository: TEDI-Design-System/angular Length of output: 466 🏁 Script executed: #!/bin/bash
# Check if there are any stories or examples showing the tab usage pattern
fd -e ts -e html 'tab.*story\|tab.*spec' | head -20Repository: TEDI-Design-System/angular Length of output: 52 🏁 Script executed: #!/bin/bash
# Find and display the complete TabsVerticalComponent
fd -e ts 'tabs-vertical\.component\.ts$' -exec cat {} \;Repository: TEDI-Design-System/angular Length of output: 257 🏁 Script executed: #!/bin/bash
# Search for calls to unselectAllTabs or selectTab with context
rg 'unselectAllTabs|selectTab' -B2 -A2 --type tsRepository: TEDI-Design-System/angular Length of output: 2297 🏁 Script executed: #!/bin/bash
# Find tab-related stories and specs
fd '(tab|tabs).*\.(spec|stories)\.ts$'Repository: TEDI-Design-System/angular Length of output: 252 🏁 Script executed: #!/bin/bash
# Read the complete TabsVerticalComponent file
cat community/components/navigation/tabs/tabs-vertical/tabs-vertical.component.tsRepository: TEDI-Design-System/angular Length of output: 1620 🏁 Script executed: #!/bin/bash
# Read the tab-card component to see the full implementation
cat community/components/navigation/tabs/tab-card/tab-card.component.tsRepository: TEDI-Design-System/angular Length of output: 1374 🏁 Script executed: #!/bin/bash
# Check the stories file for usage patterns
cat community/components/navigation/tabs/tabs.stories.tsRepository: TEDI-Design-System/angular Length of output: 4392 Multiple tabs can be
Add an output event from 🤖 Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| <ng-template #tabsList> | ||
| <ng-content select="[tedi-tab-card]"/> | ||
| </ng-template> | ||
|
|
||
| @if (activeTabContent(); as activeContent) { | ||
| <button tedi-button type="button" variant="neutral" class="tedi-tabs-vertical__back-link" (click)="unselectAllTabs()"> | ||
| <tedi-icon name="arrow_back" [size]="18"/> | ||
| <span>{{ "back" | tediTranslate }}</span> | ||
| </button> | ||
|
|
||
| <h3 tedi-text>{{ activeTabTitle() }}</h3> | ||
|
|
||
| <tedi-card class="tedi-tabs-vertical__card"> | ||
| <tedi-card-content> | ||
| <ng-container *ngTemplateOutlet="activeContent"/> | ||
| </tedi-card-content> | ||
| </tedi-card> | ||
| } @else { | ||
| <tedi-accordion class="tedi-tabs-vertical__accordion" role="tablist"> | ||
| <ng-container *ngTemplateOutlet="tabsList"/> | ||
| </tedi-accordion> | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| .tedi-tabs-vertical { | ||
| display: flex; | ||
| flex-direction: column; | ||
| align-items: start; | ||
| gap: var(--dimensions-10); | ||
|
|
||
| &__accordion, | ||
| &__card { | ||
| width: 100%; | ||
| } | ||
|
|
||
| &__back-link.tedi-button { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: var(--dimensions-03); | ||
| cursor: pointer; | ||
| padding: var(--dimensions-02) var(--dimensions-03); | ||
| } | ||
|
|
||
| &__back-link > * { | ||
| color: var(--button-main-neutral-text-active); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| import {ChangeDetectionStrategy, Component, computed, contentChildren, ViewEncapsulation} from '@angular/core'; | ||
| import {CardComponent, CardContentComponent, TabContentComponent} from "@tedi-design-system/angular/community"; | ||
| import {TabCardComponent} from "../tab-card/tab-card.component"; | ||
| import { | ||
| AccordionComponent, | ||
| ButtonComponent, | ||
| IconComponent, | ||
| TediTranslationPipe, | ||
| TextComponent | ||
| } from "@tedi-design-system/angular/tedi"; | ||
| import {NgTemplateOutlet} from "@angular/common"; | ||
|
|
||
| @Component({ | ||
| selector: 'tedi-tabs-vertical', | ||
| imports: [ | ||
| AccordionComponent, | ||
| ButtonComponent, | ||
| CardComponent, | ||
| CardContentComponent, | ||
| IconComponent, | ||
| NgTemplateOutlet, | ||
| TediTranslationPipe, | ||
| TextComponent | ||
| ], | ||
| templateUrl: './tabs-vertical.component.html', | ||
| styleUrl: './tabs-vertical.component.scss', | ||
| encapsulation: ViewEncapsulation.None, | ||
| changeDetection: ChangeDetectionStrategy.OnPush, | ||
| host: { | ||
| "[class.tedi-tabs-vertical]": "true", | ||
| }, | ||
| }) | ||
| export class TabsVerticalComponent { | ||
| private readonly tabs = contentChildren(TabCardComponent); | ||
| private readonly tabContents = contentChildren(TabContentComponent); | ||
|
|
||
| activeTabId = computed(() => | ||
| this.tabs().find((tab) => tab.selected())?.tabId() | ||
| ); | ||
|
|
||
| activeTabTitle = computed(() => | ||
| this.tabs().find((tab) => tab.selected())?.title() | ||
| ); | ||
|
|
||
| activeTabContent = computed(() => | ||
| this.tabContents().find((content) => content.tabId() === this.activeTabId())?.content() | ||
| ); | ||
|
|
||
| unselectAllTabs() { | ||
| this.tabs().forEach(tab => tab.selected.set(false)); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.