# List

Lists organize related content into rows that are easy to scan.

## Usage 

Lists are designed to be flexible
and can be used with different styles depending on the context.
They can be **read-only** or **support interactions**.

- Use a **ghost** list when the items should blend into the surrounding
  content and stay lightweight.
- Use a **divider** list when the items need separation but the list
  should still feel quiet and compact.
- Use a **filled** list when the list should stand out as a distinct section or card.
- Use an **outline** list when you want a clear container around the items
  without the stronger weight of a filled surface.

![List](images/list.png)

### When to use

- When content needs to be shown as a repeatable, scannable row.

### Best practices

- For complex data, use a [table](../lists-tables-trees/overview.md) instead of a list.
- Keep structure consistent across all list items in the same list.

## Design 

### Anatomy

**List items** are flexible building blocks that can support differentcontent types.
The following example shows the most common layout.

![List item anatomy](images/list-item-anatomy.png)

> 1\. Indicator, 2. Timestamp, 3. Heading, 4. Description, 5. Primary action, 6. Metadata, 7. Quick actions

The anatomy above is a default example, but every slot can be swapped for a different control depending on the interaction the list needs to support. For example:

- Add checkboxes to support multi-select and bulk actions,
  or radio buttons for single-select.
- Add a drag handle to support manual reordering.
- Replace the heading text with an input to support inline editing.

![List item content](images/list-item-content.png)

### Indicator

The indicator can support icons, [circle status](../status-notifications/circle-status.md),
or an [avatar](../status-notifications/avatar.md), depending on the content needs.

![List item indicator](images/list-item-indicator.png)

### Actions

The list item supports two distinct action slots:

The primary action is most directly tied to the item's purpose.
Works best as a single action, though it can hold more.

![List item action](images/list-item-primary-action.png)

Quick actions are usually for operations performed on the item itself, such as pinning, archiving, sharing, or deleting. Works best when several need to be exposed at once.

![List item quick actions](images/list-item-quick-actions.png)

Use a menu when there are more than three or four.

### Metadata

It is typically displayed as text-based informational attributes.
Icons may be added when they improve recognition.
[Badges](../status-notifications/badges.md) can be used for explicit states or applied labels that should stand out visually.

The metadata does not include an intrinsic overflow behavior.
How overflow is handled should change according to the layout constraints and information priorities.

![List item metadata](images/list-item-metadata.png)

## Code 

### List styles

Use `.list` for a ghost list, `.list.list-divider` to separate items with dividers,
`.list.list-filled` to place items on a filled surface, or `.list.list-outline` to
place each item in an outlined container.

```html
<!-- Ghost -->
<ul class="list">
  <li class="list-item">...</li>
</ul>

<!-- Divider -->
<ul class="list list-divider">
  <li class="list-item">...</li>
</ul>

<!-- Filled -->
<ul class="list list-filled">
  <li class="list-item">...</li>
</ul>

<!-- Outline -->
<ul class="list list-outline">
  <li class="list-item">...</li>
</ul>
```

#### Example

Component:

```typescript
/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
import { Component, inject } from '@angular/core';
import {
  elementAhuPlant,
  elementLightOn,
  elementFireSensor,
  elementElevator,
  elementOptionsVertical
} from '@siemens/element-icons';
import { addIcons, SiIconComponent } from '@siemens/element-ng/icon';
import { LOG_EVENT } from '@siemens/live-preview';

@Component({
  selector: 'app-sample',
  imports: [SiIconComponent],
  templateUrl: './list-variants.html',
  host: { class: 'p-5' }
})
export class SampleComponent {
  logEvent = inject(LOG_EVENT);

  icons = addIcons({
    elementAhuPlant,
    elementLightOn,
    elementFireSensor,
    elementElevator,
    elementOptionsVertical
  });

  readonly items = [
    {
      icon: this.icons.elementAhuPlant,
      title: 'HVAC Zone Controller Lobby'
    },
    {
      icon: this.icons.elementLightOn,
      title: 'Lighting Controller Parking Garage'
    },
    {
      icon: this.icons.elementFireSensor,
      title: 'Fire Alarm Panel East Wing'
    },
    {
      icon: this.icons.elementElevator,
      title: 'Elevator Motor Room Sensor'
    }
  ];
}
```

Template:

```html
<div class="d-flex flex-column gap-13">
  <div class="d-flex flex-wrap gap-13">
    <div class="flex-grow-1">
      <h4 class="mb-4">Ghost</h4>
      <ul class="list">
        @for (item of items; track item.title) {
          <li class="list-item">
            <si-icon class="list-item-indicator icon" [icon]="item.icon" />
            <h5 class="list-item-title">{{ item.title }}</h5>
            <div class="list-item-primary-action">
              <button type="button" class="btn btn-icon btn-tertiary-ghost" aria-label="Options">
                <si-icon [icon]="icons.elementOptionsVertical" />
              </button>
            </div>
          </li>
        }
      </ul>
    </div>

    <div class="flex-grow-1">
      <h4 class="mb-4">With dividers</h4>
      <ul class="list list-divider">
        @for (item of items; track item.title) {
          <li class="list-item">
            <si-icon class="list-item-indicator icon" [icon]="item.icon" />
            <h5 class="list-item-title">{{ item.title }}</h5>
            <div class="list-item-primary-action">
              <button type="button" class="btn btn-icon btn-tertiary-ghost" aria-label="Options">
                <si-icon [icon]="icons.elementOptionsVertical" />
              </button>
            </div>
          </li>
        }
      </ul>
    </div>
  </div>
  <div class="d-flex flex-wrap gap-13">
    <div class="flex-grow-1">
      <h4 class="mb-4">Filled</h4>
      <ul class="list list-filled">
        @for (item of items; track item.title) {
          <li class="position-relative">
            <button type="button" class="list-item list-item-action" (click)="logEvent(item.title)">
              <si-icon class="list-item-indicator icon" [icon]="item.icon" />
              <h5 class="list-item-title">{{ item.title }}</h5>
              <span class="list-item-primary-action btn btn-icon" aria-hidden="true"></span>
            </button>
            <div class="position-absolute top-50 end-0 translate-middle-y me-6">
              <button type="button" class="btn btn-icon btn-tertiary-ghost" aria-label="Options">
                <si-icon [icon]="icons.elementOptionsVertical" />
              </button>
            </div>
          </li>
        }
      </ul>
    </div>

    <div class="flex-grow-1">
      <h4 class="mb-4">Outline</h4>
      <ul class="list list-outline">
        @for (item of items; track item.title) {
          <li class="position-relative">
            <button type="button" class="list-item list-item-action" (click)="logEvent(item.title)">
              <si-icon class="list-item-indicator icon" [icon]="item.icon" />
              <h5 class="list-item-title">{{ item.title }}</h5>
              <span class="list-item-primary-action btn btn-icon" aria-hidden="true"></span>
            </button>
            <div class="position-absolute top-50 end-0 translate-middle-y me-6">
              <button type="button" class="btn btn-icon btn-tertiary-ghost" aria-label="Options">
                <si-icon [icon]="icons.elementOptionsVertical" />
              </button>
            </div>
          </li>
        }
      </ul>
    </div>
  </div>
</div>
```


### List item configurations

#### Example

Component:

```typescript
/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
import { CdkMenuTrigger } from '@angular/cdk/menu';
import { Component, inject } from '@angular/core';
import {
  elementArchive,
  elementCheckboxChecked,
  elementDelete,
  elementDocument,
  elementAhuPlant,
  elementSpecialObject
} from '@siemens/element-icons';
import { SiAvatarComponent } from '@siemens/element-ng/avatar';
import { SiCircleStatusComponent } from '@siemens/element-ng/circle-status';
import { addIcons, SiIconComponent, SiStatusIconComponent } from '@siemens/element-ng/icon';
import { type MenuItem, SiMenuFactoryComponent } from '@siemens/element-ng/menu';
import { LOG_EVENT } from '@siemens/live-preview';

@Component({
  selector: 'app-sample',
  imports: [
    SiIconComponent,
    SiMenuFactoryComponent,
    SiAvatarComponent,
    SiCircleStatusComponent,
    SiStatusIconComponent,
    CdkMenuTrigger
  ],
  templateUrl: './list-item.html',
  host: { class: 'p-5' }
})
export class SampleComponent {
  logEvent = inject(LOG_EVENT);

  icons = addIcons({
    elementArchive,
    elementCheckboxChecked,
    elementDelete,
    elementDocument,
    elementAhuPlant,
    elementSpecialObject
  });

  items: MenuItem[] = [
    { type: 'action', label: 'View details', action: () => this.logEvent('View details') },
    {
      type: 'action',
      label: 'Assign technician',
      action: () => this.logEvent('Assign technician')
    },
    { type: 'action', label: 'Export log', action: () => this.logEvent('Export log') }
  ];
}
```

