# Description list

- Entry point: `@koobiq/components/dl`
- Page: https://koobiq.io/en/components/dl/overview

## Overview

Description list displays term-description pairs in adaptive, horizontal, or vertical layouts.

**Example: Description list** (`dl-overview`)

```ts dl-overview-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqDd, KbqDl, KbqDt } from '@koobiq/components/dl';

@Component({
    selector: 'dl-overview-example',
    imports: [KbqDl, KbqDt, KbqDd],
    template: `
        <kbq-dl>
            <kbq-dt>Incident type</kbq-dt>
            <kbq-dd>Malware infection</kbq-dd>

            <kbq-dt>Identifier</kbq-dt>
            <kbq-dd>INC-2026-125-78253</kbq-dd>

            <kbq-dt>Status</kbq-dt>
            <kbq-dd>New</kbq-dd>

            <kbq-dt>Assignee</kbq-dt>
            <kbq-dd>John Smith</kbq-dd>

            <kbq-dt>Description</kbq-dt>
            <kbq-dd>
                An employee opened an attachment in a phishing email, and the file ran malicious code on the
                workstation.
            </kbq-dd>
        </kbq-dl>
    `,
    styles: `
        :host {
            display: block;
            padding: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DlOverviewExample {}
```

### Wide layout

The `wide` attribute splits the width equally between terms and descriptions.

**Example: Description list wide** (`dl-wide`)

```ts dl-wide-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqDd, KbqDl, KbqDt } from '@koobiq/components/dl';

