Generic LIVE column-configuration modal for admin tables: a "Shown" list (drag to reorder via the SortableGrid hook, ✕ to remove) beside an "Available" list (click to add), with Reset + Close. There is no Apply step — the consumer applies each change immediately, so the table updates behind the modal as the user works.
Ownership model
Pure presentation. The consumer owns the column catalog, the selected
list, and persistence, and implements these events. LiveView callers
need no extra wiring; LiveComponent callers pass target (a CSS
selector for the component root) so clicks and the SortableGrid hook
reach that component instead of the host LiveView:
add_column %{"column_id" => id}
remove_column %{"column_id" => id}
reorder_columns %{"ordered_ids" => ids} (from SortableGrid)
reset_columns %{}
hide_column_modal %{} (Close / backdrop / Esc)Usage
<.column_settings_modal
show={@show_columns}
columns={[%{id: "sku", label: "SKU"}, %{id: "price", label: fn -> gettext("Price") end}]}
selected={@columns}
/>columns is every configurable column; selected is the shown ids in
display order. Labels may be strings or 0-arity functions (evaluated at
render, so gettext labels stay lazy). Ids in selected that are not in
columns are ignored, so consumers with unmanaged always-on columns
(a Name column outside the editor) can pass their full list.
Shown rows use the sortable-item class the SortableGrid hook actually
reads (draggable, item-count, ordered_ids). A custom class is
ignored. Drag starts only on .pk-drag-handle so the remove button is
not a drag surface.
Summary
Functions
Attributes
show(:boolean) (required)id(:string) - Defaults to"pk-column-settings-modal".columns(:list) (required) - Every configurable column: %{id: String.t(), label: String.t() | (-> String.t())}.selected(:list) (required) - Shown column ids, in display order.target(:any) - Optional LiveComponent CSS selector (e.g.#my-table). Set on everyphx-clickand ondata-sortable-targetso a LiveComponent consumer receives add/remove/reorder/reset/close. Defaults tonil.