Template:

```html
<ul>
  <li class="list-item">
    <si-icon class="list-item-indicator icon" [icon]="icons.elementAhuPlant" />
    <h5 class="list-item-title">HVAC Zone Controller Lobby</h5>
    <div class="list-item-primary-action">
      <button
        type="button"
        class="btn btn-icon btn-tertiary-ghost element-options-vertical"
        aria-label="Options"
        [cdkMenuTriggerFor]="contextMenu"
      ></button>
    </div>
  </li>

  <li class="list-item">
    <input
      type="checkbox"
      class="form-check-input list-item-check"
      aria-label="Select VAV box actuator Room 312"
    />
    <si-icon class="list-item-indicator icon" [icon]="icons.elementSpecialObject" />
    <h5 class="list-item-title">VAV box actuator Room 312</h5>
  </li>

  <li class="list-item">
    <si-icon class="list-item-indicator icon" [icon]="icons.elementSpecialObject" />
    <h5 class="list-item-title">AHU-03 Supply Fan Fault</h5>
    <div class="list-item-primary-action">
      <button
        type="button"
        class="btn btn-icon btn-tertiary-ghost element-options-vertical"
        aria-label="Options"
        [cdkMenuTriggerFor]="contextMenu"
      ></button>
    </div>
    <p class="list-item-description"
      >Supply fan VFD reporting overcurrent fault. Airflow dropped below setpoint on floors 4–6.</p
    >
    <div class="list-item-metadata">
      <span>Building A</span>
      <div class="list-item-metadata-divider"></div>
      <div class="d-inline-flex align-items-center gap-1">
        <si-icon class="icon-sm" [icon]="icons.elementDocument" />
        <span>3</span>
      </div>
      <div class="list-item-metadata-divider"></div>
      <span>Critical</span>
    </div>
  </li>

  <li class="list-item">
    <si-avatar
      class="list-item-indicator"
      size="small"
      icon="element-user"
      altText="Assigned technician"
      color="5"
    />
    <h5 class="list-item-title">Scheduled Maintenance</h5>
    <div class="list-item-primary-action">
      <button
        type="button"
        class="btn btn-icon btn-tertiary-ghost element-options-vertical"
        aria-label="Options"
        [cdkMenuTriggerFor]="contextMenu"
      ></button>
    </div>
    <p class="list-item-description"
      >Annual condenser coil cleaning and refrigerant level check. Assigned to Mike Torres,
      Facilities.</p
    >
    <div class="list-item-quick-actions">
      <div class="btn-group" role="group" aria-label="Maintenance actions">
        <button
          type="button"
          class="btn btn-icon btn-tertiary-ghost"
          aria-label="Approve"
          (click)="logEvent('Approve maintenance task')"
        >
          <si-icon class="icon" [icon]="icons.elementCheckboxChecked" />
        </button>
        <button
          type="button"
          class="btn btn-icon btn-tertiary-ghost"
          aria-label="Archive"
          (click)="logEvent('Archive maintenance task')"
        >
          <si-icon class="icon" [icon]="icons.elementArchive" />
        </button>
        <button
          type="button"
          class="btn btn-icon btn-tertiary-ghost"
          aria-label="Delete"
          (click)="logEvent('Delete maintenance task')"
        >
          <si-icon class="icon" [icon]="icons.elementDelete" />
        </button>
      </div>
    </div>
  </li>

  <li class="list-item">
    <time class="list-item-timestamp" datetime="16:30">Yesterday at 16:30</time>
    <si-status-icon class="list-item-indicator si-h3" status="critical" />
    <h5 class="list-item-title">Fire Damper Fault Zone B3</h5>
    <p class="list-item-description"
      >Smoke damper in return duct failed to close during test sequence. Manual inspection required
      before next occupancy cycle.</p
    >
  </li>

  <li class="list-item">
    <time class="list-item-timestamp" datetime="09:12">Today at 09:12</time>
    <si-circle-status status="critical" icon="element-plant" class="list-item-indicator icon" />
    <h5 class="list-item-title">Boiler #1 Pressure Drop Alert</h5>
    <div class="list-item-primary-action">
      <button
        type="button"
        class="btn btn-icon btn-tertiary-ghost element-options-vertical"
        aria-label="Options"
        [cdkMenuTriggerFor]="contextMenu"
      ></button>
    </div>
    <p class="list-item-description"
      >System pressure fell below 12 PSI threshold. Possible leak in the north wing hydronic loop.
      Technician dispatched.</p
    >
    <div class="list-item-metadata">
      <span>Campus HQ</span>
      <div class="list-item-metadata-divider"></div>
      <div class="d-inline-flex align-items-center gap-1">
        <si-icon class="icon-sm" [icon]="icons.elementDocument" />
        <span>7</span>
      </div>
      <div class="list-item-metadata-divider"></div>
      <span>Urgent</span>
    </div>
    <div class="list-item-quick-actions">
      <div class="btn-group" role="group" aria-label="Fault actions">
        <button
          type="button"
          class="btn btn-icon btn-tertiary-ghost"
          aria-label="Approve"
          (click)="logEvent('Approve fault resolution')"
        >
          <si-icon class="icon" [icon]="icons.elementCheckboxChecked" />
        </button>
        <button
          type="button"
          class="btn btn-icon btn-tertiary-ghost"
          aria-label="Archive"
          (click)="logEvent('Archive fault resolution')"
        >
          <si-icon class="icon" [icon]="icons.elementArchive" />
        </button>
        <button
          type="button"
          class="btn btn-icon btn-tertiary-ghost"
          aria-label="Delete"
          (click)="logEvent('Delete fault resolution')"
        >
          <si-icon class="icon" [icon]="icons.elementDelete" />
        </button>
      </div>
    </div>
  </li>
</ul>

<ng-template #contextMenu>
  <si-menu-factory [items]="items" />
</ng-template>
```


