Mantine List View Table

Undolog

@gfazioli/mantine-list-view-table

The Mantine component adds a Finder-style List View to the Mantine Table, allowing for column reordering and resizing.

Installation

yarn add @gfazioli/mantine-list-view-table

After installation import package styles at the root of your application:

import '@gfazioli/mantine-list-view-table/styles.css';

You can import styles within a layer @layer mantine-list-view-table by importing @gfazioli/mantine-list-view-table/styles.layer.css file.

import '@gfazioli/mantine-list-view-table/styles.layer.css';

Usage

The ListViewTable component brings advanced table functionality inspired by the List View found in macOS Finder. Building on the core features of the Mantine Table component, it offers a familiar and intuitive interface for displaying lists of items in a structured, table-like format. Notably, it allows users to reorder columns and resize them dynamically, giving greater flexibility and control over data presentation. This makes it an excellent choice for applications that require a modern, customizable list view with enhanced interactivity.

File.txt

12 KB
2024-06-01

Image.png

2 MB
2024-06-02

Video.mp4

125 MB
2024-06-03

Document.pdf

500 KB
2024-06-04

Archive.zip

1.5 GB
2024-06-05

Spreadsheet.xlsx

300 KB
2024-06-06

Presentation.pptx

2 MB
2024-06-07

Audio.mp3

5 MB
2024-06-08

Script.js

15 KB
2024-06-09
Striped color
import { ListViewTable } from '@gfazioli/mantine-list-view-table';
import { Badge, Text } from '@mantine/core';
import [data, columns] from './data';

function Demo() {
  return (
    <ListViewTable
      columns={columns}
      data={data}
      rowKey="id"
      onRowClick={(row) => console.log('Clicked:', row.name)}

    />
  );
}

Column Width Constraints

You can control column widths using width, minWidth, and maxWidth properties. The component automatically adjusts initial widths to respect these constraints and prevents resizing beyond the specified limits.

Minimum Width

Use minWidth to ensure columns don't become too narrow. When the initial width is smaller than minWidth, the component automatically adjusts to the minimum value.

Documents

Folder
--2024-06-01

README.md

Markdown
2.1 KB2024-06-02

package.json

JSON
1.8 KB2024-06-03

src

Folder
--2024-06-04

image.png

PNG Image
45.2 KB2024-06-05
import { ListViewTable } from '@gfazioli/mantine-list-view-table';
import { Badge, Text } from '@mantine/core';
import [ data, columns ] from './data';

function Demo() {
  return (
    <ListViewTable
      columns={columns}
      data={data}
      rowKey="id"
      withTableBorder
      withColumnBorders
      highlightOnHover
      enableColumnResizing
      onColumnResize={(columnKey, width) => {
        console.log(`Column '${columnKey}' resized to: ${width}px`);
      }}
    />
  );
}

Maximum Width

Use maxWidth to prevent columns from becoming too wide. When the initial width is larger than maxWidth, the component automatically adjusts to the maximum value.

Documents

Folder
--2024-06-01

README.md

Markdown
2.1 KB2024-06-02

package.json

JSON
1.8 KB2024-06-03

src

Folder
--2024-06-04

image.png

PNG Image
45.2 KB2024-06-05
import { ListViewTable } from '@gfazioli/mantine-list-view-table';
import { Badge, Text } from '@mantine/core';
import [ data, columns ] from './data';

function Demo() {
  return (
    <ListViewTable
      columns={columns}
      data={data}
      rowKey="id"
      withTableBorder
      withColumnBorders
      highlightOnHover
      enableColumnResizing
      onColumnResize={(columnKey, width) => {
        console.log(`Column '${columnKey}' resized to: ${width}px`);
      }}
    />
  );
}

Both Minimum and Maximum Width

You can combine minWidth and maxWidth to create precise width constraints. The component will adjust initial widths to fit within these bounds and restrict resizing to the specified range.

Documents

Folder
--2024-06-01

README.md

Markdown
2.1 KB2024-06-02

package.json

JSON
1.8 KB2024-06-03

src

Folder
--2024-06-04

image.png

PNG Image
45.2 KB2024-06-05
import { ListViewTable } from '@gfazioli/mantine-list-view-table';
import { Badge, Text } from '@mantine/core';
import [ data, columns ] from './data';

function Demo() {
  return (
    <ListViewTable
      columns={columns}
      data={data}
      rowKey="id"
      withTableBorder
      withColumnBorders
      highlightOnHover
      enableColumnResizing
      onColumnResize={(columnKey, width) => {
        console.log(`Column '${columnKey}' resized to: ${width}px`);
      }}
    />
  );
}

