# @auroratide/reorder-list

> Web component for a rearrangeable list of items

Latest version **0.6.1** (published 2026-09-22) · ISC license · 0 weekly downloads

## Install

```sh
npm install @auroratide/reorder-list
pnpm add @auroratide/reorder-list
yarn add @auroratide/reorder-list
bun add @auroratide/reorder-list
```

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score; high quality score.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.6.1 |
| Published | 2026-09-22 |
| First published | 2022-11-25 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 46.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 4 |
| Author | Timothy Foster |
| Maintainers | auroratide |
| Keywords | reorder, list, rearrange, element, web component |

## Links

- npm: https://www.npmjs.com/package/@auroratide/reorder-list
- Repository: https://github.com/Auroratide/web-components.git#main
- Homepage: https://github.com/Auroratide/web-components/tree/main#readme
- Issues: https://github.com/Auroratide/web-components/issues
- npm.io page: https://npm.io/package/@auroratide/reorder-list

## Recent versions

- 0.6.1 (latest) — 2026-09-22
- 0.6.0 — 2026-08-10
- 0.5.1 — 2026-03-24
- 0.5.0 — 2026-03-24
- 0.4.0 — 2024-08-10
- 0.3.0 — 2024-06-07
- 0.2.0 — 2024-06-05
- 0.1.3 — 2024-06-04
- 0.1.2 — 2024-06-04
- 0.1.1 — 2024-02-10
- 0.1.0 — 2022-11-25

## README

# The reorder-list Elements

<p hidden><strong><a href="https://components.auroratide.com/reorder-list">View this page with live demos!</a></strong></p>

The `reorder-list`, `reorder-item`, and `reorder-handle` elements represent an ordered list of items that can be reordered. They are built with accessibility in mind and implement list/listitem semantics with a button handle.

<!--DEMO
<wc-demo>
	<p>Press and hold to drag items. Or, tab into the list and use <kbd>Alt</kbd> + <kbd>Up/Down</kbd>.</p>
	<reorder-list>
		<reorder-item><span>Apple</span></reorder-item>
		<reorder-item><span>Orange</span></reorder-item>
		<reorder-item><span>Banana</span></reorder-item>
		<reorder-item><span>Lime</span></reorder-item>
		<reorder-item><span>Blueberry</span></reorder-item>
		<reorder-item><span>Plum</span></reorder-item>
	</reorder-list>
</wc-demo>
/DEMO-->

```html
<reorder-list>
	<reorder-item>Apple</reorder-item>
	<reorder-item>Orange</reorder-item>
	<reorder-item>Banana</reorder-item>
	<reorder-item>Lime</reorder-item>
	<reorder-item>Blueberry</reorder-item>
	<reorder-item>Plum</reorder-item>
</reorder-list>
```

## Installation

You can import through CDN:

```html
<script type="module" src="https://unpkg.com/@auroratide/reorder-list/lib/define.js"></script>
```

