---
title: Sortable
category: General
---

```jsx live
const items = generateFakeData(
  (faker) => ({
    id: faker.random.uuid(),
    name: faker.name.firstName() + ' ' + faker.name.lastName(),
    sticky: faker.random.boolean(),
  }),
  10
)

class App extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      sticky: items.filter((item) => item.sticky),
      notSticky: [],
    }

    this.onDragEnd = ({ source, destination }) => {
      // dropped on same board
      if (source.droppableId === destination.droppableId) {
        this.setState((state) => ({
          [destination.droppableId]: Sortable.reorder({
            list: [...state[destination.droppableId]],
            startIndex: source.index,
            endIndex: destination.index,
          }),
        }))
      } else {
        this.setState((state) => ({
          [source.droppableId]: Sortable.remove({
            list: state[source.droppableId],
            index: source.index,
          }),
          [destination.droppableId]: Sortable.insert({
            fromList: state[source.droppableId],
            fromIndex: source.index,
            toList: state[destination.droppableId],
            toIndex: destination.index,
          }),
        }))
      }
    }

    this.handleRemove = ({ id, index }) => {
      console.log('remove index ' + index + ' from ' + id)
    }
  }

  render() {
    return (
      <Box minWidth={60} padding={1}>
        <Card>
          <Toolbar
            title="Item Notes"
            helpContent="Toolbars need help too"
            actions={<Button title="Add" />}
            padding={1}
          />
          <Divider />
          <Sortable.SortableManager onDragEnd={this.onDragEnd}>
            <Sortable.SortableList
              id="sticky"
              title="Frequently Used"
              onItemRemoveRequest={this.handleRemove}
            >
              {this.state.sticky.map((item) => (
                <Sortable.SortableItem key={item.id} id={item.id}>
                  <Input.Inline defaultValue={item.name} grow={1} />
                </Sortable.SortableItem>
              ))}
            </Sortable.SortableList>
            <Divider />
            <Sortable.SortableList
              id="notSticky"
              title="Occasionally Used"
              onItemRemoveRequest={this.handleRemove}
              emptyText="Drag a category here to hide it when it's blank."
            >
              {this.state.notSticky.map((item) => (
                <Sortable.SortableItem key={item.id} id={item.id}>
                  <Input.Inline defaultValue={item.name} grow={1} />
                </Sortable.SortableItem>
              ))}
            </Sortable.SortableList>
          </Sortable.SortableManager>
        </Card>
      </Box>
    )
  }
}

render(App)
```