@Component({
    selector: 'dl-wide-example',
    imports: [KbqDl, KbqDt, KbqDd],
    template: `
        <kbq-dl wide>
            <kbq-dt>Incident type</kbq-dt>
            <kbq-dd>Malware infection</kbq-dd>

            <kbq-dt>Identifier</kbq-dt>
            <kbq-dd>INC-2026-125-78253</kbq-dd>

            <kbq-dt>Status</kbq-dt>
            <kbq-dd>New</kbq-dd>

            <kbq-dt>Assignee</kbq-dt>
            <kbq-dd>John Smith</kbq-dd>

            <kbq-dt>Description</kbq-dt>
            <kbq-dd>
                An employee opened an attachment in a phishing email, and the file ran malicious code on the
                workstation.
            </kbq-dd>
        </kbq-dl>
    `,
    styles: `
        :host {
            display: block;
            padding: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DlWideExample {}
```

### Vertical layout

The `vertical` attribute switches the list to the vertical layout, with terms above descriptions.

**Example: Description list vertical** (`dl-vertical`)

```ts dl-vertical-example.ts
import { ChangeDetectionStrategy, Component, model } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { KbqDd, KbqDl, KbqDt } from '@koobiq/components/dl';
import { KbqToggleModule } from '@koobiq/components/toggle';

@Component({
    selector: 'dl-vertical-example',
    imports: [KbqDl, KbqDt, KbqDd, KbqToggleModule, FormsModule],
    template: `
        <div class="layout-row layout-align-center-center">
            <kbq-toggle [(ngModel)]="vertical">Vertical</kbq-toggle>
        </div>

        <kbq-dl [vertical]="vertical()">
            <kbq-dt>Incident type</kbq-dt>
            <kbq-dd>Malware infection</kbq-dd>

            <kbq-dt>Identifier</kbq-dt>
            <kbq-dd>INC-2026-125-78253</kbq-dd>

            <kbq-dt>Status</kbq-dt>
            <kbq-dd>New</kbq-dd>

            <kbq-dt>Assignee</kbq-dt>
            <kbq-dd>John Smith</kbq-dd>

            <kbq-dt>Description</kbq-dt>
            <kbq-dd>
                An employee opened an attachment in a phishing email, and the file ran malicious code on the
                workstation.
            </kbq-dd>
        </kbq-dl>
    `,
    styles: `
        :host {
            display: flex;
            flex-direction: column;
            gap: var(--kbq-size-l);
            padding: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DlVerticalExample {
    protected readonly vertical = model(true);
}
```

### Adaptive layout

Without the `vertical` attribute, the list becomes vertical when its width is at or below `verticalBreakpoint`. Resize the container to see it.

**Example: Description list vertical breakpoint** (`dl-vertical-breakpoint`)

```ts dl-vertical-breakpoint-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqDd, KbqDl, KbqDt } from '@koobiq/components/dl';

@Component({
    selector: 'dl-vertical-breakpoint-example',
    imports: [KbqDl, KbqDt, KbqDd],
    template: `
        <div class="example-container">
            <kbq-dl [verticalBreakpoint]="500">
                <kbq-dt>Incident type</kbq-dt>
                <kbq-dd>Malware infection</kbq-dd>

                <kbq-dt>Identifier</kbq-dt>
                <kbq-dd>INC-2026-125-78253</kbq-dd>

                <kbq-dt>Status</kbq-dt>
                <kbq-dd>New</kbq-dd>

                <kbq-dt>Assignee</kbq-dt>
                <kbq-dd>John Smith</kbq-dd>

                <kbq-dt>Description</kbq-dt>
                <kbq-dd>
                    An employee opened an attachment in a phishing email, and the file ran malicious code on the
                    workstation.
                </kbq-dd>
            </kbq-dl>
        </div>
    `,
    styles: `
        :host {
            display: block;
            padding: var(--kbq-size-l);
        }

        .example-container {
            box-sizing: border-box;
            width: 640px;
            min-width: 240px;
            max-width: 100%;
            padding: var(--kbq-size-l);
            border-radius: var(--kbq-size-border-radius);
            background-color: var(--kbq-background-bg-secondary);
            overflow: auto;
            resize: horizontal;
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DlVerticalBreakpointExample {}
```

### Alignment

The `verticalAlign` attribute aligns terms and descriptions within a row, and `horizontalAlign` within a column.

**Example: Description list alignment** (`dl-alignment`)

```ts dl-alignment-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqBadge } from '@koobiq/components/badge';
import { KbqDd, KbqDl, KbqDt } from '@koobiq/components/dl';

@Component({
    selector: 'dl-alignment-example',
    imports: [KbqDl, KbqDt, KbqDd, KbqBadge],
    template: `
        <kbq-dl verticalAlign="center">
            <kbq-dt>Severity</kbq-dt>
            <kbq-dd>
                <kbq-badge badgeColor="fade-error">Critical</kbq-badge>
            </kbq-dd>

            <kbq-dt>Status</kbq-dt>
            <kbq-dd>
                <kbq-badge compact badgeColor="fade-theme">New</kbq-badge>
            </kbq-dd>

            <kbq-dt>Tags</kbq-dt>
            <kbq-dd>
                <div class="layout-row layout-wrap layout-gap-xxs">
                    <kbq-badge>Phishing</kbq-badge>
                    <kbq-badge>Malware</kbq-badge>
                    <kbq-badge>Workstation</kbq-badge>
                </div>
            </kbq-dd>

            <kbq-dt>Identifier</kbq-dt>
            <kbq-dd>INC-2026-125-78253</kbq-dd>
        </kbq-dl>
    `,
    styles: `
        :host {
            display: block;
            padding: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DlAlignmentExample {}
```

### Term width

The `dtWidth` attribute sets the width of the term column in pixels.

**Example: Description list term width** (`dl-dt-width`)

```ts dl-dt-width-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqDd, KbqDl, KbqDt } from '@koobiq/components/dl';

@Component({
    selector: 'dl-dt-width-example',
    imports: [KbqDl, KbqDt, KbqDd],
    template: `
        <kbq-dl [dtWidth]="120">
            <kbq-dt>Incident type</kbq-dt>
            <kbq-dd>Malware infection</kbq-dd>

            <kbq-dt>Identifier</kbq-dt>
            <kbq-dd>INC-2026-125-78253</kbq-dd>

            <kbq-dt>Status</kbq-dt>
            <kbq-dd>New</kbq-dd>

            <kbq-dt>Assignee</kbq-dt>
            <kbq-dd>John Smith</kbq-dd>

            <kbq-dt>Description</kbq-dt>
            <kbq-dd>
                An employee opened an attachment in a phishing email, and the file ran malicious code on the
                workstation.
            </kbq-dd>
        </kbq-dl>
    `,
    styles: `
        :host {
            display: block;
            padding: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DlDtWidthExample {}
```

### Resizable

The `resizable` attribute lets the user change the width of the term column by dragging the separator or with the arrow keys. A double click on the separator collapses the column to its minimum width, and a second one restores it.

**Example: Description list resizable** (`dl-resizable`)

```ts dl-resizable-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqDd, KbqDl, KbqDt } from '@koobiq/components/dl';

@Component({
    selector: 'dl-resizable-example',
    imports: [KbqDl, KbqDt, KbqDd],
    template: `
        <kbq-dl resizable>
            <kbq-dt>Incident type</kbq-dt>
            <kbq-dd>Malware infection</kbq-dd>

            <kbq-dt>Identifier</kbq-dt>
            <kbq-dd>INC-2026-125-78253</kbq-dd>

            <kbq-dt>Status</kbq-dt>
            <kbq-dd>New</kbq-dd>

            <kbq-dt>Assignee</kbq-dt>
            <kbq-dd>John Smith</kbq-dd>

            <kbq-dt>Description</kbq-dt>
            <kbq-dd>
                An employee opened an attachment in a phishing email, and the file ran malicious code on the
                workstation.
            </kbq-dd>
        </kbq-dl>
    `,
    styles: `
        :host {
            display: block;
            padding: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DlResizableExample {}
```

#### Minimum widths

The `dtMinWidth` and `ddMinWidth` attributes set the minimum widths of the term and description columns in pixels.

**Example: Description list minimum widths** (`dl-min-width`)

```ts dl-min-width-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqDd, KbqDl, KbqDt } from '@koobiq/components/dl';

@Component({
    selector: 'dl-min-width-example',
    imports: [KbqDl, KbqDt, KbqDd],
    template: `
        <kbq-dl resizable [dtMinWidth]="120" [ddMinWidth]="240">
            <kbq-dt>Incident type</kbq-dt>
            <kbq-dd>Malware infection</kbq-dd>

            <kbq-dt>Identifier</kbq-dt>
            <kbq-dd>INC-2026-125-78253</kbq-dd>

            <kbq-dt>Status</kbq-dt>
            <kbq-dd>New</kbq-dd>

            <kbq-dt>Assignee</kbq-dt>
            <kbq-dd>John Smith</kbq-dd>

            <kbq-dt>Description</kbq-dt>
            <kbq-dd>
                An employee opened an attachment in a phishing email, and the file ran malicious code on the
                workstation.
            </kbq-dd>
        </kbq-dl>
    `,
    styles: `
        :host {
            display: block;
            padding: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DlMinWidthExample {}
```

#### Shared width

The two-way `[(dtWidth)]` binding keeps the width the user sets, so that it can be saved or shared between lists.

**Example: Description list shared width** (`dl-width-sync`)

```ts dl-width-sync-example.ts
import { ChangeDetectionStrategy, Component, model } from '@angular/core';
import { KbqDivider } from '@koobiq/components/divider';
import { KbqDd, KbqDl, KbqDt } from '@koobiq/components/dl';

@Component({
    selector: 'dl-width-sync-example',
    imports: [KbqDl, KbqDt, KbqDd, KbqDivider],
    template: `
        <kbq-dl resizable [(dtWidth)]="dtWidth">
            <kbq-dt>Incident type</kbq-dt>
            <kbq-dd>Malware infection</kbq-dd>

            <kbq-dt>Identifier</kbq-dt>
            <kbq-dd>INC-2026-125-78253</kbq-dd>

            <kbq-dt>Assignee</kbq-dt>
            <kbq-dd>John Smith</kbq-dd>
        </kbq-dl>

        <kbq-divider />

        <kbq-dl resizable [(dtWidth)]="dtWidth">
            <kbq-dt>Incident type</kbq-dt>
            <kbq-dd>Brute-force attack</kbq-dd>

            <kbq-dt>Identifier</kbq-dt>
            <kbq-dd>INC-2026-13-44357</kbq-dd>

            <kbq-dt>Assignee</kbq-dt>
            <kbq-dd>Jane Doe</kbq-dd>
        </kbq-dl>
    `,
    styles: `
        :host {
            display: flex;
            flex-direction: column;
            gap: var(--kbq-size-l);
            padding: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DlWidthSyncExample {
    protected readonly dtWidth = model(160);
}
```

### Long text

Long strings without spaces, such as identifiers, hashes, paths and URLs, wrap within their column.

**Example: Description list with long text** (`dl-long-text`)

```ts dl-long-text-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqDd, KbqDl, KbqDt } from '@koobiq/components/dl';
import { KbqLink } from '@koobiq/components/link';

@Component({
    selector: 'dl-long-text-example',
    imports: [KbqDl, KbqDt, KbqDd, KbqLink],
    template: `
        <kbq-dl resizable [dtMinWidth]="100" [ddMinWidth]="200">
            <kbq-dt>security.incident.description</kbq-dt>
            <kbq-dd>
                An employee opened the
                <span class="kbq-text-normal-strong">security_update.exe</span>
                attachment in a phishing email. The file executed malicious code on the workstation.
            </kbq-dd>

            <kbq-dt>process.parent.executable.file_name</kbq-dt>
            <kbq-dd>security_update.exe</kbq-dd>

            <kbq-dt>process.parent.executable.hash.sha256</kbq-dt>
            <kbq-dd>
                <span class="kbq-mono-normal">5cfeaa7084b508d0ea762d8cfed396b6029eed6005d381b16e725755ec801014</span>
            </kbq-dd>

            <kbq-dt>process.parent.executable.full_path</kbq-dt>
            <kbq-dd>
                C:\\Users\\Administrator\\AppData\\Local\\Temp\\SecurityUpdate\\packages\\windows\\x64\\security_update.exe
            </kbq-dd>

            <kbq-dt>threat.indicator.reference</kbq-dt>
            <kbq-dd>
                <a kbqLink pseudo>
                    https://www.virustotal.com/gui/file/5cfeaa7084b508d0ea762d8cfed396b6029eed6005d381b16e725755ec801014/detection
                </a>
            </kbq-dd>
        </kbq-dl>
    `,
    styles: `
        :host {
            display: block;
            max-width: 600px;
            padding: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DlLongTextExample {}
```

### Global options

The `kbqDlOptionsProvider` function sets the default options of every list in the application or in a specific injector.

```ts
import { ApplicationConfig } from '@angular/core';
import { kbqDlOptionsProvider } from '@koobiq/components/dl';

export const appConfig: ApplicationConfig = {
    providers: [kbqDlOptionsProvider({ wide: true, resizable: true })]
};
```

## API

### Components

#### KbqDd (component)

Description of the term before it.

```ts
@Component({ selector: 'kbq-dd' })
class KbqDd {}
```

#### KbqDl (component)

Description list: `kbq-dt` terms paired with `kbq-dd` descriptions in an adaptive, horizontal or vertical layout.

```ts
@Component({ selector: 'kbq-dl' })
class KbqDl {
    readonly verticalBreakpoint = input<number>(
        this.options.verticalBreakpoint
    );
    readonly wide = input<boolean>(this.options.wide);
    readonly resizable = input<boolean>(this.options.resizable);
    readonly dtWidth = model<number | null>(this.options.dtWidth);
    readonly dtMinWidth = input<number | undefined>(
        this.options.dtMinWidth
    );
    readonly ddMinWidth = input<number | undefined>(
        this.options.ddMinWidth
    );
    readonly resizerAriaLabel = input<string | undefined>();
    readonly verticalAlign = input<KbqDlAlign>(
        this.options.verticalAlign
    );
    readonly horizontalAlign = input<KbqDlAlign>(
        this.options.horizontalAlign
    );
    readonly vertical = input<boolean | null>(this.options.vertical);
}
```

- `[verticalBreakpoint]`: `number` — Host width in pixels at or below which the list auto-switches to the vertical layout.
  Defaults to the app-wide `KBQ_DL_OPTIONS`.
- `[wide]`: `boolean` — Whether the list uses the wide two-column layout. Defaults to the app-wide `KBQ_DL_OPTIONS`.
- `[resizable]`: `boolean` — Whether the `kbq-dt` area can be resized by dragging the separator.
  Defaults to the app-wide `KBQ_DL_OPTIONS`.
- `[(dtWidth)]`: `number | null` — Width of the `kbq-dt` area in pixels; `null` restores the default column ratio.
  Defaults to the app-wide `KBQ_DL_OPTIONS`.

  Writable: a drag or a double-click on the separator sets it, and `dtWidthChange` reports that back.
  `model()` would have been the shorter form, but it takes no `transform`, so an uncoerced attribute
  reached the layout arithmetic as a string and skipped the clamp against `dtMinWidth`.
- `[dtMinWidth]`: `number | undefined` — Minimum width of the `kbq-dt` area in pixels; defaults to the app-wide `KBQ_DL_OPTIONS`, then to the
  rendered term width.
- `[ddMinWidth]`: `number | undefined` — Minimum width retained for the `kbq-dd` area in pixels; defaults to the app-wide `KBQ_DL_OPTIONS`, then
  to the rendered term width.
- `[resizerAriaLabel]`: `string | undefined` — Accessible name of the column resize separator; falls back to the localized default when omitted.
- `[verticalAlign]`: `KbqDlAlign` — Vertical alignment of `kbq-dt` and `kbq-dd` items. Defaults to the app-wide `KBQ_DL_OPTIONS`.
- `[horizontalAlign]`: `KbqDlAlign` — Horizontal alignment of `kbq-dt` and `kbq-dd` items. Defaults to the app-wide `KBQ_DL_OPTIONS`.
- `[vertical]`: `boolean | null` — Forces the vertical layout; `null` lets the list decide based on `verticalBreakpoint`.
  Defaults to the app-wide `KBQ_DL_OPTIONS`.
- `[localeOverrides]`: `KbqPartialLocaleData | undefined` — Localized strings for this element and its subtree, keyed by locale section. Every key is optional at
  every depth.

#### KbqDt (component)

Term of a description list.

```ts
@Component({ selector: 'kbq-dt' })
class KbqDt {}
```

### Functions

#### kbqDlOptionsProvider (function)

Overrides the default description list options within the given injector scope. The options it leaves out keep the
values of the parent injector.

```ts
function kbqDlOptionsProvider(options: Partial<KbqDlOptions>): Provider;
```

### Types

#### KbqDlAlign (type)

Supported alignment values for description list items.

```ts
type KbqDlAlign = 'start' | 'center' | 'end';
```

#### KbqDlOptions (type)

Configuration for `KbqDl`. Each input of a list overrides its option.

```ts
type KbqDlOptions = {
    verticalBreakpoint: number;
    vertical: boolean | null;
    wide: boolean;
    resizable: boolean;
    dtWidth: number | null;
    dtMinWidth?: number;
    ddMinWidth?: number;
    verticalAlign: KbqDlAlign;
    horizontalAlign: KbqDlAlign;
};
```

- `verticalBreakpoint`: `number` — Host width in pixels at or below which a list switches to the vertical layout.
- `vertical`: `boolean | null` — Forces the vertical layout; `null` lets a list decide based on `verticalBreakpoint`.
- `wide`: `boolean` — Whether a list uses the wide two-column layout.
- `resizable`: `boolean` — Whether the `kbq-dt` area can be resized by dragging the separator.
- `dtWidth`: `number | null` — Width of the `kbq-dt` area in pixels; `null` keeps the default column ratio.
- `dtMinWidth?`: `number` — Minimum width of the `kbq-dt` area in pixels; defaults to the rendered term width.
- `ddMinWidth?`: `number` — Minimum width retained for the `kbq-dd` area in pixels; defaults to the rendered term width.
- `verticalAlign`: `KbqDlAlign` — Vertical alignment of `kbq-dt` and `kbq-dd` items.
- `horizontalAlign`: `KbqDlAlign` — Horizontal alignment of `kbq-dt` and `kbq-dd` items.

### Constants

#### KBQ_DL_OPTIONS (const)

Injection token holding the current `KbqDlOptions`.

```ts
const KBQ_DL_OPTIONS: InjectionToken<KbqDlOptions>;
```