Or, you may install through [NPM](https://www.npmjs.com/package/@auroratide/reorder-list) and include it as part of your build process:

```
$ npm i @auroratide/reorder-list
```

```javascript
import '@auroratide/reorder-list/lib/define.js'
```

## Usage

`reorder-list`, `reorder-item`, and `reorder-handle` are **markup elements** that you can use in your HTML document. To use them together, it is best to follow these guidelines:

* `reorder-item` elements **must** be _direct_ descendents of a `reorder-list` element. This is similar to how `li` must directly descend `ol`.
* `reorder-handle` elements are optional, but if included **must** be a descendent of a `reorder-item` element.

## Reorder Handles

By default, when there is no explicit handle provided, the entire reorder item provides a default draggable handle that covers the item. If you only want a part of the item to be draggable, then you can use `reorder-handle`, like so:

<!--DEMO
<wc-demo>
	<p>Press and hold "[Drag]" to drag items. You cannot drag via the fruit names (allowing it to scroll on mobile and such).</p>
	<reorder-list>
		<reorder-item>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Apple</span>
		</reorder-item>
		<reorder-item>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Orange</span>
		</reorder-item>
		<reorder-item>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Banana</span>
		</reorder-item>
		<reorder-item>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Lime</span>
		</reorder-item>
		<reorder-item>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Blueberry</span>
		</reorder-item>
		<reorder-item>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Plum</span>
		</reorder-item>
	</reorder-list>
</wc-demo>
/DEMO-->

```html
<reorder-list>
	<reorder-item>
		<reorder-handle><span>[Drag]</span></reorder-handle>
		<span>Apple</span>
	</reorder-item>
	<reorder-item>
		<reorder-handle><span>[Drag]</span></reorder-handle>
		<span>Orange</span>
	</reorder-item>
	<reorder-item>
		<reorder-handle><span>[Drag]</span></reorder-handle>
		<span>Banana</span>
	</reorder-item>
	<reorder-item>
		<reorder-handle><span>[Drag]</span></reorder-handle>
		<span>Lime</span>
	</reorder-item>
	<reorder-item>
		<reorder-handle><span>[Drag]</span></reorder-handle>
		<span>Blueberry</span>
	</reorder-item>
	<reorder-item>
		<reorder-handle><span>[Drag]</span></reorder-handle>
		<span>Plum</span>
	</reorder-item>
</reorder-list>
```

Handles have the following accessibility affordances:

- Handles participate in the tab order of the document.
- Handles are labeled as "Reorder {item name}", to instruct screen readers what the handle is for.
- The default handle becomes visible on focus, indicating which item is focused.

## Orientation

By default, `orientation` is "vertical", meaning you drag items up and down. Setting `orientation` to "horizontal" will allow you to reorder items left and right instead.

<!--DEMO
<wc-demo id="horizontal-demo">
	<reorder-list orientation="horizontal">
		<reorder-item>Apple</reorder-item>
		<reorder-item>Orange</reorder-item>
		<reorder-item>Banana</reorder-item>
		<reorder-item>Kiwi</reorder-item>
	</reorder-list>
</wc-demo>
<style>
	#horizontal-demo reorder-list {
		display: flex;
		flex-direction: row;
		list-style: none;
		gap: 0.5em;
		padding: 0;
	}
	#horizontal-demo reorder-item {
		border: 0.0625em solid #2573C1;
		border-radius: 0.125em;
		padding: 0.25em 1em;
	}
</style>
/DEMO-->

```html
<reorder-list orientation="horizontal">
	<reorder-item>Apple</reorder-item>
	<reorder-item>Orange</reorder-item>
	<reorder-item>Banana</reorder-item>
	<reorder-item>Kiwi</reorder-item>
</reorder-list>
```

**Note**: Bidirectional reordering is not possible with this component. `reorder-list` is for _lists_, whereas bidirectional reordering would be for a grid of some kind; they are different semantics.

## Ignoring Reorder Trigger

You may have an element within a `reorder-item` that you do not want triggering a reorder. For instance, an `input` element should not start dragging, and it should instead focus on the `input`.

Use the `data-ignore-reorder` attribute on any element within `reorder-item` in order to make that element not start dragging.

<!--DEMO
<wc-demo id="ignore-reorder">
	<reorder-list>
		<reorder-item>Drag: <input data-ignore-reorder type="text" value="Apple" /></reorder-item>
		<reorder-item>Drag: <input data-ignore-reorder type="text" value="Orange" /></reorder-item>
		<reorder-item>Drag: <input data-ignore-reorder type="text" value="Banana" /></reorder-item>
		<reorder-item>Drag: <input data-ignore-reorder type="text" value="Kiwi" /></reorder-item>
	</reorder-list>
</wc-demo>
/DEMO-->

```html
<reorder-list>
	<reorder-item>Drag: <input data-ignore-reorder type="text" value="Apple" /></reorder-item>
	<reorder-item>Drag: <input data-ignore-reorder type="text" value="Orange" /></reorder-item>
	<reorder-item>Drag: <input data-ignore-reorder type="text" value="Banana" /></reorder-item>
	<reorder-item>Drag: <input data-ignore-reorder type="text" value="Kiwi" /></reorder-item>
</reorder-list>
```

## CSS Customization

Since these are native custom elements, they can be styled the same way as regular HTML elements.

Of note:

* `reorder-item[data-dragging]` will style the currently dragged item.

Here's an example of a customized list meant to look like reorderable cards.

