Skip to content

Commit

Permalink
Merge pull request #529 from icflorescu/next
Browse files Browse the repository at this point in the history
Improve column-pinning styling
  • Loading branch information
icflorescu authored Jan 21, 2024
2 parents a493225 + c4d1351 commit 2997ecf
Show file tree
Hide file tree
Showing 9 changed files with 334 additions and 96 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
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.4.6 (2024-01-21)

- Improve first and last column pinning CSS to allow combining the feature with column groups
- Improve last column pinning CSS to fix a minor glitch in webkit browsers
- A few documentation improvements

## 7.4.5 (2024-01-20)

- Improve column toggling UX & code efficiency
Expand Down
3 changes: 1 addition & 2 deletions app/examples/basic-usage/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ export default async function BasicUsageExamplePage() {
<PageTitle of={PATH} />
<Txt>
In its most basic usage scenario, the DataTable component only requires <Code>records</Code> and{' '}
<Code>columns</Code>
properties to be set:
<Code>columns</Code> properties to be set:
</Txt>
<CodeBlock tabs={{ code, keys: ['BasicUsageExample.tsx', 'companies.json'] }} />
<Txt>The code above will produce the following result:</Txt>
Expand Down
104 changes: 104 additions & 0 deletions app/examples/pinning-the-first-column/PinFirstColumnExamples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,107 @@ export function PinFirstAndLastColumnsExampleWithRecordSelection() {
);
// example-end
}

