Accordion

Abstract base directive for accordion components. This package provides the base class for creating custom accordion implementations.


Usage

<smart-accordion [options]="options" [(show)]="open">
  <span accordionHeader>What is your refund policy?</span>
  <p accordionBody>You can request a full refund within 30 days of purchase.</p>
</smart-accordion>

Base Class API

Inputs

InputTypeDefaultDescription
showModelSignal<boolean>falseTwo-way binding for open state
optionsInputSignal<IAccordionOptions | undefined>undefinedAccordion configuration
cssClassInputSignal<string>''External CSS classes
headerTplInputSignal<TemplateRef>requiredHeader template
bodyTplInputSignal<TemplateRef>requiredBody template

IAccordionOptions

  • open is the initial state. When it is true on first render and show has not been set to true by the consumer, AccordionBaseComponent.ngOnInit sets show to true once and emits showChange, so both <smart-accordion> (default) and <smart-accordion-preset> start expanded and a bound [(show)] is updated to true. It is applied only once: later changes to options.open are ignored and later toggles / [(show)] writes are never overridden. Bind [(show)] to a signal when combining it with open; a plain class field updated during the first change detection raises NG0100 (ExpressionChangedAfterItHasBeenChecked) in dev mode.
  • disabled makes toggle() a no-op.
  • animated is deprecated: no variant (default or preset) animates expand/collapse.

Computed Properties

PropertyTypeDescription
sharedContainerClassesSignal<string[]>Divider, rounded, border classes with dark mode support

Methods

MethodDescription
toggle()Toggles show signal (no-op if disabled)
ngOnInit()Applies options.open as the initial state (sets show to true once)

Extending the base class

import { NgTemplateOutlet } from '@angular/common';
import {
  ChangeDetectionStrategy,
  Component,
  computed,
  signal,
  ViewEncapsulation,
} from '@angular/core';

import {
  AccordionBaseComponent,
  IAccordionOptions,
} from '@smartsoft001/angular';

@Component({
  selector: 'docs-custom-accordion',
  imports: [NgTemplateOutlet],
  template: `
    <div [class]="containerClasses()">
      <button
        type="button"
        class="docs-accordion__header"
        [disabled]="options()?.disabled ?? false"
        [attr.aria-expanded]="show()"
        (click)="toggle()"
      >
        <ng-container [ngTemplateOutlet]="headerTpl()" />
        <span aria-hidden="true">{{ show() ? '-' : '+' }}</span>
      </button>

      @if (show()) {
        <div class="docs-accordion__body">
          <ng-container [ngTemplateOutlet]="bodyTpl()" />
        </div>
      }
    </div>
  `,
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomAccordionComponent extends AccordionBaseComponent {
  containerClasses = computed(() =>
    ['docs-accordion', ...this.sharedContainerClasses(), this.cssClass()]
      .filter(Boolean)
      .join(' '),
  );
}

// The accordion has no standard-component token, so a custom implementation is
// rendered directly by its own selector instead of being injected into
// <smart-accordion>. The required headerTpl / bodyTpl inputs are <ng-template>
// references supplied by the host.
@Component({
  selector: 'docs-accordion-custom-example',
  imports: [CustomAccordionComponent],
  template: `
    <ng-template #headerTpl
      >What is the best thing about Switzerland?</ng-template
    >
    <ng-template #bodyTpl
      >I don't know, but the flag is a big plus.</ng-template
    >

    <docs-custom-accordion
      [headerTpl]="headerTpl"
      [bodyTpl]="bodyTpl"
      [(show)]="open"
      [options]="options"
    />
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AccordionCustomExampleComponent {
  open = signal(false);

  options: IAccordionOptions = { disabled: false };
}

AccordionPresetComponent (<smart-accordion-preset>)

A fully styled, drop-in accordion concrete based on the Preline bordered accordion (FRA-210). It extends AccordionBaseComponent, so it consumes the exact same contract as AccordionDefaultComponent: the headerTpl / bodyTpl required template inputs, the show two-way model, options and cssClass.

Not token-swappable. Unlike most preset variations in this library, the accordion has no ACCORDION_STANDARD_COMPONENT_TOKEN and the <smart-accordion> wrapper hard-codes <smart-accordion-default>. There is no NgComponentOutlet/DI seam, so the preset cannot be registered to restyle <smart-accordion>. Use it directly via the <smart-accordion-preset> selector and supply the templates yourself.

Expand/collapse is driven entirely by the inherited show model signal plus @if — no Preline JS runtime is required. The header arrow is an inline chevron (down when collapsed, up when expanded) and the container border becomes visible only while open.

Source

The component lives in packages/shared/angular/src/lib/components/accordion and is documented for Claude Code by the angular-components-accordion skill.