Skip to content
Open
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
<div demo class="w-full h-full flex justify-center items-center">
<app-tryout [title]="'COMPONENTS.ACCORDION' | translate">
<ng-container component>
<ids-accordion
<ul
#accordion
idsAccordion
[multi]="_accordionDemoService.model.multi"
[appearance]="_accordionDemoService.model.appearance"
[headingLevel]="_accordionDemoService.model.headingLevel"
[size]="_accordionDemoService.model.size"
[disabled]="_accordionDemoService.model.disabled"
[expandBtnLabel]="_accordionDemoService.model.expandBtnLabel"
Expand All @@ -16,19 +18,19 @@
[hasLeadingIcon]="_accordionDemoService.model.hasLeadingIcon"
[hasTrailingIcon]="_accordionDemoService.model.hasTrailingIcon"
>
<ids-accordion-item [summary]="_accordionDemoService.model.summary">
<li idsAccordionItem [summary]="_accordionDemoService.model.summary">
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy
text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
</ids-accordion-item>
<ids-accordion-item [summary]="_accordionDemoService.model.summary">
</li>
<li idsAccordionItem [summary]="_accordionDemoService.model.summary">
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy
text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
</ids-accordion-item>
<ids-accordion-item [summary]="_accordionDemoService.model.summary">
</li>
<li idsAccordionItem [summary]="_accordionDemoService.model.summary">
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy
text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
</ids-accordion-item>
</ids-accordion>
</li>
</ul>
</ng-container>
</app-tryout>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DemoControl, DemoControlConfig } from '@demo-types/demo-control.type';
import { DemoMethodConfig } from '@demo-types/demo-method.type';
import { convertEnumToStringArray } from '@demo-utils/convert-enum-to-string-array';
import { getDefaultFromDemoConfig } from '@demo-utils/get-defaults-from-demo-config';
import { IDS_ACCORDION_DEFAULT_CONFIG_FACTORY, IdsAccordionAppearance, IdsAccordionAppearanceType } from '@i-cell/ids-angular/accordion';
import { IDS_ACCORDION_DEFAULT_CONFIG_FACTORY, IdsAccordionAppearance, IdsAccordionAppearanceType, IdsAccordionHeadingLevel, IdsAccordionHeadingLevelType } from '@i-cell/ids-angular/accordion';
import { IdsButtonAppearance, IdsButtonAppearanceType, IdsButtonVariant, IdsButtonVariantType } from '@i-cell/ids-angular/button';
import { IdsSize, IdsSizeType } from '@i-cell/ids-angular/core';
import { Subject } from 'rxjs';
Expand All @@ -13,6 +13,7 @@ const defaultConfig = IDS_ACCORDION_DEFAULT_CONFIG_FACTORY();
type AccordionInputControls = {
size: IdsSizeType;
appearance: IdsAccordionAppearanceType;
headingLevel: IdsAccordionHeadingLevelType;
summary: string;
disabled: boolean;
multi: boolean;
Expand Down Expand Up @@ -45,6 +46,13 @@ export class AccordionDemoService {
control: DemoControl.SELECT,
list: convertEnumToStringArray(IdsAccordionAppearance),
},
headingLevel: {
description: 'Heading level.',
type: 'IdsAccordionHeadingLevelType',
default: defaultConfig.headingLevel,
control: DemoControl.SELECT,
list: convertEnumToStringArray(IdsAccordionHeadingLevel),
},
summary: {
description: 'Summary of accordion',
type: 'string',
Expand Down
10 changes: 9 additions & 1 deletion projects/widgets/accordion/accordion-defaults.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { IdsAccordionAppearance, IdsAccordionAppearanceType } from './types/accordion-appearance.type';
import { IdsAccordionHeadingLevel, IdsAccordionHeadingLevelType } from './types/accordion-heading-level.type';

import { InjectionToken } from '@angular/core';
import { IdsButtonAppearance, IdsButtonAppearanceType, IdsButtonVariant, IdsButtonVariantType } from '@i-cell/ids-angular/button';
import {
IdsButtonAppearance,
IdsButtonAppearanceType,
IdsButtonVariant,
IdsButtonVariantType,
} from '@i-cell/ids-angular/button';
import { IdsSize, IdsSizeType } from '@i-cell/ids-angular/core';

export interface IdsAccordionDefaultConfig {
size?: IdsSizeType
appearance?: IdsAccordionAppearanceType
headingLevel?: IdsAccordionHeadingLevelType,
multi?: boolean,
btnSize?: IdsSizeType,
btnAppearance?: IdsButtonAppearanceType,
Expand All @@ -29,6 +36,7 @@ export function IDS_ACCORDION_DEFAULT_CONFIG_FACTORY(): Required<IdsAccordionDef
return {
size: IdsSize.COMPACT,
appearance: IdsAccordionAppearance.FILLED,
headingLevel: IdsAccordionHeadingLevel.H3,
multi: false,
btnSize: IdsSize.COMPACT,
btnAppearance: IdsButtonAppearance.FILLED,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,65 @@
<div
#header
role="button"
class="ids-accordion-item-summary"
[id]="_headerId()"
[attr.aria-expanded]="isExpanded ? 'true' : 'false'"
[attr.aria-controls]="_contentId()"
[attr.tabindex]="_parentOrSelfDisabled() ? -1 : 0"
[attr.aria-disabled]="_parentOrSelfDisabled()"
(click)="toggle()"
>
@if (_parentOrSelfHasLeadingIcon()) {
<ids-icon icon-leading [fontIcon]="_icon" />
@switch (_parentHeadingLevel()) {
@case ('h1') {
<h1>
<ng-container [ngTemplateOutlet]="summaryButtonTemplate" />
</h1>
}
<span class="ids-accordion-item-title">{{ summary() }}</span>
@if (_parentOrSelfHasTrailingIcon()) {
<ids-icon icon-trailing [fontIcon]="_icon" />
@case ('h2') {
<h2>
<ng-container [ngTemplateOutlet]="summaryButtonTemplate" />
</h2>
}
</div>
@case ('h3') {
<h3>
<ng-container [ngTemplateOutlet]="summaryButtonTemplate" />
</h3>
}
@case ('h4') {
<h4>
<ng-container [ngTemplateOutlet]="summaryButtonTemplate" />
</h4>
}
@case ('h5') {
<h5>
<ng-container [ngTemplateOutlet]="summaryButtonTemplate" />
</h5>
}
@case ('h6') {
<h6>
<ng-container [ngTemplateOutlet]="summaryButtonTemplate" />
</h6>
}
@default {
<h3>
<ng-container [ngTemplateOutlet]="summaryButtonTemplate" />
</h3>
}
}

<ng-template #summaryButtonTemplate>
<button
#header
type="button"
role="button"
class="ids-accordion-item-summary"
[id]="_headerId()"
[attr.aria-expanded]="isExpanded ? 'true' : 'false'"
[attr.aria-controls]="_contentId()"
[attr.tabindex]="_parentOrSelfDisabled() ? -1 : 0"
[attr.aria-disabled]="_parentOrSelfDisabled()"
(click)="toggle()"
>
@if (_parentOrSelfHasLeadingIcon()) {
<ids-icon icon-leading [fontIcon]="_icon" />
}
<span class="ids-accordion-item-title">
{{ summary() }}
</span>
@if (_parentOrSelfHasTrailingIcon()) {
<ids-icon icon-trailing [fontIcon]="_icon" />
}
</button>
</ng-template>
<div
role="region"
class="ids-accordion-item-content"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ import { accordionAnimations } from '../accordion-animations';
import { IdsAccordionComponent } from '../accordion.component';

import { CdkAccordionItem } from '@angular/cdk/accordion';
import { NgTemplateOutlet } from '@angular/common';
import { ChangeDetectionStrategy, Component, computed, ElementRef, inject, input, viewChild, ViewEncapsulation } from '@angular/core';
import { coerceBooleanAttribute, ComponentBase } from '@i-cell/ids-angular/core';
import { IdsIconComponent } from '@i-cell/ids-angular/icon';

@Component({
selector: 'ids-accordion-item',
imports: [IdsIconComponent],
selector: 'ids-accordion-item, li[idsAccordionItem]',
imports: [
IdsIconComponent,
NgTemplateOutlet,
],
templateUrl: './accordion-item.component.html',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
Expand Down Expand Up @@ -47,6 +51,7 @@ export class IdsAccordionItemComponent extends ComponentBase {
protected _parentOrSelfHasLeadingIcon = computed(() => this._accordion.hasLeadingIcon() ?? this.hasLeadingIcon());
protected _parentOrSelfHasTrailingIcon = computed(() => this._accordion.hasTrailingIcon() ?? this.hasTrailingIcon());
protected _parentOrSelfDisabled = computed(() => this._accordion.disabled() || this.disabled());
protected _parentHeadingLevel = computed(() => this._accordion.headingLevel());

protected _hostClasses = computed(() => this._getHostClasses(
[this._parentOrSelfDisabled() ? 'disabled' : null],
Expand Down
8 changes: 6 additions & 2 deletions projects/widgets/accordion/accordion.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { IDS_ACCORDION_DEFAULT_CONFIG, IDS_ACCORDION_DEFAULT_CONFIG_FACTORY, IdsAccordionDefaultConfig } from './accordion-defaults';
import { IdsAccordionItemComponent } from './accordion-item/accordion-item.component';
import { IdsAccordionAppearanceType } from './types/accordion-appearance.type';
import { IdsAccordionHeadingLevelType } from './types/accordion-heading-level.type';

import { CdkAccordion } from '@angular/cdk/accordion';
import { ChangeDetectionStrategy, Component, computed, contentChildren, inject, input, ViewEncapsulation } from '@angular/core';
Expand All @@ -10,7 +11,7 @@ import { coerceBooleanAttribute, coerceStringAttribute, ComponentBaseWithDefault
const defaultConfig = IDS_ACCORDION_DEFAULT_CONFIG_FACTORY();

@Component({
selector: 'ids-accordion',
selector: 'ids-accordion, ul[idsAccordion]',
imports: [IdsButtonComponent],
templateUrl: './accordion.component.html',
encapsulation: ViewEncapsulation.None,
Expand Down Expand Up @@ -41,6 +42,7 @@ export class IdsAccordionComponent extends ComponentBaseWithDefaults<IdsAccordio
public hasLeadingIcon = input(this._defaultConfig.hasLeadingIcon, { transform: coerceBooleanAttribute });
public hasTrailingIcon = input(this._defaultConfig.hasTrailingIcon, { transform: coerceBooleanAttribute });
public multi = input<boolean>(this._defaultConfig.multi);
public headingLevel = input<IdsAccordionHeadingLevelType>(this._defaultConfig.headingLevel);
public btnSize = input<IdsSizeType>(this._defaultConfig.btnSize);
public btnAppearance = input<IdsButtonAppearanceType>(this._defaultConfig.btnAppearance);
public btnVariant = input<IdsButtonVariantType>(this._defaultConfig.btnVariant);
Expand All @@ -51,8 +53,10 @@ export class IdsAccordionComponent extends ComponentBaseWithDefaults<IdsAccordio
protected _collapseBtnId = computed(() => `${this.id()}-collapse-btn`);

protected _hostClasses = computed(() => this._getHostClasses([
'ids-accordion',
this.size(),
this.appearance(),
this.headingLevel(),
this.disabled() ? 'disabled' : null,
]));

Expand Down Expand Up @@ -86,7 +90,7 @@ export class IdsAccordionComponent extends ComponentBaseWithDefaults<IdsAccordio

const items = this._items();
const target = event.target as HTMLButtonElement;
const accordionId = target.parentElement!.id;
const accordionId = target.parentElement?.parentElement?.id;
const index = items.findIndex((item) => item.id() === accordionId);

switch (event.key) {
Expand Down
1 change: 1 addition & 0 deletions projects/widgets/accordion/public-api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './accordion-item/accordion-item.component';
export * from './types/accordion-appearance.type';
export * from './types/accordion-heading-level.type';
export * from './accordion-animations';
export * from './accordion-defaults';
export * from './accordion.component';
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const IdsAccordionHeadingLevel = {
H1: 'h1',
H2: 'h2',
H3: 'h3',
H4: 'h4',
H5: 'h5',
H6: 'h6',
} as const;

export type IdsAccordionHeadingLevelType = (typeof IdsAccordionHeadingLevel)[keyof typeof IdsAccordionHeadingLevel];
Loading