export function PinFirstColumnExampleWithColumnGroups() {
const [selectedRecord, setSelectedRecord] = useState<Employee[]>([]);

// example-start with-column-groups
return (
<DataTable
withTableBorder
withColumnBorders
pinFirstColumn
pinLastColumn
groups={[
{
id: 'name',
title: '', // 👈 empty title
style: { borderBottomColor: 'transparent' }, // 👈 hide the bottom border
columns: [
{
accessor: 'name',
title: (
// 👇 use an absolutely positioned custom title component
// to center the title vertically
<Text inherit pos="absolute" mt={-28}>
Name
</Text>
),
noWrap: true,
render: ({ firstName, lastName }) => `${firstName} ${lastName}`,
},
],
},
// example-skip other column groups
{
id: 'workplaceInformation',
columns: [
{ accessor: 'department.company.name', title: 'Company', noWrap: true },
{ accessor: 'department.name', title: 'Department' },
{ accessor: 'department.company.missionStatement', title: 'Mission statement', noWrap: true },
],
},
{
id: 'workplaceLocation',
columns: [
{ accessor: 'department.company.city', title: 'City', noWrap: true },
{ accessor: 'department.company.state', title: 'State' },
{ accessor: 'department.company.streetAddress', title: 'Address', noWrap: true },
],
},
{
id: 'actions',
title: '', // 👈 empty title
style: { borderBottomColor: 'transparent' }, // 👈 hide the bottom border
columns: [
{
accessor: 'actions',
title: (
// 👇 use an absolutely positioned custom title component
// to center the title vertically
<Text inherit pos="absolute" mt={-28} ml={12}>
Actions
</Text>
),
render: (employee) => (
<Group gap={4} 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
},
]}
// example-skip other table props
records={records}
selectedRecords={selectedRecord}
onSelectedRecordsChange={setSelectedRecord}
// example-resume
/>
);
// example-end
}
22 changes: 18 additions & 4 deletions app/examples/pinning-the-first-column/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import type { Route } from 'next';
import { CodeBlock } from '~/components/CodeBlock';
import { InternalLink } from '~/components/InternalLink';
import { PageNavigation } from '~/components/PageNavigation';
import { PageSubtitle } from '~/components/PageSubtitle';
import { PageTitle } from '~/components/PageTitle';
import { Txt } from '~/components/Txt';
import { readCodeFile } from '~/lib/code';
import { getRouteMetadata } from '~/lib/utils';
import {
PinFirstAndLastColumnsExampleWithRecordSelection,
PinFirstColumnExampleWithColumnGroups,
PinFirstColumnExampleWithoutRecordSelection,
PinFirstColumnExampleWithRecordSelection,
} from './PinFirstColumnExamples';
Expand All @@ -19,7 +21,10 @@ export const metadata = getRouteMetadata(PATH);

export default async function PinFirstColumnExamplePage() {
const code = await readCodeFile<
Record<'without-record-selection' | 'with-record-selection' | 'first-last-and-record-selection', string>
Record<
'without-record-selection' | 'with-record-selection' | 'first-last-and-record-selection' | 'with-column-groups',
string
>
>(`${PATH}/PinFirstColumnExamples.tsx`);

return (
Expand Down Expand Up @@ -54,10 +59,19 @@ export default async function PinFirstColumnExamplePage() {
<PinFirstAndLastColumnsExampleWithRecordSelection />
<Txt>Here is the code:</Txt>
<CodeBlock code={code['first-last-and-record-selection']} />
<Txt warning title="Warning">
Combining this feature with <InternalLink to="/examples/column-grouping">column grouping</InternalLink> may lead
to minor visual artifacts.
<PageSubtitle value="Using with column grouping" />
<Txt warning title="Warning!">
When using this feature with <InternalLink to="/examples/column-grouping">column grouping</InternalLink>, you
need to <strong>make sure that the first group contains only one column</strong>.
</Txt>
<Txt>
Here is an example of how you can pin the first column when using column grouping. Notice how the first group
contains only one column, and how we are using an absolutely positioned custom title component to create the
illusion that the <em>Name</em> text is centered vertically:
</Txt>
<PinFirstColumnExampleWithColumnGroups />
<Txt>Here is the code:</Txt>
<CodeBlock code={code['with-column-groups']} />
<Txt>Head over to the next example to discover more features.</Txt>
<PageNavigation of={PATH} />
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const showModal = ({ employee, action }: { employee: Employee; action: 'view' |
export function PinLastColumnExample() {
const [selectedRecord, setSelectedRecord] = useState<Employee[]>([]);

// example-start
// example-start default
return (
<DataTable
pinLastColumn // 👈 make sure the last column is always visible
Expand Down Expand Up @@ -101,3 +101,96 @@ export function PinLastColumnExample() {
);
// example-end
}

export function PinLastColumnExampleWithColumnGroups() {
const [selectedRecord, setSelectedRecord] = useState<Employee[]>([]);

// example-start with-column-groups
return (
<DataTable
withTableBorder
withColumnBorders
pinLastColumn
groups={[
// example-skip other column groups
{
id: 'name',
columns: [
{ accessor: 'firstName', noWrap: true },
{ accessor: 'lastName', noWrap: true },
],
},
{
id: 'workplaceInformation',
columns: [
{ accessor: 'department.company.name', title: 'Company', noWrap: true },
{ accessor: 'department.name', title: 'Department' },
{ accessor: 'department.company.missionStatement', title: 'Mission statement', noWrap: true },
],
},
{
id: 'workplaceLocation',
columns: [
{ accessor: 'department.company.city', title: 'City', noWrap: true },
{ accessor: 'department.company.state', title: 'State' },
{ accessor: 'department.company.streetAddress', title: 'Address', noWrap: true },
],
},
// example-resume
// 👇 this group has only one column, so it will be pinned to the right side of the table
{
id: 'actions',
title: '', // 👈 empty title
style: { borderBottomColor: 'transparent' }, // 👈 hide the group bottom border
columns: [
{
accessor: 'actions',
title: (
// 👇 use an absolutely positioned custom title component
// to center the title vertically
<Text inherit pos="absolute" mt={-28} ml={12}>
Actions
</Text>
),
render: (employee) => (
<Group gap={4} 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
},
]}
// example-skip other table props
records={records}
selectedRecords={selectedRecord}
onSelectedRecordsChange={setSelectedRecord}
// example-resume
/>
);
// example-end
}
24 changes: 18 additions & 6 deletions app/examples/pinning-the-last-column/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ import type { Route } from 'next';
import { CodeBlock } from '~/components/CodeBlock';
import { InternalLink } from '~/components/InternalLink';
import { PageNavigation } from '~/components/PageNavigation';
import { PageSubtitle } from '~/components/PageSubtitle';
import { PageTitle } from '~/components/PageTitle';
import { Txt } from '~/components/Txt';
import { readCodeFile } from '~/lib/code';
import { getRouteMetadata } from '~/lib/utils';
import { PinLastColumnExample } from './PinLastColumnExample';
import { PinLastColumnExample, PinLastColumnExampleWithColumnGroups } from './PinLastColumnExamples';

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`);
const code = await readCodeFile<Record<'default' | 'with-column-groups', string>>(
`${PATH}/PinLastColumnExamples.tsx`
);

return (
<>
Expand All @@ -37,11 +40,20 @@ export default async function PinLastColumnExamplePage() {
</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.
<CodeBlock code={code['default']} />
<PageSubtitle value="Using with column grouping" />
<Txt warning title="Warning!">
When using this feature with <InternalLink to="/examples/column-grouping">column grouping</InternalLink>, you
need to <strong>make sure that the last group contains only one column</strong>.
</Txt>
<Txt>
Here is an example of how you can pin the last column when using column grouping. Notice how the last group
contains only one column, and how we are using an absolutely positioned custom title component to create the
illusion that the <em>Actions</em> text is centered vertically:
</Txt>
<PinLastColumnExampleWithColumnGroups />
<Txt>Here is the code:</Txt>
<CodeBlock code={code['with-column-groups']} />
<Txt>
Head over to the next example to discover how you can pin the <strong>first</strong> column to the{' '}
<strong>left</strong> side of the table.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mantine-datatable",
"version": "7.4.5",
"version": "7.4.6",
"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 @@ -63,7 +63,7 @@
"./styles.layer.css": "./dist/styles.layer.css"
},
"scripts": {
"dev": "next dev --turbo",
"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",
"build:docs": "next build",
"build": "yarn build:package && yarn build:docs",
Expand Down
Loading

0 comments on commit 2997ecf

Please sign in to comment.