Skip to content
Component installs need the registry setup
VegaStack Design

Sort Menu

The one-key sort — the fields, then the two directions worded by field type, with Reset while the order is not the page's default.

Status
stable
Since
0.25.100
Accessibility pattern
two labelled radio groups; arrow keys move

Last updated

Sort by
Due datePriorityLast updatedNameSize
Oldest firstNewest first

Install

Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Sort Menu before installation. Retain the digest printed by this command.

pnpm exec vegastack-design verify sort-menu

Install with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.

pnpm dlx shadcn@4.21.0 add @vegastack/sort-menu

Run the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.

The same command installs the registry items it composes: @vegastack/button.

Usage

import { SortMenu, sortSummary } from "@/components/ui/sort-menu";

<ListToolbar
  sort={{
    content: (
      <SortMenu
        fields={[
          { key: "due", label: "Due date", type: "date" },
          { key: "title", label: "Title" },
        ]}
        value={sort}
        defaultValue={{ key: "due", direction: "asc" }}
        onValueChange={setSort}
      />
    ),
    isDefault: sort.key === "due" && sort.direction === "asc",
    summary: sortSummary(fields, sort),
  }}
/>;

A list that sorts by one key shows exactly that: which field, then which direction, each a group of options with a check on the chosen one. There are no drag handles, selects or "Add sort" — an affordance a one-key list can never use is not shown. The directions read in the field's own words: dates "Oldest first / Newest first", text "A → Z / Z → A", numbers "Low → high / High → low", a fixed order (priority, status) "First to last / Last to first". "Reset" sits in the header while the order differs from defaultValue. A column header click writes the same value.

A field the list can sort only one way sets fixedDirection: its direction shows in muted words beside its name ("Last updated Newest first"), picking it sets that direction, and the direction group hides while it is chosen, so the menu never offers an order the server cannot give. fixedDirection: "none" is a manual order ("Custom order"): no direction words at all.

sortSummary(fields, value) returns one line ("Due date, oldest first") for the Sort row Display shows once the toolbar has folded Sort into it.

For several keys at once (a table), use SortBuilder from filter-bar-managed.

Examples

Fields of every type

Sort by
Due datePriorityLast updatedNameSize
Oldest firstNewest first

API Reference

PropTypeDefaultDescription
fields*readonly SortMenuField[]—The fields, in the order offered.
onValueChange*(value: SortMenuValue) => void—Called with the next order.
value*SortMenuValue—The current order.
classNamestring—Extra classes for the root.
defaultValueSortMenuValue—The page's default order. While value differs from it, "Reset" shows.
labels(Partial<Omit<SortMenuLabels, "directions">> & { directions?: Partial<SortMenuLabels["directions"]>; })EnglishThe component's words.

Data attributes and CSS variables on SortMenu

AttributeValues
data-default""
data-slot"sort-menu" | "sort-menu-direction" | "sort-menu-fields" | "sort-menu-header" | "sort-menu-reset"

Field

PropTypeDefaultDescription
key*string—Stable key.
label*string—The field's name ("Due date").
fixedDirection"asc" | "desc" | "none"undefined (both ways)The one way this field sorts, when the list cannot sort it both ways: its direction shows beside the name and the direction group hides while it is chosen. "none" is a manual order (no direction to show at all).
type"date" | "enum" | "number" | "text""text"What the field holds — it words the directions.

Accessibility

  • The fields are a radiogroup labelled by its "Sort by" heading; the directions are a second radiogroup named "Direction". The chosen option is aria-checked.
  • Each option is 32px tall from the surface's 8px inset.
KeyAction
↑ ↓Move within a group and pick
TabMove between Reset and groups
ContractStates tested
Behaviourdefault, changed
Accessibilitylabeled, browser-accessibility-test
Visualdefault, hover

Do / Don't

Do
Type every field so the directions read in its words, and pass the page's default so Reset and the toolbar's dot work.
Don't
Use a SortBuilder with max one, or offer a field the list cannot sort by.

On this page