Files
ISA-Frontend/libs/ui/expandable/README.md
2025-06-06 15:34:33 +00:00

4.6 KiB

UI Expandable Directives

A set of Angular directives for creating expandable/collapsible content sections with proper accessibility support.

Features

  • Signal-based expanded/collapsed state management
  • Simple template-based conditional rendering
  • Supports two-way binding
  • Built-in accessibility support (ARIA attributes)
  • Modern Angular implementation using directives, signals, effects, and DI

Installation

This library is part of the ISA-Frontend project and is already available in the workspace.

Usage

Basic Usage

import { Component } from '@angular/core';
import { 
  ExpandableDirective, 
  ExpandedDirective, 
  CollapsedDirective, 
  ExpandableTriggerDirective 
} from '@isa/ui/expandable';

@Component({
  selector: 'app-my-component',
  standalone: true,
  imports: [
    ExpandableDirective,
    ExpandedDirective,
    CollapsedDirective,
    ExpandableTriggerDirective
  ],
  template: `
    <div uiExpandable>
      <button 
        uiExpandableTrigger="my-section" 
        #trigger="uiExpandableTrigger"
        uiTextButton 
        type="button" 
        color="strong" 
        size="small"
      >
        <ng-icon [name]="trigger.expanded() ? 'isaActionMinus' : 'isaActionPlus'"></ng-icon>
        {{ trigger.expanded() ? 'Less details' : 'More details' }}
      </button>

      <div [id]="'my-section'">
        <ng-container *uiCollapsed>
          <!-- Content shown when collapsed -->
          <p>Summary information</p>
        </ng-container>

        <ng-container *uiExpanded>
          <!-- Content shown when expanded -->
          <p>Detailed information</p>
        </ng-container>
      </div>
    </div>
  `
})
export class MyComponent {}

With Two-Way Binding

import { Component, signal } from '@angular/core';
import { ExpandableDirectives } from '@isa/ui/expandable';

@Component({
  selector: 'app-my-component',
  standalone: true,
  imports: [...ExpandableDirectives],
  template: `
    <div uiExpandable [(uiExpandable)]="isExpanded">
      <button 
        uiExpandableTrigger="details-section" 
        #trigger="uiExpandableTrigger"
        uiTextButton
      >
        Toggle Details
      </button>

      <div id="details-section">
        <ng-container *uiExpanded>
          Expanded content
        </ng-container>
        <ng-container *uiCollapsed>
          Collapsed content
        </ng-container>
      </div>
    </div>

    <p>The section is currently: {{ isExpanded() ? 'Expanded' : 'Collapsed' }}</p>
    <button (click)="isExpanded.set(true)">Expand from outside</button>
  `
})
export class MyComponent {
  isExpanded = signal(false);
}

API Reference

ExpandableDirective

The main container directive that manages expanded/collapsed state.

Selector: [uiExpandable]

Inputs:

  • [(uiExpandable)]: Two-way binding for the expanded state.

Methods:

  • toggle(): Toggles between expanded and collapsed states.

ExpandedDirective

Structural directive that shows content only when expanded.

Selector: [uiExpanded]

CollapsedDirective

Structural directive that shows content only when collapsed.

Selector: [uiCollapsed]

ExpandableTriggerDirective

Adds toggle functionality and accessibility attributes to an element.

Selector: [uiExpandableTrigger]

Inputs:

  • uiExpandableTrigger: String ID of the element being controlled (used for aria-controls).

Methods:

  • toggle(): Toggles the parent expandable's state.
  • expanded(): Returns the current expanded state (signal).

Exported as: uiExpandableTrigger

Accessibility

These directives automatically add the following accessibility features:

  • role="button" on the trigger element
  • aria-expanded with the current state on the trigger element
  • aria-controls linking the trigger to the content section (requires matching the ID)

Example: Real-world Usage in Return Details Component

<div uiExpandable>
  <label class="-ml-3" uiTextButton type="button" color="strong" size="small" uiExpandableTrigger="return-details" #trigger="uiExpandableTrigger">
    <ng-icon [name]="trigger.expanded() ? 'isaActionMinus' : 'isaActionPlus'"></ng-icon>
    {{ trigger.expanded() ? 'Weniger anzeigen' : 'Bestelldetails anzeigen' }}
  </label>

  <div id="return-details">
    <ng-container *uiExpanded>
      <oms-feature-return-details-order-group-data [receipt]="receipt"></oms-feature-return-details-order-group-data>
    </ng-container>

    <ng-container *uiCollapsed>
      <oms-feature-return-details-data [receipt]="receipt"></oms-feature-return-details-data>
    </ng-container>
  </div>
</div>

Running unit tests

Run nx test ui-expandable to execute the unit tests.