Skip to content

feat(table): add column visibility kwargs and UI controls#9687

Merged
kirangadhave merged 9 commits into
mainfrom
kg/table-column-visibility
May 26, 2026
Merged

feat(table): add column visibility kwargs and UI controls#9687
kirangadhave merged 9 commits into
mainfrom
kg/table-column-visibility

Conversation

@kirangadhave
Copy link
Copy Markdown
Member

@kirangadhave kirangadhave commented May 26, 2026

Summary

Adds hidden_columns / visible_columns kwargs to mo.ui.table and wires interactive visibility controls into the UI. Visibility is a view-only concern: .value, selection, search, sort, filter, and CSV download continue to include hidden columns. This is the first PR. I will have a follow up PR which adds changes to the column explorer. Right now there is no way to unhide the hidden column, PR 2 will add that.

What's in PR 1

  • Backend: hidden_columns / visible_columns kwargs with validation and normalized payload.
  • Frontend plumbing: Zod schema + Data interface updates.
  • useColumnVisibility hook seeded from the payload, wired into DataTable state.
  • System columns (row index, select) are non-hideable.
  • Column header menu: "Hide column" item.
  • Bottom bar: clickable (N hidden) indicator that opens the Column Explorer (PR 2 will add unhide buttons here).
  • Recovery banner: when all user columns are hidden, render "All columns are hidden" with an "Unhide all" button.

PR 2 (discoverability: smart search, eye-icon toggle, "Unhide all" in Column Explorer) will follow.

Screen.Recording.2026-05-26.at.12.18.12.AM.mov

Addresses: #9220

@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment May 26, 2026 3:51pm

Request Review

@kirangadhave kirangadhave added the enhancement New feature or request label May 26, 2026
@kirangadhave kirangadhave marked this pull request as ready for review May 26, 2026 07:20
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 15 files

Architecture diagram
sequenceDiagram
    participant User as Python User
    participant Table as mo.ui.table (Python)
    participant Val as Validation
    participant Plugin as DataTablePlugin (Frontend)
    participant Schema as Zod Schema
    participant Hook as useColumnVisibility
    participant DT as DataTableInternal
    participant ColHeader as ColumnHeaderMenu
    participant ColExplorer as ColumnExplorerPanel
    participant BottomBar as TableBottomBar
    participant Banner as All-Hidden Banner

    Note over User,Banner: Column Visibility Flow (Happy Path)

    User->>Table: table(data, hidden_columns=["col1"])
    Table->>Val: _validate_column_visibility()
    Val-->>Table: validated list
    Table->>Table: normalizes hidden_columns or visible_columns to hidden list
    Table-->>Plugin: payload with hiddenColumns

    Plugin->>Schema: parse hiddenColumns
    Schema-->>Plugin: validated string[]
    Plugin->>DT: pass hiddenColumns prop
    DT->>Hook: useColumnVisibility(hiddenColumns)
    Hook->>Hook: init state: {"col1": false}
    Hook-->>DT: columnVisibility, setColumnVisibility

    DT->>DT: table options: onColumnVisibilityChange = setColumnVisibility
    DT->>DT: state: columnVisibility

    Note over DT,Banner: UI Controls

    User->>ColHeader: click column header menu
    ColHeader->>ColHeader: render HideColumn component
    alt column.getCanHide()
        User->>ColHeader: click "Hide column"
        ColHeader->>ColHeader: column.toggleVisibility(false)
        ColHeader-->>DT: visibility state update
    else column is system/row header
        ColHeader->>ColHeader: returns null (no hide option)
    end

    DT->>BottomBar: render with table ref
    BottomBar->>BottomBar: getUserColumnVisibilityCounts(table)
    BottomBar-->>BottomBar: {total, visible, hidden}
    alt hidden > 0
        BottomBar->>BottomBar: render "(N hidden)" button
        User->>BottomBar: click "(N hidden)"
        BottomBar->>ColExplorer: togglePanel(COLUMN_EXPLORER)
    else hidden = 0
        BottomBar->>BottomBar: no suffix rendered
    end

    Note over DT,Banner: All-Hidden Recovery

    DT->>DT: getUserColumnVisibilityCounts(table)
    alt total > 0 AND visible = 0
        DT->>Banner: render "All columns are hidden" banner
        User->>Banner: click "Unhide all"
        Banner->>DT: table.resetColumnVisibility()
        DT->>Hook: setColumnVisibility({})
    else visible > 0
        DT->>Banner: no banner rendered
    end

    Note over User,ColExplorer: Value Independent of Visibility

    User->>Table: .value
    Table-->>User: includes hidden columns (view-only concern)

    Note over ColExplorer: Column Explorer Display

    ColExplorer->>ColExplorer: prettifyRowColumnCount(hiddenColumns)
    ColExplorer-->>ColExplorer: shows visible count + hidden indicator
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread frontend/src/components/data-table/data-table.tsx Outdated
Comment thread marimo/_plugins/ui/_impl/table.py
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds column visibility support to mo.ui.table by introducing backend kwargs (hidden_columns / visible_columns) and wiring them through the frontend to TanStack Table column-visibility state, along with initial UI affordances (hide-from-header-menu, hidden-count indicator, and an all-hidden recovery banner).

