Skip to content
Template Empire
Browse components

Table Column Visibility

A free React table column visibility component for data tables in Next.js, React and Tailwind.

Choose the columns for this view

4 of 4 columns visible

Visible columns
Choose visible columns
Wear Valley Railway fleet records
RecordTeamStatusLast service
76084 KirkstoneTrafficIn service12 Oct 2026
5643 GlyderEngineeringUnder overhaul28 Sep 2026
68011 SnowdonOperationsIn service04 Oct 2026

Customise

Code

const columns = [
  { id: "record", label: "Record" },
  { id: "team", label: "Team" },
  { id: "status", label: "Status" },
];

const rows = [
  { id: "76084", cells: { record: "76084 Kirkstone", team: "Traffic", status: "In service" } },
  { id: "5643", cells: { record: "5643 Glyder", team: "Engineering", status: "Under overhaul" } },
];

const [visibleColumnIds, setVisibleColumnIds] = useState<string[]>(columns.map(({ id }) => id));

<TableColumnVisibility
  columns={columns}
  rows={rows}
  caption="Wear Valley Railway fleet records"
  visibleColumnIds={visibleColumnIds}
  onVisibleColumnIdsChange={setVisibleColumnIds}
/>

Table Column Visibility is a free table component for Next.js and React, styled with Tailwind. It lets people choose which columns appear using a native disclosure and checkboxes while keeping the current records and their order in place.

Visible columns remain real table headers and cells, hidden columns leave the table and accessibility tree, and the last visible column stays protected. Use controlled IDs when your application owns the preference, or let the component manage the current view locally.

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/table-column-visibility

Usage

import { TableColumnVisibility } from "@/components/table-column-visibility";

const columns = [
  { id: "record", label: "Record" },
  { id: "team", label: "Team" },
  { id: "status", label: "Status" },
];

const rows = [
  { id: "76084", cells: { record: "76084 Kirkstone", team: "Traffic", status: "In service" } },
  { id: "5643", cells: { record: "5643 Glyder", team: "Engineering", status: "Under overhaul" } },
];

export default function Page() {
  return <TableColumnVisibility caption="Fleet records" columns={columns} rows={rows} />;
}

Props

PropTypeDefaultDescription
columns{ id: string; label: string; align?: "left" | "center" | "right"; defaultVisible?: boolean }[]requiredOrdered table columns. Duplicate and empty IDs are ignored after validation.
rows{ id: string; cells: Record<string, ReactNode> }[]requiredConsumer-owned rows and cell content, rendered in supplied order. Duplicate or empty row IDs get deterministic fallback keys.
captionstringrequiredVisible table caption.
visibleColumnIdsstring[]undefinedControlled visible IDs, normalized to known column IDs in column order. Requires onVisibleColumnIdsChange.
defaultVisibleColumnIdsstring[]all columnsInitial visible IDs for uncontrolled use. Invalid or empty sets fall back to the first valid column.
onVisibleColumnIdsChange(visibleColumnIds: string[]) => voidundefinedCalled with the normalized visible IDs after a user change or Show all action.
classNamestringundefinedAdditional classes merged onto the component shell.

Customisation

The table uses semantic surface, border, foreground, muted and focus tokens. Pass IDs to control visibility from application state, and scope theme tokens around this instance when it sits in a distinct panel:

<TableColumnVisibility
  columns={columns}
  rows={rows}
  caption="Fleet records"
  visibleColumnIds={visibleIds}
  onVisibleColumnIdsChange={setVisibleIds}
  className="max-w-5xl"
/>

Frequently asked questions

Is Table Column Visibility free for commercial use?
Yes. Table Column Visibility is MIT licensed and can be used in personal and commercial projects.
Are hidden columns still available to screen readers?
No. Hidden columns are removed from the table markup, so they leave the visual table and its accessible representation together.
Can I control which columns are shown?
Yes. Pass visibleColumnIds with onVisibleColumnIdsChange for controlled state, or use defaultVisibleColumnIds for an initial local view. The component always keeps at least one valid column visible.

Related components

Want a complete data interface?Template Empire templates pair production-ready table views with polished pages and workflows.Browse Template Empire templates