Domphy

Column Visibility & Ordering

Column visibility

Enable column visibility — users can show/hide columns:

import { createDomphyTable } from "@domphy/table/domphy"
import { toState } from "@domphy/core"

const columnVisibility = toState<Record<string, boolean>>({})

const table = createDomphyTable({
  data: () => rows,
  columns,
  state: { columnVisibility: columnVisibility.get() },
  onColumnVisibilityChange: (updater) => {
    columnVisibility.set(
      typeof updater === "function"
        ? updater(columnVisibility.get())
        : updater
    )
  },
  enableHiding: true,
})

Column visibility toggle UI

const ColumnToggle = {
  div: [
    { h4: "Columns" },
    {
      div: (l) => table.getAllLeafColumns(l).map((col) => ({
        _key: col.id,
        label: [
          {
            input: null,
            type: "checkbox",
            checked: (l) => col.getIsVisible(),
            disabled: !col.getCanHide(),
            onChange: () => col.toggleVisibility(),
          },
          { span: String(col.columnDef.header ?? col.id) },
        ],
      })),
    },
  ],
}

col.getCanHide() returns false for columns with enableHiding: false — prevent critical columns from being hidden.

Pin certain columns as always visible

const columns = [
  columnHelper.accessor("id", {
    header: "ID",
    enableHiding: false,   // cannot be hidden
  }),
  columnHelper.accessor("name", {
    header: "Name",
  }),
  columnHelper.accessor("status", {
    header: "Status",
  }),
]

Column ordering

Reorder columns programmatically or via drag-and-drop:

import { toState } from "@domphy/core"

const columnOrder = toState<string[]>([])

const table = createDomphyTable({
  data: () => rows,
  columns,
  state: { columnOrder: columnOrder.get() },
  onColumnOrderChange: (updater) => {
    columnOrder.set(
      typeof updater === "function"
        ? updater(columnOrder.get())
        : updater
    )
  },
})

// Move a column
function moveColumn(fromId: string, toId: string) {
  table.table.setColumnOrder((old) => {
    const order = old.length
      ? [...old]
      : table.getAllLeafColumns().map(c => c.id)

    const from = order.indexOf(fromId)
    const to = order.indexOf(toId)
    if (from === -1 || to === -1) return old

    const next = [...order]
    next.splice(from, 1)
    next.splice(to, 0, fromId)
    return next
  })
}

Column ordering with drag and drop

Combine with @domphy/dnd for drag-to-reorder headers:

import { dragDrop } from "@domphy/dnd"
import { toState } from "@domphy/core"

const headerOrder = toState<string[]>([])

const HeaderRow = {
  tr: (l) => {
    const headers = table.getHeaderGroups(l)[0]?.headers ?? []
    return headers.map((header) => ({
      th: String(header.column.columnDef.header ?? ""),
      _key: header.id,
      style: { cursor: "grab" },
    }))
  },
  $: [dragDrop(headerOrder, {
    group: "column-headers",
    onSort: (order) => table.table.setColumnOrder(order),
  })],
}

Persisting column state

Save column visibility and order to localStorage:

const STORAGE_KEY = "table-column-state"

interface ColumnState {
  visibility: Record<string, boolean>
  order: string[]
}

function loadColumnState(): ColumnState {
  try {
    return JSON.parse(localStorage.getItem(STORAGE_KEY) ?? "null") ?? { visibility: {}, order: [] }
  } catch {
    return { visibility: {}, order: [] }
  }
}

function saveColumnState(state: ColumnState) {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(state))
}

const saved = loadColumnState()
const columnVisibility = toState(saved.visibility)
const columnOrder = toState(saved.order)

// Persist on change
columnVisibility.subscribe((v) => saveColumnState({ visibility: v, order: columnOrder.get() }))
columnOrder.subscribe((o) => saveColumnState({ visibility: columnVisibility.get(), order: o }))

"Show all" / "Hide all" buttons

const ShowAllButton = {
  button: "Show all",
  onClick: () => table.table.resetColumnVisibility(),
}

const HideButton = (columnId: string) => ({
  button: "Hide",
  onClick: () => table.table.getColumn(columnId)?.toggleVisibility(false),
})

Visibility API

MethodDescription
col.getIsVisible()true if column is visible
col.getCanHide()false if enableHiding: false
col.toggleVisibility(value?)Toggle or set visibility
table.getVisibleLeafColumns(l)All visible leaf columns
table.getIsAllColumnsVisible(l)true if all columns visible
table.getIsSomeColumnsVisible(l)true if some columns visible
table.toggleAllColumnsVisible()Toggle all
table.resetColumnVisibility()Reset to initial state
table.setColumnOrder(updater)Set column order
table.resetColumnOrder()Reset to initial order