This is a component that can hide or show content using a button.
import { Component } from '@angular/core';
import {
HeadwindAccordionButtonComponent,
HeadwindAccordionComponent,
HeadwindAccordionContentDirective,
} from '@favian/headwind-ui';
import { animate, state, style, transition, trigger } from '@angular/animations';
@Component({
selector: 'app-basic-accordion-example',
standalone: true,
imports: [HeadwindAccordionComponent, HeadwindAccordionButtonComponent, HeadwindAccordionContentDirective],
template: `
<div class="w-full max-w-[400px] space-y-2 rounded-2xl bg-white p-8 shadow">
@for (person of people; track person.name) {
<headwind-accordion #accordion class="block space-y-2">
<headwind-accordion-button
class="flex items-center justify-between rounded-md bg-rose-500 px-3 py-2 text-sm text-white transition-colors hover:bg-rose-400"
>
<div>
{{ person.name }}
</div>
<svg
[@rotate]="accordion.opened ? 'rotated' : 'none'"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="h-4 w-4"
>
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</headwind-accordion-button>
<ng-template headwindAccordionContent>
<div [@expand] class="space-y-4 overflow-hidden py-3 text-sm">
<div class="flex items-center space-x-1">
<img
[src]="person.avatarUrl"
[alt]="person.name"
class="block h-10 w-10 rounded-full bg-zinc-200 object-cover"
/>
<div>
<div class="font-semibold">
{{ person.name }}
</div>
<div class="text-xs text-zinc-400">
{{ person.job }}
</div>
</div>
</div>
<div class="space-y-1">
<div class="text-xs text-zinc-400">Biography</div>
<div>
{{ person.biography }}
</div>
</div>
</div>
</ng-template>
</headwind-accordion>
}
</div>
`,
animations: [
trigger('expand', [
state(
'void',
style({
height: 0,
}),
),
transition(
'void => *',
animate(
'.1s',
style({
height: '*',
}),
),
),
transition(
'* => void',
animate(
'.1s',
style({
height: 0,
}),
),
),
]),
trigger('rotate', [
state(
'none',
style({
transform: 'rotate(0)',
}),
),
state(
'rotated',
style({
transform: 'rotate(180deg)',
}),
),
transition('none <=> rotated', animate('.1s')),
]),
],
})
export class BasicAccordionExampleComponent {
people = [
{
name: 'Tori Day',
avatarUrl: 'https://picsum.photos/id/174/64',
job: 'Designer',
biography:
'I can fit 6 brushes and pencils on each of my fingers and draw a picture. When working on a computer, I attach 4 mouses to my hands and feet, allowing me to work at a speed 5 times faster than others.',
},
{
name: 'Ishaan Martinez',
avatarUrl: 'https://picsum.photos/id/213/64',
job: 'Full-Stack Developer',
biography:
'From the day I was born, I was a coding prodigy who screamed "console.log(\'Waah~ Waah~\')". At the age of 3, I mastered JavaScript and TypeScript, and by the time I turned 7, I had evolved into a flawless full-stack developer.',
},
{
name: 'Alvin Bailey',
avatarUrl: 'https://picsum.photos/id/322/64',
job: 'Lawyer',
biography: 'I am an ordinary lawyer.',
},
];
}
Each component used to implement Accordion has the same class name as its name. You can set styles using the class name as a selector in a style file.
import { Component } from '@angular/core';
import {
HeadwindAccordionButtonComponent,
HeadwindAccordionComponent,
HeadwindAccordionContentDirective,
} from '@favian/headwind-ui';
@Component({
selector: 'app-accordion-classes-example',
standalone: true,
imports: [HeadwindAccordionComponent, HeadwindAccordionButtonComponent, HeadwindAccordionContentDirective],
template: `
<headwind-accordion>
<headwind-accordion-button> Button </headwind-accordion-button>
<ng-template headwindAccordionContent>
<div class="mt-3">Content</div>
</ng-template>
</headwind-accordion>
`,
styles: [
`
@tailwind components;
@layer components {
.headwind-accordion {
@apply block w-full max-w-[400px] rounded-2xl bg-white p-8 shadow;
}
.headwind-accordion-button {
@apply flex items-center justify-between rounded-md bg-rose-500 px-3 py-2 text-sm text-white transition-colors hover:bg-rose-400;
}
}
`,
],
})
export class AccordionClassesExampleComponent {}
When an Accordion is open, the <headwind-accordion>
component has the class .headwind-opened
.
import { Component } from '@angular/core';
import {
HeadwindAccordionButtonComponent,
HeadwindAccordionComponent,
HeadwindAccordionContentDirective,
} from '@favian/headwind-ui';
@Component({
selector: 'app-accordion-opened-class-example',
standalone: true,
imports: [HeadwindAccordionComponent, HeadwindAccordionButtonComponent, HeadwindAccordionContentDirective],
template: `
<headwind-accordion>
<headwind-accordion-button> Button</headwind-accordion-button>
<ng-template headwindAccordionContent>
<div class="mt-3">Content</div>
</ng-template>
</headwind-accordion>
`,
styles: [
`
@tailwind components;
@layer components {
.headwind-accordion {
@apply block w-full max-w-[400px] rounded-2xl bg-white p-8 shadow;
&.headwind-opened {
.headwind-accordion-button {
@apply bg-indigo-400;
}
}
}
.headwind-accordion-button {
@apply flex items-center justify-between rounded-md bg-rose-500 px-3 py-2 text-sm text-white transition-colors hover:bg-rose-400;
}
}
`,
],
})
export class AccordionOpenedClassExampleComponent {}
You can use the opened
attribute to change the display state of the content. When the opened state changes, the changed value is emitted through the openedChange
emitter.
import { Component } from '@angular/core';
import {
HeadwindAccordionButtonComponent,
HeadwindAccordionComponent,
HeadwindAccordionContentDirective,
} from '@favian/headwind-ui';
@Component({
selector: 'app-accordion-opened-state-example',
standalone: true,
imports: [HeadwindAccordionComponent, HeadwindAccordionButtonComponent, HeadwindAccordionContentDirective],
template: `
<headwind-accordion
[(opened)]="opened"
class="block w-full max-w-[400px] space-y-2 rounded-2xl bg-white p-8 shadow"
>
<headwind-accordion-button
class="block rounded-md bg-rose-500 px-3 py-2 text-sm text-white transition-colors hover:bg-rose-400"
>
Button Opened: {{ opened }}
</headwind-accordion-button>
<ng-template headwindAccordionContent>
<div class="mt-3">Content</div>
</ng-template>
</headwind-accordion>
`,
})
export class AccordionOpenedStateExampleComponent {
opened = true;
}
The <headwind-accordion>
component provides the toggle()
, open()
, and close()
methods.
import { Component } from '@angular/core';
import {
HeadwindAccordionButtonComponent,
HeadwindAccordionComponent,
HeadwindAccordionContentDirective,
} from '@favian/headwind-ui';
@Component({
selector: 'app-accordion-methods-example',
standalone: true,
imports: [HeadwindAccordionComponent, HeadwindAccordionButtonComponent, HeadwindAccordionContentDirective],
template: `
<div class="w-full max-w-[400px]">
<div class="flex flex-wrap items-stretch gap-2">
<button
(click)="accordion.toggle()"
class="min-h-8 flex-[1_1_0] rounded-md bg-rose-500 px-3 text-sm text-white"
>
Toggle Accordion
</button>
<button (click)="accordion.open()" class="min-h-8 flex-[1_1_0] rounded-md bg-rose-500 px-3 text-sm text-white">
Open Accordion
</button>
<button (click)="accordion.close()" class="min-h-8 flex-[1_1_0] rounded-md bg-rose-500 px-3 text-sm text-white">
Close Accordion
</button>
</div>
<headwind-accordion #accordion class="mt-3 block space-y-2 rounded-2xl bg-white p-8 shadow">
<headwind-accordion-button
class="block rounded-md bg-rose-500 px-3 py-2 text-sm text-white transition-colors hover:bg-rose-400"
>
Button
</headwind-accordion-button>
<ng-template headwindAccordionContent>
<div class="mt-3">Content</div>
</ng-template>
</headwind-accordion>
</div>
`,
})
export class AccordionMethodsExampleComponent {}
Bind an animation trigger to the content of [headwindAccordionContent]
to play animation when content is toggled.
import { Component } from '@angular/core';
import {
HeadwindAccordionButtonComponent,
HeadwindAccordionComponent,
HeadwindAccordionContentDirective,
} from '@favian/headwind-ui';
import { animate, state, style, transition, trigger } from '@angular/animations';
@Component({
selector: 'app-accordion-animation-example',
standalone: true,
imports: [HeadwindAccordionButtonComponent, HeadwindAccordionComponent, HeadwindAccordionContentDirective],
template: `
<headwind-accordion class="mt-3 block w-full max-w-[400px] space-y-2 rounded-2xl bg-white p-8 shadow">
<headwind-accordion-button
class="block rounded-md bg-rose-500 px-3 py-2 text-sm text-white transition-colors hover:bg-rose-400"
>
Button
</headwind-accordion-button>
<ng-template headwindAccordionContent>
<div [@expand] class="mt-3">Content</div>
</ng-template>
</headwind-accordion>
`,
animations: [
trigger('expand', [
state(
'void',
style({
height: 0,
}),
),
transition(
'void => *',
animate(
'.1s',
style({
height: '*',
}),
),
),
transition(
'* => void',
animate(
'.1s',
style({
height: 0,
}),
),
),
]),
],
})
export class AccordionAnimationExampleComponent {}
Clicking on the <headwind-accordion-button>
element toggles its contents.
Command | Target | Description |
---|---|---|
Space , Enter |
<headwind-accordion-button> |
Toggle the contents. |
The root component of Accordion.
<headwind-accordion>
.headwind-accordion
<br/>
.headwind-opened
when Accordion opened.
Name | Description |
---|---|
@Input() set opened(value: boolean) |
Set the opened state of content. |
Name | Description |
---|---|
@Output() openedChange: EventEmitter<boolean> |
Emits the changed opened state of content. |
Name | Description |
---|---|
toggle() |
Toggle the opened state of Content. |
open() |
Open the content. If it is already open, it is ignored. |
close() |
Close the content. If it is already closed, it is ignored. |
A component that can open and close the Accordion content.
<headwind-accordion-button>
.headwind-accordion-button
A directive for a template that wraps Accordion content.
ng-template[headwindAccordionContent]