Scroll Area Integration

The ListViewTable works seamlessly with Mantine's ScrollArea component. This is useful when you want to create a fixed-height table with scrollable content while maintaining the table's sticky header functionality.

When used inside a ScrollArea, the stickyHeader prop will make the table header stick to the top of the scroll area, providing a consistent user experience during scrolling.

Documents

Folder
--2024-06-01

README.md

Markdown
2.1 KB2024-06-02

package.json

JSON
1.8 KB2024-06-03

src

Folder
--2024-06-04

image.png

PNG Image
45.2 KB2024-06-05

video.mp4

Video
12.5 MB2024-06-06

archive.zip

ZIP Archive
3.4 MB2024-06-07

Downloads

Folder
--2024-06-08

notes.txt

Text File
1.2 KB2024-06-09
import { ListViewTable } from '@gfazioli/mantine-list-view-table';
import { Badge, ScrollArea, Text } from '@mantine/core';
import [ data, columns ] from './data';

function Demo() {
  return (
    <ScrollArea h={250}>
      <ListViewTable
        columns={columns}
        data={data}
        rowKey="id"
        stickyHeader
        onRowClick={(record) => {
          console.log('Clicked:', record.name);
        }}
      />
    </ScrollArea>
  );
}

Advanced Features

The ListViewTable component provides internal implementations for sorting, column reordering, and column resizing by default. However, developers can take full control over these features when needed for custom business logic or integration with external state management.

External Sorting Control

By default, the component handles sorting internally when you click on sortable column headers. However, you can override this behavior to implement custom sorting logic, integrate with external APIs, or manage sorting state in your application's state management system.

When you provide both sortStatus and onSort props, the component will use external sorting mode. You'll need to handle the data sorting logic yourself and update the sortStatus when the user clicks on column headers.

Documents

Folder
--2024-06-01

README.md

Markdown
2.1 KB2024-06-02

image.png

PNG Image
45.2 KB2024-06-05

package.json

JSON
1.8 KB2024-06-03

src

Folder
--2024-06-04
import { ListViewTable, ListViewTableSortStatus } from '@gfazioli/mantine-list-view-table';
import { Badge, Text } from '@mantine/core';
import React from 'react';
import [ data, columns ] from './data';

function Demo() {
  const [sortStatus, setSortStatus] = React.useState<ListViewTableSortStatus>({
    columnKey: 'name',
    direction: 'asc',
  });

  const sortedData = React.useMemo(() => {
    const sorted = [...data].sort((a, b) => {
      const aValue = a[sortStatus.columnKey as keyof typeof a];
      const bValue = b[sortStatus.columnKey as keyof typeof b];

      if (sortStatus.direction === 'desc') {
        return String(bValue).localeCompare(String(aValue));
      }
      return String(aValue).localeCompare(String(bValue));
    });
    return sorted;
  }, [sortStatus]);

  return (
    <ListViewTable
      columns={columns}
      data={sortedData}
      rowKey="id"
      withTableBorder
      highlightOnHover
      sortStatus={sortStatus}
      onSort={setSortStatus}
    />
  );
}

External Column Reordering and Resizing

Similarly, column reordering and resizing are handled internally by default. You can override these behaviors by providing onColumnReorder and onColumnResize callbacks. This is useful when you need to persist column configurations, sync with external state, or implement custom reordering logic.

The component will still provide the visual feedback and drag-and-drop functionality, but you'll have full control over how the state changes are handled.

Documents

Folder
--2024-06-01

README.md

Markdown
2.1 KB2024-06-02

package.json

JSON
1.8 KB2024-06-03

src

Folder
--2024-06-04

image.png

PNG Image
45.2 KB2024-06-05
import { ListViewTable, ListViewTableColumn } from '@gfazioli/mantine-list-view-table';
import { Badge, Text } from '@mantine/core';
import React from 'react';
import [ data, initialColumns ] from './data';

function Demo() {
  const [currentColumns, setCurrentColumns] = React.useState(initialColumns);

  const handleColumnReorder = (fromIndex: number, toIndex: number) => {
    const newColumns = [...currentColumns];
    const [movedColumn] = newColumns.splice(fromIndex, 1);
    newColumns.splice(toIndex, 0, movedColumn);
    setCurrentColumns(newColumns);
    console.log('Column reordered from', fromIndex, 'to', toIndex);
  };

  const handleColumnResize = (columnKey: string, width: number) => {
    console.log('Column resized:', columnKey, 'to width:', width);
  };

  return (
    <ListViewTable
      columns={currentColumns}
      data={data}
      rowKey="id"
      withTableBorder
      highlightOnHover
      enableColumnReordering
      enableColumnResizing
      onColumnReorder={handleColumnReorder}
      onColumnResize={handleColumnResize}
      onRowClick={(record) => {
        console.log('Clicked:', record.name);
      }}
    />
  );
}

