# Sortable List

> A list the user reorders by drag or keyboard.

Source: https://ngwr.dev/reference/components/sortable-list  
Updated in v15

## Installation

Import the class, and `@use` the entry point in your global styles: without it the component renders unstyled.

```typescript
import { Component } from '@angular/core';
import { WrDragHandle, WrSortableItem, WrSortableList } from 'ngwr/sortable-list';

@Component({ imports: [WrDragHandle, WrSortableItem, WrSortableList] })
export class MyComponent {}
```

```scss
@use 'ngwr/sortable-list';
```

## Peer dependencies

Needs `@angular/cdk`.

```bash
pnpm add @angular/cdk
```

```bash
npm install @angular/cdk
```

```bash
yarn add @angular/cdk
```

```bash
bun add @angular/cdk
```

## Basic usage

Bind `[(items)]` and write one `<wr-sortable-item>` per item in your own loop. A row has no padding, border or background: style it yourself.

```angular-html
<wr-sortable-list [(items)]="rows" (reorder)="onReorder($event)">
  @for (row of rows(); track row.id; let i = $index) {
    <wr-sortable-item>
      <div class="row">
        <span class="row__index">#{{ i + 1 }}</span>
        <span>{{ row.label }}</span>
      </div>
    </wr-sortable-item>
  }
</wr-sortable-list>
```

```scss
.row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--wr-border-base);
  border-radius: var(--wr-border-radius-base);
  background: var(--wr-color-surface);
}
```

## With a drag handle

Put `wrDragHandle` on one element in the row, and only that element starts a drag.

```angular-html
<wr-sortable-list [(items)]="rows">
  @for (row of rows(); track row.id) {
    <wr-sortable-item>
      <div class="row">
        <span wrDragHandle aria-label="Reorder">≡</span>
        <span>{{ row.label }}</span>
      </div>
    </wr-sortable-item>
  }
</wr-sortable-list>
```

## Keyboard

Every row is a tab stop.

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `Space / Enter` | Pick the focused row up, or drop the one being held. | `key` | — |
| `Arrow keys` | Move the held row. Follows the reading direction when horizontal. | `key` | — |
| `Escape` | Put the held row back where it started. | `key` | — |

## API

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `items`required | Items to render. Two-way — emits the reordered array on drop. | `T[]` | — |
| `orientation` | Layout direction. Drives CDK's `cdkDropListOrientation`. | `'vertical' \| 'horizontal'` | `'vertical'` |
| `disabled` | Disable all dragging. | `boolean` | `false` |
| `lockAxis` | Locked axis — restrict drag movement to one axis even diagonally. | `'x' \| 'y' \| undefined` | `undefined` |
| `dragStartDelay` | Delay (ms) before a drag begins after the pointer goes down. The touch delay is the fix for the classic CDK touch snag: without it, the `touch-action: none` CDK puts on each item blocks scrolling the list on a phone. With a small touch delay, a quick swipe scrolls and a brief hold starts the drag; mouse stays instant. Pass a single number to apply one delay to both pointers. | `number \| { touch: number; mouse: number }` | `{ touch: 150, mouse: 0 }` |
| `(reorder)` | Fired after a successful reorder with the new array + indices. | `WrSortableReorderEvent<T>` | — |

## Related

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `<wr-sortable-item>` | One row. Write one per item in your own loop. | `component` | `—` |
| `[wrDragHandle]` | Only this element starts a drag. | `directive` | `—` |

## CSS variables

Set these on the component's selector or a wrapper, not on `:root`: the defaults are declared on `ngwr/sortable-list`'s own element.

| Variable | Default | Declared on |
| --- | --- | --- |
| `--wr-sortable-list-gap` | `var(--wr-space-sm)` | `.wr-sortable-list` |
| `--wr-sortable-list-item-font-family` | `var(--wr-font-family-base)` | `.wr-sortable-list__item` |
| `--wr-sortable-list-placeholder-radius` | `var(--wr-border-radius-base)` | `.wr-sortable-list` |

## Dependencies

| Angular CDK | `drag-drop` |
| --- | --- |

## See also

- [List](https://ngwr.dev/reference/components/list) — A list of rows with leading, body and trailing slots.
- [Transfer](https://ngwr.dev/reference/components/transfer) — Move items between two lists; the right one is the value.
