Reorder
Create drag-to-reorder effects with a simple set of components.
The Reorder
components can be used to create drag-to-reorder lists, like reorderable tabs or todo items.
import { Reorder } from "framer-motion"import { useState } from "react"
function List() { const [items, setItems] = useState([0, 1, 2, 3]) return ( <Reorder.Group axis="y" values={items} onReorder={setItems}> {items.map((item) => ( <Reorder.Item key={item} value={item}> {item} </Reorder.Item> ))} </Reorder.Group> )}
#Usage
Every reorderable list is wrapped in the Reorder.Group
component.
import { Reorder } from "framer-motion"
function List() { return ( <Reorder.Group> </Reorder.Group> )}
By default, this is rendered as a <ul>
, but this can be changed with the as
prop.
<Reorder.Group as="ol">
Reorder.Group
must be passed the array of values in your reorderable list via the values
prop.
Additionally, a onReorder
event will fire with the latest calculated order. For items to reorder, this must update the values
state.
import { Reorder } from "framer-motion"
function List() { const [items, setItems] = useState([0, 1, 2, 3])
return ( <Reorder.Group values={items} onReorder={setItems}> </Reorder.Group> )}
To render each reorderable item, use Reorder.Item
, passing it the value it represents via the value
prop.
import { Reorder } from "framer-motion"
function List() { const [items, setItems] = useState([0, 1, 2, 3])
return ( <Reorder.Group values={items} onReorder={setItems}> {items.map(item => ( <Reorder.Item key={item} value={item}> {item} </Reorder.Item> ))} </Reorder.Group> )}
Now, when items are dragged, onReorder
will fire with a new order.
#Layout animations
Reorder.Item
components are already configured to perform layout animations, so if new items are added or removed to the reorderable list, surrounding items will animate to their new position automatically.
#Exit animations
AnimatePresence
can be used as normal to animate items as they enter/leave the React tree.
<AnimatePresence> {items.map(item => ( <Reorder.Item initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} key={item} /> ))</AnimatePresence>
#Drag triggers
By default, all of a Reorder.Item
will be draggable. useDragControls
can be used to define a different component to act as a drag trigger
import { Reorder, useDragControls } from "framer-motion"
function Item({ value }) { const controls = useDragControls() return ( <Reorder.Item value={value} dragListener={false} dragControls={controls} > <div className="reorder-handle" onPointerDown={(e) => controls.start(e)} /> </Reorder.Item> )}
#Scrollable lists
If Reorder.Item
components are within a scrollable container, that container needs a layoutScroll
prop so Framer Motion can correctly measure its scroll offset.
In this example, the scrollable container is the Reorder.Group
:
<Reorder.Group axis="y" onReorder={setItems} layoutScroll style={{ overflowY: "scroll" }}> {items.map((item) => ( <Item key={item} item={item} /> ))}</Reorder.Group>
If the scrollable container is a normal HTML component it'll need to be converted to a motion
component with layoutScroll
.
#Reorder.Group props
#as: string
The underlying component for Reorder.Group
to render.
Currently, this only accepts the name of a HTML element, but in the future will accept any HTML-rendering React component.
Defaults to "ul"
#axis: "x" | "y"
Required
The direction of reorder detection.
By default, all Reorder.Item
components will be draggable only on this axis. To allow dragging on both axes, pass the drag
prop to child Reorder.Item
components.
#values: any[]
Required
The values array used as the source for the rendered Reorder.Item
components.
#onReorder(newOrder): void
Required
A callback that will fire when items are detected to have reordered. The provided newOrder
should be passed to a values
state update function.
#Reorder.Item props
Reorder.Item
components accept all motion component props in addition to the following:
#as: string
The underlying component for Reorder.Item
to render.
Currently, this only accepts the name of a HTML element, but in the future will accept any HTML-rendering React component.
Defaults to "li"
#value: any
Required
When onReorder
is called, this is the value that will be passed through in the newly ordered array.