Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 114 additions & 6 deletions src/aria/accordion/accordion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import {
'role': 'region',
'[attr.id]': '_pattern.id()',
'[attr.aria-labelledby]': '_pattern.accordionTrigger()?.id()',
'[attr.inert]': '_pattern.hidden() ? true : null',
'[attr.inert]': 'hidden() ? true : null',
},
})
export class AccordionPanel {
Expand All @@ -59,6 +59,9 @@ export class AccordionPanel {
/** A local unique identifier for the panel, used to match with its trigger's value. */
value = input.required<string>();

/** Whether the accordion panel is hidden. True if the associated trigger is not expanded. */
readonly hidden = computed(() => this._pattern.hidden());

/** The parent accordion trigger pattern that controls this panel. This is set by AccordionGroup. */
readonly accordionTrigger: WritableSignal<AccordionTriggerPattern | undefined> =
signal(undefined);
Expand All @@ -73,9 +76,24 @@ export class AccordionPanel {
constructor() {
// Connect the panel's hidden state to the DeferredContentAware's visibility.
afterRenderEffect(() => {
this._deferredContentAware.contentVisible.set(!this._pattern.hidden());
this._deferredContentAware.contentVisible.set(!this.hidden());
});
}

/** Opens this item. */
open(itemValue: string) {
this.accordionTrigger()?.expansionControl.open();
}

/** Closes this item. */
close(itemValue: string) {
this.accordionTrigger()?.expansionControl.close();
}

/** Toggles the expansion state of this item. */
toggle(itemValue: string) {
this.accordionTrigger()?.expansionControl.toggle();
}
}

/**
Expand All @@ -87,14 +105,14 @@ export class AccordionPanel {
exportAs: 'ngAccordionTrigger',
host: {
'class': 'ng-accordion-trigger',
'[attr.data-active]': '_pattern.active()',
'[attr.data-active]': 'active()',
'role': 'button',
'[id]': '_pattern.id()',
'[attr.aria-expanded]': '_pattern.expanded()',
'[attr.aria-expanded]': 'expanded()',
'[attr.aria-controls]': '_pattern.controls()',
'[attr.aria-disabled]': '_pattern.disabled()',
'[attr.aria-disabled]': 'disabled()',
'[attr.disabled]': 'hardDisabled() ? true : null',
'[attr.tabindex]': '_pattern.tabindex()',
'[attr.tabindex]': 'tabindex()',
'(keydown)': '_pattern.onKeydown($event)',
'(pointerdown)': '_pattern.onPointerdown($event)',
'(focusin)': '_pattern.onFocus($event)',
Expand All @@ -116,6 +134,18 @@ export class AccordionTrigger {
/** Whether the trigger is disabled. */
disabled = input(false, {transform: booleanAttribute});

/** Whether the trigger is active. */
readonly active = computed(() => this._pattern.active());

/** Whether the trigger is expanded. */
readonly expanded = computed(() => this._pattern.expanded());

/** The index of the trigger within its accordion group. */
readonly index = computed(() => this._pattern.index());

/** The tabindex of the trigger. */
readonly tabindex = computed(() => this._pattern.tabindex());

/**
* Whether this trigger is completely inaccessible.
*
Expand All @@ -135,6 +165,21 @@ export class AccordionTrigger {
accordionGroup: computed(() => this._accordionGroup._pattern),
accordionPanel: this.accordionPanel,
});

/** Opens this item. */
open(itemValue: string) {
this._pattern.expansionControl.open();
}

/** Closes this item. */
close(itemValue: string) {
this._pattern.expansionControl.close();
}

/** Toggles the expansion state of this item. */
toggle(itemValue: string) {
this._pattern.expansionControl.toggle();
}
}

/**
Expand Down Expand Up @@ -204,6 +249,69 @@ export class AccordionGroup {
}
});
}

/** Navigates to the first accordion panel. */
first() {
this._pattern.navigation.first();
}

/** Navigates to the last accordion panel. */
last() {
this._pattern.navigation.last();
}

/** Navigates to the previous accordion panel. */
prev() {
this._pattern.navigation.prev();
}

/** Navigates to the next accordion panel. */
next() {
this._pattern.navigation.next();
}

/** Opens the accordion panel with the specified value. */
open(itemValue: string) {
const trigger = this._findTriggerPatternByValue(itemValue);

if (trigger) {
this._pattern.expansionManager.open(trigger);
}
}

/** Closes the accordion panel with the specified value. */
close(itemValue: string) {
const trigger = this._findTriggerPatternByValue(itemValue);

if (trigger) {
this._pattern.expansionManager.close(trigger);
}
}

/** Toggles the expansion state of the accordion panel with the specified value. */
toggle(itemValue: string) {
const trigger = this._findTriggerPatternByValue(itemValue);

if (trigger) {
this._pattern.expansionManager.toggle(trigger);
}
}

/** Opens all accordion panels if multi-expandable. */
openAll() {
this._pattern.expansionManager.openAll();
}

/** Closes all accordion panels. */
closeAll() {
this._pattern.expansionManager.closeAll();
}

_findTriggerPatternByValue(value: string) {
const trigger = this._triggers().find(t => t.value() === value);

return trigger?._pattern;
}
}

/**
Expand Down
Loading