Changes:

  • Backend: add hidden_columns / visible_columns kwargs, validate them, and emit a normalized hidden-columns payload.
  • Frontend: extend table plugin payload/schema, seed and manage TanStack columnVisibility, and add UI controls (hide action + hidden-count indicator + “all hidden” banner).
  • Tests: add Python + frontend unit tests covering visibility seeding and UI indicators.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tests/_plugins/ui/_impl/test_table.py Adds backend tests for hidden/visible kwargs normalization and validation.
marimo/_plugins/ui/_impl/table.py Implements kwargs, validation, and hidden-columns payload emission.
frontend/src/plugins/impl/DataTablePlugin.tsx Extends plugin Data + Zod schema, passes hiddenColumns into DataTable.
frontend/src/components/data-table/TableBottomBar.tsx Shows hidden-count suffix and hooks it to opening Column Explorer.
frontend/src/components/data-table/pagination.tsx Updates prettifyRowColumnCount to return structured output incl. hidden suffix.
frontend/src/components/data-table/hooks/use-column-visibility.ts Adds useColumnVisibility hook and column visibility counting helper.
frontend/src/components/data-table/header-items.tsx Adds HideColumn dropdown item component.
frontend/src/components/data-table/data-table.tsx Wires columnVisibility into table state and renders “all hidden” banner.
frontend/src/components/data-table/columns.tsx Marks which columns are hideable (excludes row headers/system/unnamed).
frontend/src/components/data-table/column-header.tsx Inserts hide action into the column header dropdown menu.
frontend/src/components/data-table/column-explorer-panel/column-explorer.tsx Adjusts to new prettifyRowColumnCount return type.
frontend/src/components/data-table/tests/useColumnVisibility.test.ts Tests seeding and updating visibility state.
frontend/src/components/data-table/tests/TableBottomBar.test.tsx Tests hidden-count rendering and click behavior.
frontend/src/components/data-table/tests/header-items.test.tsx Tests HideColumn menu item behavior.
frontend/src/components/data-table/tests/data-table.test.tsx Tests the “all columns hidden” banner visibility behavior.

Comment thread marimo/_plugins/ui/_impl/table.py
Comment thread marimo/_plugins/ui/_impl/table.py
Comment thread frontend/src/components/data-table/data-table.tsx Outdated
Comment thread frontend/src/components/data-table/column-header.tsx Outdated
Comment thread frontend/src/components/data-table/TableBottomBar.tsx
Comment thread frontend/src/components/data-table/TableBottomBar.tsx Outdated
Comment thread frontend/src/components/data-table/column-header.tsx Outdated
Companion to the backend change that started emitting `hidden-columns` in
the args payload. This wires the Zod schema, the `DataTableProps`
boundary, and a new `useColumnVisibility` hook so the next commit can
hand TanStack's `columnVisibility` state a seed.