<!--DEMO
<wc-demo id="fancy">
	<reorder-list>
		<reorder-item>
			<strong>Cobb Salad</strong>
			<ul>
				<li>chicken</li>
				<li>egg</li>
				<li>tomato</li>
			</ul>
		</reorder-item>
		<reorder-item>
			<strong>Fried Rice</strong>
			<ul>
				<li>rice</li>
				<li>shrimp</li>
				<li>egg</li>
			</ul>
		</reorder-item>
		<reorder-item>
			<strong>Chimichanga</strong>
			<ul>
				<li>chicken</li>
				<li>beans</li>
			</ul>
		</reorder-item>
		<reorder-item>
			<strong>Banana Pancake</strong>
			<ul>
				<li>breakfast</li>
				<li>banana</li>
			</ul>
		</reorder-item>
		<reorder-item>
			<strong>Philly Cheese Sandwich</strong>
			<ul>
				<li>steak</li>
				<li>cheese</li>
				<li>bread</li>
			</ul>
		</reorder-item>
	</reorder-list>
</wc-demo>
<style>
	#fancy reorder-list {
		list-style: none;
		background: var(--t-bg-a);
		border-radius: 0.5em;
		width: min(400px, 100%);
		padding: 0.75em;
		display: flex;
		flex-direction: column;
		gap: 0.5em;
	}
	#fancy reorder-item {
		background: var(--t-bg-b);
		border-radius: 0.25em;
		padding: 0.5em;
		box-shadow: 0 0.1em 0.15em #0002;
	}
	#fancy ul {
		list-style: none;
		display: flex;
		flex-direction: row;
		flex-wrap: wrap;
		gap: 0.5em;
		padding: 0;
		margin: 0;
		font-size: 90%;
		color: var(--t-primary-b);
	}
</style>
/DEMO-->

```css
reorder-list {
	list-style: none;
	background: oklch(22% 0.021 255);
	border-radius: 0.5em;
	width: min(400px, 100%);
	padding: 0.5em;
	display: flex;
	flex-direction: column;
	gap: 0.5em;
}

reorder-item {
	background: oklch(27% 0.02 255);
	border-radius: 0.25em;
	padding: 0.5em;
	box-shadow: 0 0.1em 0.15em #0002;
}

reorder-item ul {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.5em;
	padding: 0;
	margin: 0;
	font-size: 90%;
	color: oklch(64% 0.142 250);
}
```

## Events

The `reorder-list` element dispatches the following events:

| Name | When Triggered |
| ------------- | ------------- |
| `change` | Whenever an item in the list is reordered |
| `commit` | At the end of an item being dragged |

Both events contain a reference to the item that was reordered, its previous position in the list, and its new position.

```js
list.addEventListener('change', e => {
	console.log(e.detail.item)
	console.log(e.detail.oldIndex)
	console.log(e.detail.newIndex)
})
```

The difference between `change` and `commit` is the `change` event happens any time an element changes order, including in the middle of a drag. The `commit` event only triggers at the end of a drag, so the old index in that event's details will represent the position of that item prior to the drag being started.

## Nesting Lists

Nothing stops you from putting lists inside of lists.

<!--DEMO
<wc-demo id="nested-demo">
	<reorder-list orientation="horizontal">
		<reorder-item>
			<strong>Fruit</strong>
			<reorder-list>
				<reorder-item>Apple</reorder-item>
				<reorder-item>Orange</reorder-item>
				<reorder-item>Banana</reorder-item>
				<reorder-item>Kiwi</reorder-item>
			</reorder-list>
		</reorder-item>
		<reorder-item>
			<strong>Vegetable</strong>
			<reorder-list>
				<reorder-item>Tomato</reorder-item>
				<reorder-item>Carrot</reorder-item>
				<reorder-item>Squash</reorder-item>
				<reorder-item>Lettuce</reorder-item>
			</reorder-list>
		</reorder-item>
		<reorder-item>
			<strong>Grain</strong>
			<reorder-list>
				<reorder-item>Wheat</reorder-item>
				<reorder-item>Barley</reorder-item>
				<reorder-item>Rye</reorder-item>
				<reorder-item>Rice</reorder-item>
			</reorder-list>
		</reorder-item>
	</reorder-list>
