Documentation Index
Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
Use this file to discover all available pages before exploring further.
Implementation
DndSort Props
DndSort.Card Props
DndSort.Zone Props
DndSortChangeEvent
Common Examples
Bucketing
DndSort is a great way to create a drag-and-drop interface for moving items between different buckets.Sorting a list
DndSort is also a great way to create a drag-and-drop interface for sorting a list of items.Bucket and sort
DndSort can also be used to create a drag-and-drop interface for moving items between different buckets and sorting them within those buckets.Note this example also demonstrates cards initially beginning outside of the buckets.Validation
DndSort provides ways to validate the drag-and-drop interaction. This is useful for preventing invalid interactions, such as moving an item to a bucket that does not accept it.Basic Validation
The simplest way to validate is to use the type prop on the DndSort.Card component in conjunction with acceptedTypes prop on the DndSort.Zone component.<DndSort.Zone acceptedTypes={["fruit"]}>
<DndSort.Card type="fruit">🍎 Apple</DndSort.Card>
</DndSort.Zone>
Advanced Validation
A more advanced way to validate is to use the validator prop on the DndSort.Zone component. This prop takes a function which receives the item id. The function should return a boolean indicating whether the drop is valid. Here are some examples of how to use the validator prop:// Limit the zone to only accept items with ids in an allowed list
const validator = (id) => validIds.includes(id);
<DndSort.Zone validator={validator}></DndSort.Zone>;
// Limit the based on a property of the item
const validator = (id) => people[id].isFriendly;
<DndSort.Zone validator={validator}></DndSort.Zone>;
// Limit the number of items in a zone to 5
const validator = () => zoneItems.length <= 5;
<DndSort.Zone validator={validator}></DndSort.Zone>;
Customization
DndSort provides a number of ways to customize the drag-and-drop interaction. This includes customizing the appearance of the items and zones.Advanced zone rendering
The advancedRenderer prop of DndSort.Zone is an alternative to children, allowing you to customize the appearance of the drop zone based upon its internal state.This allows you to show different content when a drag is happening, when an item is over the drop zone, or if the dragged item is valid/invalid for the drop zone.Custom card preview rendering
The previewRenderer prop of DndSort.Card offers a means to customize the appearance of the card when it is being dragged. This is useful for showing a different appearance for the card, such as a simpler version of a complex card.Interactive Children
By default, the DndSort.Card places a button around the entire card. This is optimal for accessibility. But if you want to place interactive elements inside your card, it harms accessibility. To resolve this issue, set dragOnlyWithHandle on the DndSort.Card if your card has interactive elements.Anti-Patterns
Nesting
DndSort does not support nesting. i.e. you may not use a zone as an item.This is an intentional design decision to guarantee these components meet our accessibility and usability standards.If you have a use case that requires nesting, please reach out to us. We would love to hear about your use case and help you find a solution.Best Practices
dragOnlyWithHandle
<DndSort.Card dragOnlyWithHandle>
<Button />
</DndSort.Card>
Use the dragOnlyWithHandle prop if your card contains interactive elements.<DndSort.Card>
<Button />
</DndSort.Card>
Don’t use interactive elements in cards without dragOnlyWithHandle.import { DndSort } from "@servicetitan/anvil2";
function ExampleComponent() {
return (
<DndSort onDrop={(event) => console.log(event)}>
{/* DndSort.Zone and DndSort.Card components */}
</DndSort>
); }
DndSort Props
DndSort is the root component that must wrap DndSort sub-components. It provides the context and internal logic for the drag-and-drop interaction.Various children elements including DndSort.Zone and DndSort.Card.
onDrop
(DndSortChangeEvent) => void
Callback function fired when an item is dropped.
import { DndSort } from "@servicetitan/anvil2";
function ExampleComponent() {
return (
<DndSort.Card
id="card-1"
label="Card 1"
dragOnlyWithHandle={false}
>
Card content
</DndSort.Card>
);
}
DndSort.Card Props
DndSort.Card is a component that represents a card that can be dragged and dropped. It uses Card internally and most of the props are forwarded to the Card.The unique identifier for the card.
The label for the card, used for accessibility.
If true, the card can only be dragged when the drag handle is used. If false,
the card can be dragged by any part of it.
onDrop
(DndSortChangeEvent) => void
Callback function to be called when the card is dropped. Same as onDrop on
the DndSort component.
previewRenderer
({ valid }) => React.ReactNode
Advanced. A function that returns a React node to be used as the preview
renderer.
The type of the card, used for validation (optional).
import { DndSort } from "@servicetitan/anvil2";
function ExampleComponent() {
return (
<DndSort.Zone
id="zone-1"
label="Zone 1"
sortable={false}
orientation="vertical"
>
{/* Zone content */}
</DndSort.Zone>
); }
DndSort.Zone Props
DndSort.Zone is a component that represents a drop zone where items can be dropped. It may either be sortable or non-sortable. Only the basic styling is applied to the zone (i.e. border and background during a drag-and-drop interaction). Props are forwarded to the underlying div element, so you can provide styles, className, and other props to customize the appearance of the zone.The unique identifier for the zone.
The label for the zone, used for accessibility.
An array of accepted types for this zone. If not provided, all types are
accepted. Compares against the type prop of the card.
advancedRenderer
({ isDragging, isOver, isValid }) => React.ReactNode
Advanced. A function to render the drop zone using internal state parameters.
The contents of the zone.
defaultDropPosition
"start" | "end"
default:"end"
The default position where items will be dropped if dropped directly onto the zone.
The gap between items in the zone. See Flex for more info. Important for sortable zones to maintain
enough space for the sort line.
orientation
"horizontal" | "vertical"
default:"vertical"
The orientation of the items in the zone.
If true, the zone is sortable. If false, the zone is not sortable.
sortedIds
(string | number)[]
default:"[]"
Required if sortable. An array of sorted IDs for the items in the zone, must
match render order.
A function to validate the drop action. Given an item’s id, this function
must return true for valid drops, false for invalid drops.
DndSortChangeEvent
The ID of the draggable item that was dropped.
The ID of the previous drop zone where the item was located before being
dropped. This can be null if the item is coming from outside of any zone.
previousZoneSort
"(string" | "number)[]" | "null"
An array representing the sort order of items in the previous drop zone before
the drop. This can be used to update the order of items in the previous zone.
This value is null if the previous drop zone (if any) was not sortable.
Indicates whether the drop was valid based on the accepted types and custom
validation.
The ID of the drop zone where the item was dropped. This can be null if the
item was not dropped in a zone.
zoneSort
"(string" | "number)[]" | "null"
An array representing the sort order of items in the drop zone after the drop.
This can be used to update the order of items in the zone. This value is
null if the target drop zone (if any) is not sortable.