Sticky Header

The stickyHeader prop enables the table header to remain fixed at the top of the viewport (or scroll container) when the user scrolls through the table content. This is particularly useful for long tables where you want to keep the column headers visible at all times.

The sticky header feature works both with the document scroll and when the table is used inside a ScrollArea. When enabled, the header will maintain its position and remain accessible during scrolling, improving the user experience by providing constant context about the data structure.

You can also use the stickyHeaderOffset prop to adjust the sticky header position when your page has a fixed navigation bar or header. This ensures the table header doesn't overlap with other fixed elements on the page.

Documents

Folder
--2024-06-01

README.md

Markdown
2.1 KB2024-06-02

package.json

JSON
1.8 KB2024-06-03

src

Folder
--2024-06-04

image.png

PNG Image
45.2 KB2024-06-05

video.mp4

Video
12.5 MB2024-06-06

archive.zip

ZIP Archive
3.4 MB2024-06-07

Downloads

Folder
--2024-06-08

notes.txt

Text File
1.2 KB2024-06-09

node_modules

Folder
--2024-06-10

dist

Folder
--2024-06-11

LICENSE

Text
1.1 KB2024-06-12

.gitignore

Text
0.5 KB2024-06-13

tsconfig.json

JSON
2.3 KB2024-06-14

vite.config.ts

TypeScript
1.9 KB2024-06-15

eslint.config.js

JavaScript
0.8 KB2024-06-16

yarn.lock

Lock File
456.7 KB2024-06-17

pnpm-lock.yaml

Lock File
234.1 KB2024-06-18

rollup.config.js

JavaScript
3.2 KB2024-06-19

jest.config.js

JavaScript
1.4 KB2024-06-20
import { ListViewTable } from '@gfazioli/mantine-list-view-table';
import { Badge, Text } from '@mantine/core';
import { data, columns } from './data';

function Demo() {
  return (
    <ListViewTable
      columns={columns}
      data={data}
      rowKey="id"
      withTableBorder
      withColumnBorders
      highlightOnHover
      stickyHeader
      stickyHeaderOffset={60}
      onRowClick={(record) => {
        console.log('Clicked:', record.name);
      }}
    />
  );
}

Table States

The ListViewTable component provides built-in support for common table states to enhance user experience during data loading and when no data is available.

Loading State

When data is being fetched or processed, you can show a loading indicator by setting the loading prop to true. This displays a spinner overlay while maintaining the table structure and headers.

import { ListViewTable } from '@gfazioli/mantine-list-view-table';
import { Badge, Text } from '@mantine/core';
import { columns } from './data';

function Demo() {
  return (
    <ListViewTable
      columns={columns}
      data={[]}
      rowKey="id"
      height={400}
      withTableBorder
      loading
    />
  );
}

Empty State

When no data is available to display, you can provide a custom empty state message using the emptyText prop. This gives users clear feedback when the table has no content to show.

No files found

import { ListViewTable } from '@gfazioli/mantine-list-view-table';
import { Badge, Text } from '@mantine/core';
import { columns } from './data';

function Demo() {
  return (
    <ListViewTable
      columns={columns}
      data={[]}
      rowKey="id"
      withTableBorder
      emptyText="No files found"
    />
  );
}

Vertical Variant

The ListViewTable component supports the variant="vertical" prop from Mantine Table component, which displays data in a key-value format where each row represents a property-value pair. This is particularly useful for displaying detailed information about a single item, such as configuration settings, user profiles, or metadata.

When using the vertical variant, consider setting layout="fixed" to ensure consistent column widths and a more structured appearance.

Epic name7.x migration
StatusOpen
Total issues135
Total story points874
Last updated atSeptember 26, 2024 17:41:26
import { ListViewTable } from '@gfazioli/mantine-list-view-table';
import { data, columns } from './data';

function Demo() {
  return (
    <ListViewTable
      columns={columns}
      data={data}
      rowKey={(row, i) => row.label + i}
      withTableBorder
      variant="vertical"
      layout="fixed"
    />
  );
}