@tedi-design-system/angular 7.1.0-rc.21 → 7.1.0-rc.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19602,7 +19602,7 @@ const navigateTablist = (event) => {
19602
19602
  const tablist = current.closest('[role="tablist"]');
19603
19603
  if (!tablist)
19604
19604
  return null;
19605
- const tabs = Array.from(tablist.querySelectorAll('[role="tab"]:not([disabled])')).filter((tab) => getComputedStyle(tab).display !== "none");
19605
+ const tabs = Array.from(tablist.querySelectorAll('[role="tab"]:not([disabled]):not([aria-disabled="true"])')).filter((tab) => getComputedStyle(tab).display !== "none");
19606
19606
  const currentIndex = tabs.indexOf(current);
19607
19607
  if (tabs.length === 0 || currentIndex === -1)
19608
19608
  return null;
@@ -19616,12 +19616,16 @@ const navigateTablist = (event) => {
19616
19616
  };
19617
19617
 
19618
19618
  /**
19619
- * A single tab button inside `tedi-tabs-list`. Applied to a native `<button>`
19620
- * so it inherits native focus, disabled and activation behaviour.
19619
+ * A single tab inside `tedi-tabs-list`. Applied to a native `<button>` (in-page
19620
+ * tab) or `<a>` (a tab that navigates to a route — add `href`/`routerLink`).
19621
+ * The anchor form keeps the same `role="tab"` semantics but is a real link, so
19622
+ * it works with keyboard/new-tab/copy-link as WCAG expects for navigation.
19621
19623
  */
19622
19624
  class TabsTriggerComponent {
19623
19625
  tabs = inject(TabsComponent);
19624
19626
  host = inject(ElementRef);
19627
+ /** Whether the trigger is rendered as an anchor (`<a>`) rather than a button. */
19628
+ isAnchor = this.host.nativeElement.tagName === "A";
19625
19629
  /**
19626
19630
  * Unique identifier for this tab. Used as the element id and to link to the
19627
19631
  * corresponding `tedi-tabs-content` panel (`aria-controls="{id}-panel"`).
@@ -19632,6 +19636,11 @@ class TabsTriggerComponent {
19632
19636
  /** Whether the tab is disabled. */
19633
19637
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
19634
19638
  isSelected = computed(() => this.tabs.activeTab() === this.id(), ...(ngDevMode ? [{ debugName: "isSelected" }] : []));
19639
+ tabIndex = computed(() => {
19640
+ if (this.disabled())
19641
+ return -1;
19642
+ return this.isSelected() ? 0 : -1;
19643
+ }, ...(ngDevMode ? [{ debugName: "tabIndex" }] : []));
19635
19644
  /** Plain-text label, used as the accessible name of the overflow dropdown item. */
19636
19645
  get label() {
19637
19646
  return this.host.nativeElement.textContent?.trim() ?? "";
@@ -19646,36 +19655,74 @@ class TabsTriggerComponent {
19646
19655
  inline: "nearest",
19647
19656
  });
19648
19657
  }
19649
- handleClick() {
19650
- if (!this.disabled()) {
19651
- this.tabs.select(this.id());
19658
+ handleClick(event) {
19659
+ if (this.disabled()) {
19660
+ // Buttons are inert via the disabled attribute; a disabled anchor is kept
19661
+ // unreachable via `pointer-events: none` + `tabindex="-1"`. preventDefault
19662
+ // is a final guard against native href traversal. (A consumer-supplied
19663
+ // `routerLink` navigates from its own click handler and can't be blocked
19664
+ // here — bind `[routerLink]` to null while disabled, see docs.)
19665
+ event?.preventDefault();
19666
+ return;
19667
+ }
19668
+ // An anchor opened in another browsing context — a modifier/middle click or
19669
+ // target="_blank" — must not change the active tab in this view. Let the
19670
+ // browser (or RouterLink, which also skips modifier clicks) handle it.
19671
+ if (this.isAnchor && this.opensInNewBrowsingContext(event)) {
19672
+ return;
19673
+ }
19674
+ this.tabs.select(this.id());
19675
+ }
19676
+ opensInNewBrowsingContext(event) {
19677
+ if (event instanceof MouseEvent &&
19678
+ (event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey)) {
19679
+ return true;
19652
19680
  }
19681
+ const target = this.host.nativeElement.target;
19682
+ return target !== "" && target !== "_self";
19653
19683
  }
19654
19684
  handleKeydown(event) {
19685
+ // Anchors don't activate on Space natively; the tab pattern expects it to,
19686
+ // so forward it to a click (which drives routerLink/href navigation).
19687
+ if (this.isAnchor && event.key === " ") {
19688
+ event.preventDefault();
19689
+ if (!this.disabled()) {
19690
+ this.host.nativeElement.click();
19691
+ }
19692
+ return;
19693
+ }
19655
19694
  const target = navigateTablist(event);
19656
19695
  if (target) {
19657
- this.tabs.select(target.id);
19696
+ // Automatic activation for button tabs — activation just toggles an
19697
+ // in-page panel. Anchor tabs navigate, so use manual activation: arrows
19698
+ // only move focus and the user presses Enter/Space to follow the link
19699
+ // (APG's recommended mode when activation is disruptive).
19700
+ if (target.tagName !== "A") {
19701
+ this.tabs.select(target.id);
19702
+ }
19658
19703
  }
19659
19704
  }
19660
19705
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: TabsTriggerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19661
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: TabsTriggerComponent, isStandalone: true, selector: "button[tedi-tabs-trigger]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "button", "role": "tab" }, listeners: { "click": "handleClick()", "keydown": "handleKeydown($event)" }, properties: { "id": "id()", "disabled": "disabled()", "attr.aria-selected": "isSelected()", "attr.aria-controls": "id() + '-panel'", "attr.tabindex": "isSelected() ? 0 : -1", "attr.data-name": "'tabs-trigger'", "class.tedi-tabs-trigger--selected": "isSelected()" }, classAttribute: "tedi-tabs-trigger" }, ngImport: i0, template: "@if (icon()) {\n <tedi-icon [name]=\"icon()!\" [size]=\"18\" color=\"inherit\" />\n}\n<ng-content />\n", styles: [".tedi-tabs-trigger{--_tab-background: var(--tab-item-default-background);--_tab-color: var(--tab-item-default-text);display:inline-flex;gap:var(--tab-inner-spacing);align-items:center;justify-content:center;padding:var(--tab-spacing-y) var(--tab-spacing-x);font-size:var(--body-regular-size);color:var(--_tab-color);white-space:nowrap;cursor:pointer;background:var(--_tab-background);border:none}.tedi-tabs-trigger:hover{--_tab-background: var(--tab-item-hover-background);--_tab-color: var(--tab-item-hover-text)}.tedi-tabs-trigger:focus-visible{outline:none;box-shadow:inset 0 0 0 var(--tedi-borders-02) var(--general-border-brand)}.tedi-tabs-trigger:active{--_tab-background: var(--tab-item-active-background);--_tab-color: var(--tab-item-active-text)}.tedi-tabs-trigger{position:relative;text-decoration:none}.tedi-tabs-trigger--selected{--_tab-background: var(--tab-item-selected-background);--_tab-color: var(--tab-item-selected-text);font-weight:var(--body-bold-weight)}.tedi-tabs-trigger--selected:after{position:absolute;top:0;right:0;left:0;content:\"\";border-top:3px solid var(--tab-item-selected-border)}.tedi-tabs-trigger:disabled{pointer-events:none;opacity:.4}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "tedi-icon", inputs: ["name", "size", "color", "background", "variant", "type", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
19706
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: TabsTriggerComponent, isStandalone: true, selector: "button[tedi-tabs-trigger], a[tedi-tabs-trigger]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "tab" }, listeners: { "click": "handleClick($event)", "keydown": "handleKeydown($event)" }, properties: { "attr.type": "isAnchor ? null : 'button'", "id": "id()", "attr.disabled": "!isAnchor && disabled() ? '' : null", "attr.aria-disabled": "isAnchor && disabled() ? 'true' : null", "attr.aria-selected": "isSelected()", "attr.aria-controls": "id() + '-panel'", "attr.tabindex": "tabIndex()", "attr.data-name": "'tabs-trigger'", "class.tedi-tabs-trigger--selected": "isSelected()", "class.tedi-tabs-trigger--disabled": "disabled()" }, classAttribute: "tedi-tabs-trigger" }, ngImport: i0, template: "@if (icon()) {\n <tedi-icon [name]=\"icon()!\" [size]=\"18\" color=\"inherit\" />\n}\n<ng-content />\n", styles: [".tedi-tabs-trigger{--_tab-background: var(--tab-item-default-background);--_tab-color: var(--tab-item-default-text);display:inline-flex;gap:var(--tab-inner-spacing);align-items:center;justify-content:center;padding:var(--tab-spacing-y) var(--tab-spacing-x);font-size:var(--body-regular-size);color:var(--_tab-color);white-space:nowrap;cursor:pointer;background:var(--_tab-background);border:none}.tedi-tabs-trigger:hover{--_tab-background: var(--tab-item-hover-background);--_tab-color: var(--tab-item-hover-text)}.tedi-tabs-trigger:focus-visible{outline:none;box-shadow:inset 0 0 0 var(--tedi-borders-02) var(--general-border-brand)}.tedi-tabs-trigger:active{--_tab-background: var(--tab-item-active-background);--_tab-color: var(--tab-item-active-text)}.tedi-tabs-trigger{position:relative;text-decoration:none}.tedi-tabs-trigger--selected{--_tab-background: var(--tab-item-selected-background);--_tab-color: var(--tab-item-selected-text);font-weight:var(--body-bold-weight)}.tedi-tabs-trigger--selected:after{position:absolute;top:0;right:0;left:0;content:\"\";border-top:3px solid var(--tab-item-selected-border)}.tedi-tabs-trigger--disabled{pointer-events:none;opacity:.4}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "tedi-icon", inputs: ["name", "size", "color", "background", "variant", "type", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
19662
19707
  }
19663
19708
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: TabsTriggerComponent, decorators: [{
19664
19709
  type: Component,
19665
- args: [{ selector: "button[tedi-tabs-trigger]", standalone: true, imports: [IconComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
19710
+ args: [{ selector: "button[tedi-tabs-trigger], a[tedi-tabs-trigger]", standalone: true, imports: [IconComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
19666
19711
  class: "tedi-tabs-trigger",
19667
- type: "button",
19668
19712
  role: "tab",
19713
+ "[attr.type]": "isAnchor ? null : 'button'",
19669
19714
  "[id]": "id()",
19670
- "[disabled]": "disabled()",
19715
+ "[attr.disabled]": "!isAnchor && disabled() ? '' : null",
19716
+ "[attr.aria-disabled]": "isAnchor && disabled() ? 'true' : null",
19671
19717
  "[attr.aria-selected]": "isSelected()",
19672
19718
  "[attr.aria-controls]": "id() + '-panel'",
19673
- "[attr.tabindex]": "isSelected() ? 0 : -1",
19719
+ "[attr.tabindex]": "tabIndex()",
19674
19720
  "[attr.data-name]": "'tabs-trigger'",
19675
19721
  "[class.tedi-tabs-trigger--selected]": "isSelected()",
19676
- "(click)": "handleClick()",
19722
+ "[class.tedi-tabs-trigger--disabled]": "disabled()",
19723
+ "(click)": "handleClick($event)",
19677
19724
  "(keydown)": "handleKeydown($event)",
19678
- }, template: "@if (icon()) {\n <tedi-icon [name]=\"icon()!\" [size]=\"18\" color=\"inherit\" />\n}\n<ng-content />\n", styles: [".tedi-tabs-trigger{--_tab-background: var(--tab-item-default-background);--_tab-color: var(--tab-item-default-text);display:inline-flex;gap:var(--tab-inner-spacing);align-items:center;justify-content:center;padding:var(--tab-spacing-y) var(--tab-spacing-x);font-size:var(--body-regular-size);color:var(--_tab-color);white-space:nowrap;cursor:pointer;background:var(--_tab-background);border:none}.tedi-tabs-trigger:hover{--_tab-background: var(--tab-item-hover-background);--_tab-color: var(--tab-item-hover-text)}.tedi-tabs-trigger:focus-visible{outline:none;box-shadow:inset 0 0 0 var(--tedi-borders-02) var(--general-border-brand)}.tedi-tabs-trigger:active{--_tab-background: var(--tab-item-active-background);--_tab-color: var(--tab-item-active-text)}.tedi-tabs-trigger{position:relative;text-decoration:none}.tedi-tabs-trigger--selected{--_tab-background: var(--tab-item-selected-background);--_tab-color: var(--tab-item-selected-text);font-weight:var(--body-bold-weight)}.tedi-tabs-trigger--selected:after{position:absolute;top:0;right:0;left:0;content:\"\";border-top:3px solid var(--tab-item-selected-border)}.tedi-tabs-trigger:disabled{pointer-events:none;opacity:.4}\n"] }]
19725
+ }, template: "@if (icon()) {\n <tedi-icon [name]=\"icon()!\" [size]=\"18\" color=\"inherit\" />\n}\n<ng-content />\n", styles: [".tedi-tabs-trigger{--_tab-background: var(--tab-item-default-background);--_tab-color: var(--tab-item-default-text);display:inline-flex;gap:var(--tab-inner-spacing);align-items:center;justify-content:center;padding:var(--tab-spacing-y) var(--tab-spacing-x);font-size:var(--body-regular-size);color:var(--_tab-color);white-space:nowrap;cursor:pointer;background:var(--_tab-background);border:none}.tedi-tabs-trigger:hover{--_tab-background: var(--tab-item-hover-background);--_tab-color: var(--tab-item-hover-text)}.tedi-tabs-trigger:focus-visible{outline:none;box-shadow:inset 0 0 0 var(--tedi-borders-02) var(--general-border-brand)}.tedi-tabs-trigger:active{--_tab-background: var(--tab-item-active-background);--_tab-color: var(--tab-item-active-text)}.tedi-tabs-trigger{position:relative;text-decoration:none}.tedi-tabs-trigger--selected{--_tab-background: var(--tab-item-selected-background);--_tab-color: var(--tab-item-selected-text);font-weight:var(--body-bold-weight)}.tedi-tabs-trigger--selected:after{position:absolute;top:0;right:0;left:0;content:\"\";border-top:3px solid var(--tab-item-selected-border)}.tedi-tabs-trigger--disabled{pointer-events:none;opacity:.4}\n"] }]
19679
19726
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
19680
19727
 
19681
19728
  /**