### Action list items

If the entire item is clickable, wrap the content inside a `<button>` or `<a>` element and apply the `.list-item-action` helper class for hover and focus styling.
Use `<a>` when the action navigates to another page or resource, and `<button>` when it triggers an in-page action.

The item should be placed inside a `<ul>` + `<li>` structure to preserve list semantics.

Use `aria-labelledby` and `aria-describedby` on the interactive element to provide a concise accessible name (the title) and description, instead of exposing all inner text as the accessible name.

#### Example

Component:

```typescript
/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
import { Component, inject } from '@angular/core';
import { elementUser, elementLock } from '@siemens/element-icons';
import { addIcons, SiIconComponent } from '@siemens/element-ng/icon';
import { LOG_EVENT } from '@siemens/live-preview';

@Component({
  selector: 'app-sample',
  imports: [SiIconComponent],
  templateUrl: './list-item-action.html',
  host: { class: 'p-5' }
})
export class SampleComponent {
  logEvent = inject(LOG_EVENT);

  icons = addIcons({ elementUser, elementLock });
}
```

Template:

```html
<ul>
  <li>
    <button
      type="button"
      class="list-item list-item-action"
      (click)="logEvent('Open project Alpha')"
    >
      <time class="list-item-timestamp" datetime="PT2H">Edited 2 hours ago</time>
      <h5 class="list-item-title">Project Alpha</h5>
      <p class="list-item-description">Automation config for assembly line 3</p>
    </button>
  </li>
  <li>
    <button
      type="button"
      class="list-item list-item-action"
      (click)="logEvent('Open project Beta')"
    >
      <time class="list-item-timestamp" datetime="P3D">Edited 3 days ago</time>
      <h5 class="list-item-title">Project Beta</h5>
      <p class="list-item-description">Drive parameter tuning for conveyor motors</p>
      <div class="list-item-metadata">
        <div class="d-inline-flex align-items-center gap-1">
          <si-icon class="icon-sm" [icon]="icons.elementUser" />
          <span>3 contributors</span>
        </div>
      </div>
    </button>
  </li>
  <li>
    <button
      type="button"
      class="list-item list-item-action"
      (click)="logEvent('Open project Gamma')"
    >
      <time class="list-item-timestamp" datetime="P1W">Edited last week</time>
      <h5 class="list-item-title">Project Gamma</h5>
      <p class="list-item-description">Safety interlock logic for press station</p>
      <div class="list-item-metadata">
        <span>Workspace B</span>
        <div class="list-item-metadata-divider"></div>
        <div class="d-inline-flex align-items-center gap-1">
          <si-icon class="icon-sm" [icon]="icons.elementLock" />
          <span>Private</span>
        </div>
        <div class="list-item-metadata-divider"></div>
        <span class="badge bg-warning">Review pending</span>
      </div>
    </button>
  </li>
</ul>
```