</wc-demo>
<style>
	#nested-demo > reorder-list {
		flex-direction: row;
		list-style: none;
		gap: 0.5em;
		padding: 0;
	} #nested-demo > reorder-list strong {
		display: block;
		text-align: center;
	} #nested-demo > reorder-list > reorder-item {
		background: var(--t-bg-a);
		padding: 0.75em;
		border-radius: 0.25em;
		flex: 1;
	}
	#nested-demo reorder-list reorder-list {
		list-style: none;
		border-radius: 0.5em;
		width: min(400px, 100%);
		padding: 0.5em;
		display: flex;
		flex-direction: column;
		gap: 0.5em;
		margin: 0;
	} #nested-demo reorder-list reorder-list reorder-item {
		background: var(--t-bg-b);
		border-radius: 0.25em;
		padding: 0.5em;
		box-shadow: 0 0.1em 0.15em #0002;
	}
</style>
/DEMO-->

```html
<reorder-list orientation="horizontal">
	<reorder-item>
		<strong>Fruit</strong>
		<reorder-list>
			<reorder-item>Apple</reorder-item>
			<reorder-item>Orange</reorder-item>
			<reorder-item>Banana</reorder-item>
			<reorder-item>Kiwi</reorder-item>
		</reorder-list>
	</reorder-item>
	<reorder-item>
		<strong>Vegetable</strong>
		<reorder-list>
			<reorder-item>Tomato</reorder-item>
			<reorder-item>Carrot</reorder-item>
			<reorder-item>Squash</reorder-item>
			<reorder-item>Lettuce</reorder-item>
		</reorder-list>
	</reorder-item>
	<reorder-item>
		<strong>Grain</strong>
		<reorder-list>
			<reorder-item>Wheat</reorder-item>
			<reorder-item>Barley</reorder-item>
			<reorder-item>Rye</reorder-item>
			<reorder-item>Rice</reorder-item>
		</reorder-list>
	</reorder-item>
</reorder-list>
```

## Filtering

You may have a list with some of the items hidden as a result of filtering. The reorder-list will still allow you to reorder the sublist!

Some important notes:

* The `change` and `commit` events continue to report the changes in the indexes of the overall list, not just the visible list.
* The end result of the reorder will be as if the invisible items were visible, for the sake of predictability.
* This works with arrow keys too for accessibility.

<!--DEMO
<wc-demo>
	<p>Orange and Lime are hidden. Dragging and arrowing both move straight past them.</p>
	<reorder-list>
		<reorder-item>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Apple</span>
		</reorder-item>
		<reorder-item hidden>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Orange</span>
		</reorder-item>
		<reorder-item>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Banana</span>
		</reorder-item>
		<reorder-item hidden>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Lime</span>
		</reorder-item>
		<reorder-item>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Blueberry</span>
		</reorder-item>
		<reorder-item>
			<reorder-handle><span>[Drag]</span></reorder-handle>
			<span>Plum</span>
		</reorder-item>
	</reorder-list>
</wc-demo>
/DEMO-->

```html
<reorder-list>
	<reorder-item>
		<reorder-handle><span>[Drag]</span></reorder-handle>
		<span>Apple</span>
	</reorder-item>
	<reorder-item hidden>
		<reorder-handle><span>[Drag]</span></reorder-handle>
		<span>Orange</span>
	</reorder-item>
	<reorder-item>
		<reorder-handle><span>[Drag]</span></reorder-handle>
		<span>Banana</span>
	</reorder-item>
</reorder-list>
```

If you need the distinction yourself, `list.items()` gives every item and `list.visibleItems()` only the ones on screen.

## Accessibility

This custom element is build with accessibility in mind! It implements list/listitem semantics and uses handles to reorder the items.

* Each handle is a focusable item that participates in the tab order.
* <kbd>Up</kbd> and <kbd>Down</kbd> can be used to navigate the list, focusing on an element that will be reordered.
* <kbd>Alt</kbd> + <kbd>Up</kbd>/<kbd>Down</kbd> moves the currently selected list item up or down in the order.
* If orientation is horizontal, then <kbd>Left</kbd> and <kbd>Right</kbd> are used instead.
* A live region is used to announce the last change of order.

### Reorder Announcer

List reordering is announced to assistive technology using a live region. This region is located at the end of the body document, with the `data-reorder-list-announcer` attribute. All `reorder-list` elements share the same announcement region.

---
_Source: https://npm.io/package/@auroratide/reorder-list · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
