Token Order
A forms and inputs component for ranking preferences with native controls.
Customise
Code
"use client";
import { useState } from "react";
import { InputTokenOrder } from "@/components/ui/input-token-order";
function WorkshopTopics() {
const [topicsOrder, setTopicsOrder] = useState(["systems", "accessibility", "motion"]);
const topics = [
{ id: "systems", label: "Design systems" },
{ id: "accessibility", label: "Accessibility" },
{ id: "motion", label: "Motion" },
];
return (
<InputTokenOrder
<InputTokenOrder
items={topics}
value={topicsOrder}
onValueChange={setTopicsOrder}
label="Session topics, highest priority first"
name="session-topic"
/>Token Order is a free forms and inputs component for Next.js, React and Tailwind that lets people rank a fixed set of choices with named Up and Down buttons. Each proposed move remains controlled by the parent, so visible ranks and repeated form fields always represent the committed order.
The server-rendered ordered list and hidden fields remain complete without JavaScript; move controls appear after hydration. A finite Motion layout transition gives committed moves spatial feedback, while reduced motion, printing and offscreen content use the final order immediately.
Install
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/input-token-orderUsage
"use client";
import { useState } from "react";
import { InputTokenOrder } from "@/components/ui/input-token-order";
const topics = [
{ id: "systems", label: "Design systems" },
{ id: "accessibility", label: "Accessibility" },
{ id: "motion", label: "Motion" },
];
export function WorkshopTopics() {
const [order, setOrder] = useState(topics.map((topic) => topic.id));
return (
<InputTokenOrder
items={topics}
value={order}
onValueChange={setOrder}
label="Session topics, highest priority first"
name="session-topic"
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| items | ReadonlyArray<{ id: string; label: string }> | required | Two to twelve stable choices with unique, nonblank IDs and nonblank labels. |
| value | ReadonlyArray<string> | required | The controlled committed permutation containing every item ID exactly once. |
| onValueChange | (next: string[]) => void | required | Receives one proposed permutation per accepted move; the parent decides whether to commit it. |
| label | string | required | Visible group label and accessible name. Must contain nonblank text. |
| name | string | required | Repeated hidden input name; committed IDs are submitted in rank order. |
| className | string | undefined | Additional classes merged onto the root element. |
Customisation
Scope --token-order-ink for the ordinal mark, --token-order-surface for its backing and --token-order-duration for the finite FLIP beat. Defaults follow --primary, --background and --dur-3 respectively.
.workshop-order {
--token-order-ink: var(--primary);
--token-order-surface: var(--background);
--token-order-duration: var(--dur-3, 600ms);
}Frequently asked questions
- Is Token Order free for commercial use?
- Yes. Token Order is MIT licensed and may be used in personal and commercial projects.
- Does Token Order work with a keyboard and reduced motion?
- Yes. It uses native Up and Down buttons with visible focus, retains focus after a committed move, and switches to the final order under reduced motion. Server-rendered ranks and form fields remain available without JavaScript.
- Can I change the ranking colours and movement duration?
- Yes. Set --token-order-ink, --token-order-surface and --token-order-duration on an ancestor to retheme the ordinal and choose the FLIP duration.