Documentation
¶
Overview ¶
Package sortablelist renders a reorderable list with HTML5 drag-and-drop plus keyboard fallback (Space to grab, Arrow up/down to move within a column, Arrow left/right to move between columns, Space again to drop, Esc to cancel).
Single-list usage (back-compat — no new attrs emitted):
<ol data-fui-comp="ui-sortable-list" role="listbox"
data-fui-sortable data-fui-sortable-rpc="<path>">
<li data-fui-sortable-item data-fui-sort-key="<key>"
draggable="true" tabindex="0" role="option">…</li>
</ol>
Kanban (cross-container) usage — render one list per column, all sharing the same Group, each with a unique Container id:
<ol data-fui-sortable data-fui-sortable-group="board-1"
data-fui-sortable-container="todo"
data-fui-sortable-rpc="/api/move"
data-fui-sortable-version="v3"
data-fui-sortable-conflict="/api/conflict?col=todo">
…
</ol>
After a successful same-container reorder the runtime POSTs `order=<comma-sep-keys>`. A cross-container drop POSTs `order=<dest-keys>&moved=<key>&container=<col-id>`. When Version is set, a `version=<token>` field is appended to every commit; a 409 response fires the conflict path (GET ConflictRPC → replace list HTML) instead of a blanket rollback. The server is authoritative — non-2xx reverts the DOM.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RenderItems ¶ added in v0.20.0
RenderItems renders just the <li> items without the <ol> wrapper. Used by conflict-recovery endpoints that need to replace a list's innerHTML with fresh server-rendered rows. Returns an empty fragment when cfg has no Items (authoritative reconciliation can replace a column with an empty response — issue #82).
Types ¶
type Config ¶
type Config struct {
// Items are the entries in initial order. May be empty — an empty
// column renders a valid sortable <ol> wrapper with no <li>
// children (Kanban empty containers, issue #82).
Items []Item
// Label is the accessible label for the list (required, used as
// aria-label on the <ol>).
Label string
// RPCPath, when set, is POSTed with order=<keys> after every
// successful reorder. Server responds 2xx to confirm or non-2xx
// to reject + revert.
RPCPath string
ID string
Class string
// ExtraAttrs are merged onto the <ol> after all built-in attrs.
ExtraAttrs html.Attrs
// Group is the board id shared by linked columns (kanban). Lists
// with the same non-empty Group allow cross-container drag and
// keyboard moves between them. Lists with no Group stay isolated
// (back-compat: existing single lists are unaffected).
Group string
// Container is the per-column id sent as the `container` field in
// a cross-container move payload so the server knows which column
// the item landed in. Distinct from Group (the board id) because a
// board has one Group but N Containers — the server needs both to
// route the write.
Container string
// Version is an optional optimistic-concurrency token sent as a
// `version` body field on every commit. When set, a 409 response
// fires the conflict path (refetch ConflictRPC HTML) instead of a
// blanket rollback. Without Version, 409 is treated like any other
// non-2xx (rollback) — back-compat.
Version string
// ConflictRPC, when set alongside Version, is GET-fetched on a
// 409 response. The response body replaces the destination list's
// innerHTML (server-rendered reconciliation). Without ConflictRPC,
// a 409 falls back to rollback + a console warn.
ConflictRPC string
}
Config configures a SortableList.
type Item ¶
type Item struct {
// Key is the stable identifier the server uses to apply the new
// order (required).
Key string
// Label is the visible row text + accessible label for the drag
// handle (required).
Label string
// Content, when set, replaces Label as the row body. Use for
// richer rows (icons, badges, etc.). The grip's aria-label still
// uses Label.
Content render.HTML
}
Item is one entry in the list.