{"schemaVersion":"1.0","type":"Article","slug":"mantine-list-view-table-from-table-to-finder-yu6j5","url":"https://api.zyvop.com/mantine-list-view-table-from-table-to-finder-yu6j5","title":"Mantine List View Table - From Table to Finder","subtitle":null,"tldr":"Row selection, keyboard navigation, context menus, column visibility, dual resize modes, and 6...","keywords":["react","TypeScript","webcomponents","ui"],"entities":["Giovambattista Fazioli","Senior Full-stack Engineer, Lead Developer","react","TypeScript","webcomponents","ui","ZyVOP"],"keyTakeaways":["Row selection, keyboard navigation, context menus, column visibility, dual resize modes, and 6 exported hooks — one release, zero compromises.","Introduction Picture the macOS Finder: you click a file, Shift+click to select a range, right-click for a context menu, double-click a column divider to auto-fit, and hide columns you don't need.","Now picture doing all of that in a React table component — with full Mantine integration and zero external dependencies."],"headings":["Introduction","What's New","✨ Row Selection","⌨️ Keyboard Navigation","🖱️ Context Menu","👁️ Column Visibility","↔️ Dual Resize Modes","🎯 Double-Click Auto-Fit","🪝 6 Exported Hooks","📋 New Props Summary","🎨 New Styles API","💥 Breaking Changes","1. Props interface no longer extends TableProps","2. enableColumnReordering and enableColumnResizing default to false","3. Component ref type changed","4. Context menu requires Menu.Item elements","5. visibleMediaQuery removed from column config","6. contextMenu Styles API selector removed","🐛 Bug Fixes","🔧 Improvements","Migration Guide","Step 1: Install the update","Step 2: Wrap Table props in tableProps","Step 3: Opt in to reordering/resizing"],"outboundLinks":["https://www.npmjs.com/package/@gfazioli/mantine-list-view-table","https://gfazioli.github.io/mantine-list-view-table/","https://github.com/gfazioli/mantine-list-view-table","https://www.youtube.com/playlist?list=PL85tTROKkZrWyqCcmNCdWajpx05-cTal4","https://mantine-extensions.vercel.app/"],"contentText":"Row selection, keyboard navigation, context menus, column visibility, dual resize modes, and 6 exported hooks — one release, zero compromises. Introduction Picture the macOS Finder: you click a file, Shift+click to select a range, right-click for a context menu, double-click a column divider to auto-fit, and hide columns you don't need. Now picture doing all of that in a React table component — with full Mantine integration and zero external dependencies. That's what @gfazioli/mantine-list-view-table 2.0.0 delivers. This isn't an incremental update; it's a rewrite that transforms a sortable table into a complete Finder-style list view, with every piece of logic extracted into reusable, publicly exported hooks. What's New ✨ Row Selection Select rows exactly like macOS Finder. Single click selects one row, Cmd/Ctrl+Click toggles, Shift+Click selects a range. Both single and multiple modes are supported, with controlled and uncontrolled state. &lt;ListViewTablecolumns={columns}data={data}rowKey=\"id\"selectionMode=\"multiple\"onSelectionChange={(keys, records) =&gt; setSelected(keys)}selectedRowColor=\"blue\"/&gt; Enter fullscreen mode Exit fullscreen mode Selected rows get a visible highlight that desaturates when the component loses focus — matching Finder's behavior pixel for pixel. ⌨️ Keyboard Navigation When selectionMode is set, keyboard navigation activates automatically: Key Action Arrow Up/Down Move focus between rows Enter Activate row (onRowActivate) Space Toggle selection Home / End Jump to first / last row Cmd/Ctrl+A Select all (multiple mode) &lt;ListViewTableselectionMode=\"multiple\"enableKeyboardNavigationonRowActivate={(record) =&gt; openFile(record)}/&gt; Enter fullscreen mode Exit fullscreen mode 🖱️ Context Menu Right-click any row to show a context menu powered by Mantine's Menu component. The clicked row is automatically selected before the menu appears. You get Mantine's full accessibility, keyboard support, and dark mode out of the box. &lt;ListViewTableselectionMode=\"single\"renderContextMenu={({ record }) =&gt; ( &lt;&gt; &lt;Menu.Item leftSection={&lt;IconCopy size={14} /&gt;}&gt;Copy&lt;/Menu.Item&gt; &lt;Menu.Item leftSection={&lt;IconDownload size={14} /&gt;}&gt;Download&lt;/Menu.Item&gt; &lt;Menu.Divider /&gt; &lt;Menu.Item color=\"red\" leftSection={&lt;IconTrash size={14} /&gt;}&gt;Delete&lt;/Menu.Item&gt; &lt;/&gt;)}/&gt; Enter fullscreen mode Exit fullscreen mode 👁️ Column Visibility Hide and show columns programmatically or let users toggle them by right-clicking the table header. Supports both controlled and uncontrolled modes. &lt;ListViewTablehiddenColumns={['size', 'modified']}onHiddenColumnsChange={setHiddenColumns}enableColumnVisibilityToggle/&gt; Enter fullscreen mode Exit fullscreen mode ↔️ Dual Resize Modes The new resizeMode prop gives you two column resize behaviors: standard (default) — width is traded between the dragged column and its right neighbor. Total table width stays fixed. Great for fixed-width layouts. finder — only the dragged column changes width. The table grows freely, just like Finder. Pair with Table.ScrollContainer for horizontal scrolling. &lt;ListViewTable enableColumnResizing resizeMode=\"finder\" /&gt; Enter fullscreen mode Exit fullscreen mode 🎯 Double-Click Auto-Fit Double-click any resize handle to auto-fit the column to its content — measured accurately using off-screen DOM clones. In standard mode, the adjacent column compensates to keep the total width constant. 🪝 6 Exported Hooks Every piece of internal logic is now a standalone, reusable hook: Hook Purpose useSorting Sort state with controlled/uncontrolled modes useColumnReorder Drag-and-drop column reordering useColumnResize Column resize with standard/finder modes useRowSelection Row selection (single, multiple, range) useKeyboardNavigation Arrow/Enter/Space keyboard navigation useColumnVisibility Column show/hide management Import them directly for advanced compositions: import { useRowSelection, useKeyboardNavigation } from '@gfazioli/mantine-list-view-table'; Enter fullscreen mode Exit fullscreen mode 📋 New Props Summary Prop Type Default Description selectionMode `'single' \\ 'multiple'` — selectedRows React.Key[] — Controlled selected row keys defaultSelectedRows React.Key[] — Default selected keys (uncontrolled) onSelectionChange (keys, records) =&gt; void — Selection change callback selectedRowColor MantineColor — Selected row background color enableKeyboardNavigation boolean true when selectionMode is set Enable keyboard nav onRowActivate (record, index) =&gt; void — Enter key callback renderContextMenu (info) =&gt; ReactNode — Context menu content (use Menu.Item) onRowContextMenu (record, index, event) =&gt; void — Right-click callback hiddenColumns string[] — Controlled hidden column keys defaultHiddenColumns string[] — Default hidden columns (uncontrolled) onHiddenColumnsChange (keys) =&gt; void — Hidden columns change callback enableColumnVisibilityToggle boolean false Right-click header to toggle columns resizeMode `'standard' \\ 'finder'` 'standard' tableProps Partial&lt;TableProps&gt; — Props passed to inner &lt;Table&gt; stickyHeader boolean false Sticky table header stickyHeaderOffset `number \\ string` 0 tabularNums boolean false Tabular number alignment 🎨 New Styles API New selectors: selectedRow, focusedRow New CSS variables: Variable Description --list-view-selected-row-color Background color of selected rows --list-view-sticky-blur Backdrop blur for sticky column overlay 💥 Breaking Changes [!CAUTION] This release contains breaking changes. Review the migration guide below before upgrading. 1. Props interface no longer extends TableProps Table-level props (variant, layout, etc.) must now be passed through tableProps: // Before&lt;ListViewTable variant=\"vertical\" /&gt; // After&lt;ListViewTable tableProps={{ variant: 'vertical' }} /&gt; Enter fullscreen mode Exit fullscreen mode 2. enableColumnReordering and enableColumnResizing default to false Previously both defaulted to true. Now you must opt in: &lt;ListViewTable enableColumnReordering enableColumnResizing /&gt; Enter fullscreen mode Exit fullscreen mode 3. Component ref type changed // Beforeconst ref = useRef&lt;HTMLTableElement&gt;(null); // Afterconst ref = useRef&lt;HTMLDivElement&gt;(null); Enter fullscreen mode Exit fullscreen mode 4. Context menu requires Menu.Item elements The renderContextMenu prop must now return Mantine Menu.Item / Menu.Divider components instead of arbitrary JSX: // BeforerenderContextMenu={() =&gt; (&lt;Stack gap={0}&gt; &lt;UnstyledButton&gt;Copy&lt;/UnstyledButton&gt;&lt;/Stack&gt;)} // AfterrenderContextMenu={() =&gt; (&lt;&gt; &lt;Menu.Item leftSection={&lt;IconCopy size={14} /&gt;}&gt;Copy&lt;/Menu.Item&gt;&lt;/&gt;)} Enter fullscreen mode Exit fullscreen mode 5. visibleMediaQuery removed from column config Use the new hiddenColumns prop instead for programmatic column visibility. 6. contextMenu Styles API selector removed The context menu is now powered by Mantine's Menu, which has its own styling system. 🐛 Bug Fixes Double-click no longer triggers drag resize — event.detail &gt;= 2 guard prevents mousedown from starting a drag during double-click Auto-fit preserves table width — adjacent column compensates the exact delta in standard mode Controlled sort respects external data order — no internal re-sorting when sortStatus + onSort are both provided Keyboard navigation bounds check — Enter/Space no longer fire with invalid indices after data filtering Range selection clamped — Shift+click clamps to [0, data.length - 1] when data changes between clicks 🔧 Improvements Resize handle UX overhaul — 14px hit area (20px touch), animated indicator line with spring curve Finder-style header focus — inset bottom border instead of background highlight Accessible focus indicator — :focus-visible outline on root element for keyboard users Sticky columns without !important — cleaner CSS specificity Vertical variant — now supports dot-notation keys (getNestedValue) and renderCell Migration Guide Step 1: Install the update yarn add @gfazioli/mantine-list-view-table@^2.0.0 Enter fullscreen mode Exit fullscreen mode Step 2: Wrap Table props in tableProps If you passed Mantine Table props directly, move them: // Before&lt;ListViewTable variant=\"vertical\" layout=\"fixed\" /&gt; // After&lt;ListViewTable tableProps={{ variant: 'vertical', layout: 'fixed' }} /&gt; Enter fullscreen mode Exit fullscreen mode Step 3: Opt in to reordering/resizing &lt;ListViewTable enableColumnReordering enableColumnResizing /&gt; Enter fullscreen mode Exit fullscreen mode Step 4: Update ref type const ref = useRef&lt;HTMLDivElement&gt;(null); // was HTMLTableElement Enter fullscreen mode Exit fullscreen mode Step 5: Update context menu Replace custom JSX with Menu.Item from @mantine/core: import { Menu } from '@mantine/core'; renderContextMenu={({ record }) =&gt; (&lt;&gt; &lt;Menu.Item leftSection={&lt;IconCopy size={14} /&gt;}&gt;Copy&lt;/Menu.Item&gt; &lt;Menu.Divider /&gt; &lt;Menu.Item color=\"red\" leftSection={&lt;IconTrash size={14} /&gt;}&gt;Delete&lt;/Menu.Item&gt;&lt;/&gt;)} Enter fullscreen mode Exit fullscreen mode Step 6: Replace visibleMediaQuery // Before (on column){ key: 'size', visibleMediaQuery: '(min-width: 768px)' } // After (on component)&lt;ListViewTable hiddenColumns={isMobile ? ['size'] : []} /&gt; Enter fullscreen mode Exit fullscreen mode Compatibility Mantine: 8.x React: 18.x / 19.x @tabler/icons-react: ^3.34.0 License: MIT Links 📦 npm 📖 Documentation &amp; Demos 🔗 GitHub 🎥 YouTube Tutorials 🧩 Mantine Extensions Hub","contentHash":"sha256:890aca5be4533fd81efc1c66be4e27897067dc59452bbb55a1234b2150e3266b","authorName":"Giovambattista Fazioli","authorUrl":"https://api.zyvop.com/author/giovambattista","authorSameAs":["https://gfazioli.github.io","https://github.com/gfazioli","https://x.com/gfazioli","https://www.linkedin.com/in/giovambattistafazioli/"],"category":null,"tags":["react","TypeScript","webcomponents","ui"],"audience":"Readers researching react","tone":"Professional, senior full-stack engineer, lead developer perspective","readingTimeMinutes":6,"wordCount":1275,"faqs":null,"primaryTopic":"react","publishedAt":"2026-09-04T09:25:28.342Z","updatedAt":"2026-09-04T09:25:28.342Z","canonicalUrl":"https://dev.to/undolog/mantine-list-view-table-from-table-to-finder-ini"}