The hook mirrors `useColumnPinning`: `useInternalStateWithSync` with a
dequal comparator. That keeps user toggles sticky across renders while
still re-applying a fresh seed when the upstream kwarg changes (the
visibility kwargs are seeds, not constraints).

No UI behavior change yet. `useReactTable` is not consuming the hook in
this commit.
Consumes the `hidden-columns` payload via the new `useColumnVisibility`
hook. The hook seeds TanStack's `columnVisibility` state from the prop
and routes user toggles back through `onColumnVisibilityChange`.

Also gates which columns may be hidden: row headers and nameless
columns get `enableHiding: false`. The selection column already had it.
This protects structural columns from being removed by the column-header
menu added in the next commit.
Adds a "Hide column" entry to the column-header dropdown using TanStack's
`column.toggleVisibility`. The item only renders for columns with
`enableHiding: true`, which excludes row headers, nameless columns, and
the selection column.

Implemented as a React component (`<HideColumn />`) rather than the
`renderX(column)` helpers used elsewhere in this file. The pattern shift
is captured as a follow-up refactor for the other helpers; both shapes
coexist with a TODO at the call site.

No guard against hiding the last visible column. The all-hidden state is
reachable from both this menu and from `hidden_columns=[...]` on the
Python side; recovery happens through a single banner rather than
ad-hoc per-path guards.
Footer renders "(N hidden)" suffix when columns are hidden;
clicking it opens the Column Explorer panel.
When every user-hideable column is hidden, render a banner with an
'Unhide all' button above the table. Extract a shared helper for
user column visibility counts.
resetColumnVisibility() without args reverts to initial state seeded
from the hidden_columns kwarg, which leaves user-passed hidden columns
hidden. Pass true so all columns become visible.
When DataTablePlugin clips columns, the table instance only has the
rendered subset. Use that subset's total for visible/hidden math; keep
the dataset-wide prop only for the no-hidden label.
@kirangadhave kirangadhave force-pushed the kg/table-column-visibility branch from 55c3706 to dffd209 Compare May 26, 2026 15:50
@kirangadhave kirangadhave requested review from akshayka and removed request for manzt May 26, 2026 15:56
Copy link
Copy Markdown
Collaborator

@Light2Dark Light2Dark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code looks good

Comment on lines +165 to +173
{hiddenSuffix && (
<button
type="button"
className="text-xs underline-offset-2 hover:underline cursor-pointer"
onClick={() => togglePanel?.(PANEL_TYPES.COLUMN_EXPLORER)}
>
{hiddenSuffix}
</button>
)}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

Comment thread marimo/_plugins/ui/_impl/table.py
@kirangadhave kirangadhave merged commit 21b0084 into main May 26, 2026
43 checks passed
@kirangadhave kirangadhave deleted the kg/table-column-visibility branch May 26, 2026 18:32
@github-actions
Copy link
Copy Markdown

🚀 Development release published. You may be able to view the changes at https://marimo.app?v=0.23.9-dev5

kirangadhave added a commit that referenced this pull request May 27, 2026
## Summary
Second of two PRs implementing `mo.ui.table` column visibility (RFC).
Builds on #9687 (PR 1: Python kwargs, hooks, hidden-count display,
recovery banner).

- Substring filter replaced with `smartMatch`: queries split on
whitespace and each word must prefix a word in the column name.
- Click hides/shows the column. Eye icon when visible, eye-off when
hidden.
- "Unhide all" link + hidden count in the panel header. Shown only when
at least one user column is hidden.


https://github.com/user-attachments/assets/6f08b1cf-c5ba-474b-8a49-6cb86c9d5625


Related to #9220
Closes #9419
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants