SortableList
a list reordered by its grips, with the mouse or the keyboard.
usage
example
fix the fuel leak
knife up quohog's table
sell mink meat to the schools
dodge the cavefish
code
import { SortableList } from 'charcell/react';
export function SortableListExample() {
return (
<SortableList
items={[
'fix the fuel leak',
"knife up quohog's table",
'sell mink meat to the schools',
'dodge the cavefish',
]}
>
{({ item }) => <span>{item}</span>}
</SortableList>
);
}▴
▾
<script setup lang="ts">
import { SortableList } from 'charcell/vue';
</script>
<template>
<SortableList
:items="[
'fix the fuel leak',
'knife up quohog\'s table',
'sell mink meat to the schools',
'dodge the cavefish',
]"
>
<template #default="{ item }">
<span>{{ item }}</span>
</template>
</SortableList>
</template>▴
▾
<script lang="ts">
import { SortableList } from 'charcell/svelte';
</script>
<SortableList
items={[
'fix the fuel leak',
"knife up quohog's table",
'sell mink meat to the schools',
'dodge the cavefish',
]}
>
{#snippet children({ item })}
<span>{item}</span>
{/snippet}
</SortableList>▴
▾
<!-- component: SortableListDriver (behavior not included) -->
<div class="CharcellSortableList" role="list">
<!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>fix the fuel leak</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>knife up quohog's table</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>sell mink meat to the schools</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>dodge the cavefish</span>
</div>
</div>
<!-- /component -->
</div>
<!-- /component -->▴
▾
import { SortableList } from 'charcell/react';
export function SortableListExample() {
return (
<SortableList
items={[
'fix the fuel leak',
"knife up quohog's table",
'sell mink meat to the schools',
'dodge the cavefish',
]}
spacious
>
{({ item }) => <span>{item}</span>}
</SortableList>
);
}▴
▾
<script setup lang="ts">
import { SortableList } from 'charcell/vue';
</script>
<template>
<SortableList
:items="[
'fix the fuel leak',
'knife up quohog\'s table',
'sell mink meat to the schools',
'dodge the cavefish',
]"
spacious
>
<template #default="{ item }">
<span>{{ item }}</span>
</template>
</SortableList>
</template>▴
▾
<script lang="ts">
import { SortableList } from 'charcell/svelte';
</script>
<SortableList
items={[
'fix the fuel leak',
"knife up quohog's table",
'sell mink meat to the schools',
'dodge the cavefish',
]}
spacious
>
{#snippet children({ item })}
<span>{item}</span>
{/snippet}
</SortableList>▴
▾
<!-- component: SortableListDriver (behavior not included) -->
<div class="CharcellSortableList CharcellSortableList--spacious" role="list">
<!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>fix the fuel leak</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>knife up quohog's table</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>sell mink meat to the schools</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>dodge the cavefish</span>
</div>
</div>
<!-- /component -->
</div>
<!-- /component -->▴
▾
import { SortableList } from 'charcell/react';
export function SortableListExample() {
return (
<SortableList
items={[
'fix the fuel leak',
"knife up quohog's table",
'sell mink meat to the schools',
'dodge the cavefish',
]}
snap="row"
>
{({ item }) => <span>{item}</span>}
</SortableList>
);
}▴
▾
<script setup lang="ts">
import { SortableList } from 'charcell/vue';
</script>
<template>
<SortableList
:items="[
'fix the fuel leak',
'knife up quohog\'s table',
'sell mink meat to the schools',
'dodge the cavefish',
]"
snap="row"
>
<template #default="{ item }">
<span>{{ item }}</span>
</template>
</SortableList>
</template>▴
▾
<script lang="ts">
import { SortableList } from 'charcell/svelte';
</script>
<SortableList
items={[
'fix the fuel leak',
"knife up quohog's table",
'sell mink meat to the schools',
'dodge the cavefish',
]}
snap="row"
>
{#snippet children({ item })}
<span>{item}</span>
{/snippet}
</SortableList>▴
▾
<!-- component: SortableListDriver (behavior not included) -->
<div class="CharcellSortableList" role="list">
<!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>fix the fuel leak</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>knife up quohog's table</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>sell mink meat to the schools</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>dodge the cavefish</span>
</div>
</div>
<!-- /component -->
</div>
<!-- /component -->▴
▾
import { SortableList } from 'charcell/react';
export function SortableListExample() {
return (
<SortableList
items={[
'fix the fuel leak',
"knife up quohog's table",
'sell mink meat to the schools',
'dodge the cavefish',
]}
snap="none"
>
{({ item }) => <span>{item}</span>}
</SortableList>
);
}▴
▾
<script setup lang="ts">
import { SortableList } from 'charcell/vue';
</script>
<template>
<SortableList
:items="[
'fix the fuel leak',
'knife up quohog\'s table',
'sell mink meat to the schools',
'dodge the cavefish',
]"
snap="none"
>
<template #default="{ item }">
<span>{{ item }}</span>
</template>
</SortableList>
</template>▴
▾
<script lang="ts">
import { SortableList } from 'charcell/svelte';
</script>
<SortableList
items={[
'fix the fuel leak',
"knife up quohog's table",
'sell mink meat to the schools',
'dodge the cavefish',
]}
snap="none"
>
{#snippet children({ item })}
<span>{item}</span>
{/snippet}
</SortableList>▴
▾
<!-- component: SortableListDriver (behavior not included) -->
<div class="CharcellSortableList" role="list">
<!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>fix the fuel leak</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>knife up quohog's table</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>sell mink meat to the schools</span>
</div>
</div>
<!-- /component --><!-- component: SortableItemDriver (behavior not included) -->
<div class="CharcellSortableList__row" role="listitem">
<button class="CharcellSortableList__grip" type="button"></button>
<div class="CharcellSortableList__content">
<span>dodge the cavefish</span>
</div>
</div>
<!-- /component -->
</div>
<!-- /component -->▴
▾
as text
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
place hereplace here
drop here⠿ fix the fuel leak ⠿ knife up quohog's table drop here ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
⠿ fix the fuel leak ⠿ knife up quohog's table ⠿ sell mink meat to the schools ⠿ dodge the cavefish
props
SortableList
- itemsItem[]
- The items, in order.
- onItemsChange(items: Item[]) => void
- Called with the list's items after every move that touches it.
- idstring
- A list in a group: its name in the group's moves.
- getKey(item: Item, index: number) => string
- A stable key per item. In a group it travels with the item between lists; without it the list keeps its own keys beside the items.
- getLabel(item: Item, index: number) => string
- The item's name, for its grip ("reorder ben") and what the list says about it; a string or number item names itself, any other its position.
- customGripboolean
- The item places its own grip: spread
gripPropson a button anywhere in it (their class gives it the grip's look and states), and the row draws no grip column. - spaciousboolean
- Each item takes two rows, its grip a cell wide and both rows tall, so grips sit far enough apart to meet the 24px target size (wcag 2.5.8), which one-row items fall short of.
- translationsSortableListTranslations
- A list on its own: every string it says (English defaults).
- snap'character' | 'row' | 'none'= 'character'
- A list on its own: how a drag moves,
'character'(the default) in whole cells,'row'in whole rows down only,'none'freely.
SortableRow
- engagedboolean
- The item is picked up or dragged: the grip fills.
- draggingboolean
- The row being dragged: it paints the ground, lifted over the rows it passes.
- customGripboolean
- The grip is the consumer's, spread with the list's grip props wherever the item puts it; the row draws no grip column.
- gripPropsRecord<string, unknown>
- Spread onto the grip: the drag handle's ref, name, description and handlers.
it also takes any other attribute of its <div>.
SortablePlace
- labelstring
- The text: the button's name, or with
hintthe drag's hint. - targetboolean
- With
hint, where the dragged item lands: the hint inverted. - hintboolean
it also takes any other attribute of its <span>.
slots
in react, the default slot is children and each named slot a prop of its name, a function where the slot hands values; in vue, a slot; in svelte, a snippet.
SortableList
- default{ item: Item; index: number; dragging: boolean; picked: boolean; gripProps: SortableGripProps }
- An item's row, given the
item, itsindex, whether it'sdraggingorpicked, and thegripPropsan item that places its own grip (customGrip) spreads on it. - empty{ state: 'idle' | 'picked' | 'dragging'; placeProps: SortablePlaceButtonProps }
- What an empty list shows in place of its place and drop rows, given its
state. SpreadplacePropsonto an element to place the picked item there.
SortableRow
- default
▴
▾