Skip to content

Commit

Permalink
Merge pull request #460 from icflorescu/next
Browse files Browse the repository at this point in the history
Implement pinning the last column feature
  • Loading branch information
icflorescu authored Nov 7, 2023
2 parents c60dde9 + 3713fe1 commit e5695a1
Show file tree
Hide file tree
Showing 24 changed files with 390 additions and 151 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
The following is a list of notable changes to the Mantine DataTable component.
Minor versions that are not listed in the changelog are bug fixes and small improvements.

## 7.1.3 (2023-11-07)

- Implement `pinLastColumn` feature
- Add missing `package.json` fields (`main` and `module`)

## 7.1.2 (2023-11-06)

- Switch to `tsup` building, to fix usage issues with Remix & Next.js
Expand Down
5 changes: 5 additions & 0 deletions app/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ export const ROUTES: RouteInfo[] = [
title: 'Row actions cell',
description: `Example: how to implement a row actions cell on ${PRODUCT_NAME}`,
},
{
href: '/examples/pinning-the-last-column',
title: 'Pinning the last column',
description: `Example: how to pin the last column on ${PRODUCT_NAME}`,
},
{
href: '/examples/links-or-buttons-inside-clickable-rows-or-cells',
title: 'Links or buttons inside clickable rows or cells',
Expand Down
19 changes: 14 additions & 5 deletions app/examples/complex-usage-scenario/ComplexUsageExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,30 +173,38 @@ export function ComplexUsageExample() {
const columns: DataTableProps<Employee>['columns'] = [
{
accessor: 'name',
width: 150,
ellipsis: true,
noWrap: true,
sortable: true,
render: ({ firstName, lastName }) => `${firstName} ${lastName}`,
},
{
accessor: 'email',
sortable: true,
visibleMediaQuery: aboveXs,
},
{
accessor: 'department.company.name',
title: 'Company',
width: 150,
noWrap: true,
sortable: true,
visibleMediaQuery: aboveXs,
},
{
accessor: 'department.name',
title: 'Department',
width: 130,
sortable: true,
visibleMediaQuery: aboveXs,
},
{
accessor: 'department.company.city',
title: 'City',
noWrap: true,
visibleMediaQuery: aboveXs,
},
{
accessor: 'department.company.state',
title: 'State',
visibleMediaQuery: aboveXs,
},
{
accessor: 'age',
width: 80,
Expand Down Expand Up @@ -226,6 +234,7 @@ export function ComplexUsageExample() {
withColumnBorders
striped
verticalAlign="top"
pinLastColumn
columns={columns}
fetching={isFetching}
records={data?.employees}
Expand Down
14 changes: 11 additions & 3 deletions app/examples/complex-usage-scenario/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Route } from 'next';
import { PRODUCT_NAME } from '~/app/config';
import { CodeBlock } from '~/components/CodeBlock';
import { ExternalLink } from '~/components/ExternalLink';
import { InternalLink } from '~/components/InternalLink';
import { PageNavigation } from '~/components/PageNavigation';
import { PageTitle } from '~/components/PageTitle';
import { Txt } from '~/components/Txt';
Expand All @@ -28,9 +29,16 @@ export default async function ComplexUsageExamplePage() {
<>
<PageTitle of={PATH} />
<Txt>
Here is a complex usage scenario featuring custom column definitions, asynchronous data loading with{' '}
<ExternalLink to="https://tanstack.com/query/latest">TanStack React Query</ExternalLink>, sorting, pagination,
custom cell data rendering, multiple row selection, row expansion, action cells, and row context-menu.
Here is a complex usage scenario featuring{' '}
<InternalLink to="/examples/column-properties-and-styling">custom column definitions</InternalLink>,{' '}
<InternalLink to="/examples/asynchronous-data-loading">asynchronous data loading</InternalLink> with{' '}
<ExternalLink to="https://tanstack.com/query/latest">TanStack React Query</ExternalLink>,{' '}
<InternalLink to="/examples/sorting">sorting</InternalLink>,{' '}
<InternalLink to="/examples/pagination">pagination</InternalLink>, custom cell data rendering,{' '}
<InternalLink to="/examples/records-selection">multiple row selection</InternalLink>,{' '}
<InternalLink to="/examples/expanding-rows">row expansion</InternalLink>,{' '}
<InternalLink to="/examples/row-actions-cell">action cells</InternalLink>, and{' '}
<InternalLink to="/examples/using-with-mantine-contextmenu">row context-menu</InternalLink>.
</Txt>
<ComplexUsageExampleWrapper>
<ComplexUsageExample />
Expand Down
98 changes: 98 additions & 0 deletions app/examples/pinning-the-last-column/PinLastColumnExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
'use client';

import { ActionIcon, Box, Button, Grid, GridCol, Group, Stack, Text } from '@mantine/core';
import { closeModal, openModal } from '@mantine/modals';
import { IconEdit, IconEye, IconTrash } from '@tabler/icons-react';
import { DataTable } from '__PACKAGE__';
import { employees, type Employee } from '~/data';

const records = employees.slice(0, 5);

const showModal = ({ employee, action }: { employee: Employee; action: 'view' | 'edit' | 'delete' }) => {
openModal({
modalId: action,
title:
action === 'view'
? 'Showing company information'
: action === 'edit'
? 'Editing company information'
: 'Deleting company',
children: (
<Stack>
<Text>
{action === 'view'
? 'Here’s where you could show more information...'
: action === 'edit'
? 'Here’s where you could put an edit form...'
: 'Here’s where you could ask for confirmation before deleting...'}
</Text>
<Grid gutter="xs">
<GridCol span={2}>ID</GridCol>
<GridCol span={10}>{employee.id}</GridCol>
<GridCol span={2}>First name</GridCol>
<GridCol span={10}>{employee.firstName}</GridCol>
<GridCol span={2}>Last name</GridCol>
<GridCol span={10}>{employee.lastName}</GridCol>
</Grid>
<Button onClick={() => closeModal(action)}>Close</Button>
</Stack>
),
});
};

export function PinLastColumnExample() {
// example-start
return (
<DataTable
pinLastColumn // 👈 make sure the last column is always visible
withTableBorder
columns={[
{ accessor: 'firstName', noWrap: true },
{ accessor: 'lastNameName', noWrap: true },
{ accessor: 'department.name', title: 'Department' },
{ accessor: 'department.company.name', title: 'Company', noWrap: true },
{ accessor: 'department.company.city', title: 'City', noWrap: true },
{ accessor: 'department.company.state', title: 'State' },
{ accessor: 'department.company.streetAddress', title: 'Address', noWrap: true },
{ accessor: 'department.company.missionStatement', title: 'Mission statement', noWrap: true },
{
accessor: 'actions',
title: <Box mr={6}>Row actions</Box>,
textAlign: 'right',
render: (employee) => (
// example-skip action cells custom rendering
<Group gap={4} justify="right" wrap="nowrap">
<ActionIcon
size="sm"
variant="subtle"
color="green"
onClick={() => showModal({ employee, action: 'view' })}
>
<IconEye size={16} />
</ActionIcon>
<ActionIcon
size="sm"
variant="subtle"
color="blue"
onClick={() => showModal({ employee, action: 'edit' })}
>
<IconEdit size={16} />
</ActionIcon>
<ActionIcon
size="sm"
variant="subtle"
color="red"
onClick={() => showModal({ employee, action: 'delete' })}
>
<IconTrash size={16} />
</ActionIcon>
</Group>
// example-resume
),
},
]}
records={records}
/>
);
// example-end
}
49 changes: 49 additions & 0 deletions app/examples/pinning-the-last-column/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Code } from '@mantine/core';
import type { Route } from 'next';
import { CodeBlock } from '~/components/CodeBlock';
import { InternalLink } from '~/components/InternalLink';
import { PageNavigation } from '~/components/PageNavigation';
import { PageTitle } from '~/components/PageTitle';
import { Txt } from '~/components/Txt';
import { readCodeFile } from '~/lib/code';
import { getRouteMetadata } from '~/lib/utils';
import { PinLastColumnExample } from './PinLastColumnExample';

const PATH: Route = '/examples/pinning-the-last-column';

export const metadata = getRouteMetadata(PATH);

export default async function PinLastColumnExamplePage() {
const code = await readCodeFile<string>(`${PATH}/PinLastColumnExample.tsx`);

return (
<>
<PageTitle of={PATH} />
<Code hidden>fix, fixed, affix, sticky</Code>
<Txt>
You may have noticed that when you are using{' '}
<InternalLink to="/examples/records-selection">row selection</InternalLink> and the table needs to scroll
horizontally, the checkbox column is always visible. This is because the checkbox column is pinned to the left
side of the table.
</Txt>
<Txt>
In the same way, pinning the last column to the right side of the table could be useful when you have a table
with many columns and you want to make sure the last column is always visible, even when the table is scrolled
horizontally. For instance, you could use this feature to ensure that the{' '}
<InternalLink to="/examples/row-actions-cell">row actions</InternalLink> are always visible.
</Txt>
<Txt>
You can achieve this by setting the <Code>pinLastColumn</Code> DataTable prop to <Code>true</Code>:
</Txt>
<PinLastColumnExample />
<Txt>Here is the code:</Txt>
<CodeBlock code={code} />
<Txt warning title="Warning">
Combining this feature with <InternalLink to="/examples/column-grouping">column grouping</InternalLink> may lead
to minor visual artifacts.
</Txt>
<Txt>Head over to the next example to discover more features.</Txt>
<PageNavigation of={PATH} />
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
'use client';
// 👆 Since 'useContextMenu' is a hook, don't forget to add the 'use client' directive
// at the top of your file if you're using it in a RSC context

import { useMediaQuery } from '@mantine/hooks';
import { showNotification } from '@mantine/notifications';
Expand Down
5 changes: 5 additions & 0 deletions components/PackageUsers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ const USERS = [
logo: { base: 'markup', ext: 'png', themed: true, scale: 72 },
link: 'https://www.getmarkup.com',
},
{
name: 'InvenTree',
logo: { base: 'inventree', ext: 'png', themed: true, scale: 140, shift: 1 },
link: 'https://inventree.org',
},
{
name: 'BookieBase',
logo: { base: 'bookiebase', ext: 'svg', themed: true, scale: 72, shift: 2 },
Expand Down
36 changes: 19 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mantine-datatable",
"version": "7.1.2",
"version": "7.1.3",
"description": "The lightweight, dependency-free, dark-theme aware table component for your Mantine UI data-rich applications, featuring asynchronous data loading support, pagination, intuitive Gmail-style additive batch rows selection, column sorting, custom cell data rendering, row expansion, nesting, context menus, and much more",
"keywords": [
"mantine",
Expand Down Expand Up @@ -40,6 +40,13 @@
"type": "github",
"url": "https://github.com/sponsors/icflorescu"
},
"files": [
"./dist",
"./README.md",
"./LICENSE"
],
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
Expand All @@ -55,11 +62,6 @@
"./styles.css": "./dist/styles.css",
"./styles.layer.css": "./dist/styles.layer.css"
},
"files": [
"./dist",
"./README.md",
"./LICENSE"
],
"scripts": {
"dev": "next dev",
"build:package": "rm -rf dist; tsup --config scripts/tsup.esm.ts; tsup --config scripts/tsup.cjs.ts; tsup --config scripts/tsup.dts.ts; postcss package/styles*.css --dir dist",
Expand All @@ -72,29 +74,29 @@
"@docsearch/react": "^3.5.2",
"@ducanh2912/next-pwa": "^9.7.2",
"@faker-js/faker": "^8.2.0",
"@formkit/auto-animate": "^0.8.0",
"@mantine/code-highlight": "^7.1.7",
"@mantine/core": "^7.1.7",
"@mantine/dates": "^7.1.7",
"@mantine/hooks": "^7.1.7",
"@mantine/modals": "^7.1.7",
"@mantine/notifications": "^7.1.7",
"@formkit/auto-animate": "^0.8.1",
"@mantine/code-highlight": "^7.2.0",
"@mantine/core": "^7.2.0",
"@mantine/dates": "^7.2.0",
"@mantine/hooks": "^7.2.0",
"@mantine/modals": "^7.2.0",
"@mantine/notifications": "^7.2.0",
"@tabler/icons-react": "^2.40.0",
"@tanstack/react-query": "^5.7.2",
"@types/lodash": "^4.14.200",
"@types/node": "^20.8.10",
"@types/react": "^18.2.36",
"@types/react-dom": "^18.2.14",
"@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.9.1",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"clsx": "^2.0.0",
"cssnano": "^6.0.1",
"dayjs": "^1.11.10",
"eslint": "^8.53.0",
"eslint-config-next": "^14.0.1",
"eslint-config-prettier": "^9.0.0",
"lodash": "^4.17.21",
"mantine-contextmenu": "^7.1.9",
"mantine-contextmenu": "^7.1.10",
"next": "14.0.1",
"postcss": "^8.4.31",
"postcss-cli": "^10.1.0",
Expand All @@ -114,6 +116,6 @@
"@mantine/core": ">=7",
"@mantine/hooks": ">=7",
"clsx": ">=2",
"react": ">=18"
"react": ">=18.2"
}
}
Loading

0 comments on commit e5695a1

Please sign in to comment.