import {
ChangeDetectionStrategy,
Component,
computed,
input,
model,
} from '@angular/core';
import { AfricaniesIconComponent } from '@africanies/africanies-icons';
/**
* Visual density for {@link AccordionComponent}.
*
* - `md` — page sections (pay review, top-level cards)
* - `sm` — nested panels (e.g. export boxes inside a manifest box)
*/
export type AccordionSize = 'md' | 'sm';
/**
* Bordered expandable panel with animated fold — the pattern used on
* Manifest detail and Make Payment review.
*
* Parent owns open state via {@link open} (`model()` / `[(open)]`).
*
* @example
* ```html
*
* …
*
* ```
*/
@Component({
selector: 'africanies-accordion',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [AfricaniesIconComponent],
host: {
class: 'block',
},
styles: `
.africanies-accordion-fold {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 200ms ease;
}
.africanies-accordion-fold-open {
grid-template-rows: 1fr;
}
.africanies-accordion-fold-body {
min-height: 0;
overflow: hidden;
}
@media (prefers-reduced-motion: reduce) {
.africanies-accordion-fold {
transition: none;
}
}
`,
template: `
`,
})
/**
* Bordered expandable panel with animated fold — the pattern used on Manifest detail and Make Payment review.
*/
export class AccordionComponent {
/** Plain-text header. Prefer projected `[africaniesAccordionTitle]` for rich titles. */
readonly title = input('');
/** Whether the panel body is expanded. */
readonly open = model(false);
/** Padding / chevron density. */
readonly size = input('md');
protected readonly chevronSize = computed(() =>
this.size() === 'sm' ? 14 : 16,
);
protected readonly shellClass = computed(() =>
this.size() === 'sm'
? 'rounded-lg border border-border dark:border-white/10'
: 'rounded-xl border border-border dark:border-white/10',
);
protected readonly triggerClass = computed(() =>
this.size() === 'sm'
? 'flex w-full items-center justify-between gap-3 px-3 py-2 text-left text-ink dark:text-white'
: 'flex w-full items-center justify-between gap-3 px-4 py-3 text-left text-ink dark:text-white',
);
protected readonly bodyClass = computed(() =>
this.size() === 'sm'
? 'border-t border-border px-3 py-2 dark:border-white/10'
: 'border-t border-border px-4 py-3 dark:border-white/10',
);
protected toggle(): void {
this.open.update((value) => !value);
}
}