### Metadata

Use `.list-item-metadata` to display supplementary contextual information below the description, such as workspace names, contributor counts, document links, or status badges.
Items within the metadata row can be separated with `.list-item-metadata-divider`, which renders a small dot separator.

### Unread state

Use the `.unread` class on `.list-item-title` to indicate unread items with a bold title and a dot indicator.

#### Example

Component:

```typescript
/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
import { Component, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { SiFormItemComponent } from '@siemens/element-ng/form';

@Component({
  selector: 'app-sample',
  imports: [FormsModule, SiFormItemComponent],
  templateUrl: './list-item-unread.html',
  host: { class: 'p-5' }
})
export class SampleComponent {
  readonly unread = signal(true);
}
```

Template:

```html
<ul>
  <li class="list-item">
    <time class="list-item-timestamp" datetime="14:20">Today at 14:20</time>
    <h5 class="list-item-title" [class.unread]="unread()">Conveyor belt inspection completed</h5>
    <p class="list-item-description"
      >Routine inspection of conveyor belt CB-04 finished without issues. All parameters within
      tolerance.</p
    >
  </li>

  <li class="list-item">
    <time class="list-item-timestamp" datetime="11:45">Today at 11:45</time>
    <h5 class="list-item-title" [class.unread]="unread()">Sensor calibration report available</h5>
    <p class="list-item-description"
      >Calibration of temperature sensors on production line 2 has been completed and documented.</p
    >
    <div class="list-item-metadata">
      <span>Production line 2</span>
      <div class="list-item-metadata-divider"></div>
      <a href="#">View report</a>
    </div>
  </li>

  <li class="list-item">
    <time class="list-item-timestamp" datetime="16:05">Yesterday at 16:05</time>
    <h5 class="list-item-title" [class.unread]="unread()">Motor drive fault detected</h5>
    <p class="list-item-description"
      >Drive unit DU-07 on packaging station reported overcurrent fault. Manual reset required.</p
    >
  </li>
</ul>

<div class="card mt-6 mx-4 e2e-ignore">
  <div class="card-header">Interactive Demo Controls</div>
  <div class="card-body">
    <si-form-item class="col" label="Unread (indicator and emphasis)">
      <input type="checkbox" class="form-check-input" [(ngModel)]="unread" />
    </si-form-item>
  </div>
</div>
```


### Migrating from the list group

The Bootstrap based list group (`.list-group`) is deprecated in favor of the list.
The list group is only a bordered container and has no notion of the list anatomy,
so migrating means restructuring the markup, it is not a plain class rename.

| Deprecated                          | Replacement                                                                                                |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `.list-group`                       | `.list`, optionally with `.list-divider`, `.list-filled` or `.list-outline`                                |
| `.list-group-item`                  | `.list-item`, wrap the content in the slot classes such as `.list-item-title` and `.list-item-description` |
| `.list-group-item-action`           | `.list-item.list-item-action` on a `<button>` or `<a>`                                                     |
| `.list-group-flush`                 | `.list.list-divider` to preserve dividers; otherwise `.list`, which has no outer border                    |
| `.list-group-md`, `.list-group-lg`  | No replacement, the height of a list item follows its content                                              |
| `.list-group-horizontal*`           | No replacement, use flex or grid utilities                                                                 |
| `.list-group-numbered`              | No replacement, use an ordered list with a custom counter because `.list-item` removes list markers        |
| `.list-group-item-*` color variants | No replacement, use the background and text utilities, or an [indicator](#indicator)                       |
| `.list-header`                      | No replacement, use a heading element                                                                      |

Start with the structural migration below, then choose the list style according to the application context.

```html
<!-- Before -->
<ul class="list-group">
  <li class="list-group-item">Item</li>
</ul>

<!-- After -->
<ul class="list">
  <li class="list-item">
    <span class="list-item-title">Item</span>
  </li>
</ul>
```

#### Choosing the right style

The new list does not have a default background.
When replacing `.list-group` with `.list`, change the style according to the context.

- If `.list-group` is placed in a side panel, card, or container with a `base-1` background,
  use `.list` for a ghost style or `.list.list-divider` for a divider style.
- If `.list-group` is placed directly on the application's bottom layer or on a `base-0`
  background, use `.list.list-outline` or `.list.list-filled`.
- To retain the exact same style as before, apply `.card` to `.list.list-divider`.

![List group migration](images/list-group-migration.png)
