Skip to content

Commit

Permalink
Merge pull request #355 from icflorescu/next
Browse files Browse the repository at this point in the history
Fix #354 - context menu not working inside modal
  • Loading branch information
icflorescu authored Jun 29, 2023
2 parents c1cdb20 + 4a88d49 commit eed129f
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 55 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 2.7.1 (2023-06-29)

- Fix row context menu not showing properly when used on tables inside modals (see [#354](https://github.com/icflorescu/mantine-datatable/issues/354))

## 2.7.0 (2023-06-28)

- Add `defaultColumnProps` (see [#340](https://github.com/icflorescu/mantine-datatable/issues/340))
Expand Down
73 changes: 65 additions & 8 deletions docs/examples/RowContextMenuExamples.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Button } from '@mantine/core';
import { modals } from '@mantine/modals';
import { showNotification } from '@mantine/notifications';
import { IconEdit, IconSend, IconTrash, IconX } from '@tabler/icons-react';
import { IconAppWindow, IconEdit, IconSend, IconTrash, IconX } from '@tabler/icons-react';
import { DataTable } from 'mantine-datatable';
import companies from '~/data/companies.json';

Expand Down Expand Up @@ -116,7 +118,7 @@ export function RowContextMenuExample4() {
columns={[{ accessor: 'name' }, { accessor: 'streetAddress' }, { accessor: 'city' }, { accessor: 'state' }]}
records={companies}
rowContextMenu={{
// hide the context menu for the 1st row
// 👇 hide the context menu for the 1st row
hidden: (record) => companies.indexOf(record) === 0,
items: (record) => [
// example-skip
Expand Down Expand Up @@ -202,7 +204,7 @@ export function RowContextMenuExample6() {
{
key: 'delete',
color: 'red',
// hide this item for the 1st row
// 👇 hide this item for the 1st row
hidden: companies.indexOf(record) === 0,
title: `Delete company ${record.name}`,
onClick: () => showNotification({ color: 'red', message: `Should delete company ${record.name}` }),
Expand Down Expand Up @@ -278,7 +280,7 @@ export function RowContextMenuExample8() {
{
key: 'delete',
color: 'red',
// set a specific icon for the 1st row
// 👇 set a specific icon for the 1st row
icon: companies.indexOf(record) === 0 ? <IconX size={16} /> : <IconTrash size={16} />,
title: `Delete company ${record.name}`,
onClick: () => showNotification({ color: 'red', message: `Should delete company ${record.name}` }),
Expand Down Expand Up @@ -318,7 +320,7 @@ export function RowContextMenuExample9() {
// example-resume
{
key: 'delete',
// set a specific color for the 1st row
// 👇 set a specific color for the 1st row
color: companies.indexOf(record) === 0 ? 'orange' : 'red',
icon: <IconTrash size={16} />,
title: `Delete company ${record.name}`,
Expand Down Expand Up @@ -349,8 +351,8 @@ export function RowContextMenuExample10() {
columns={[{ accessor: 'name' }, { accessor: 'streetAddress' }, { accessor: 'city' }, { accessor: 'state' }]}
records={companies}
rowContextMenu={{
shadow: 'xl', // custom shadow
borderRadius: 'md', // custom border radius
shadow: 'xl', // 👈 custom shadow
borderRadius: 'md', // 👈 custom border radius
items: (record) => [
{
key: 'edit',
Expand All @@ -361,7 +363,7 @@ export function RowContextMenuExample10() {
color: 'red',
onClick: () => showNotification({ color: 'red', message: `Should delete company ${record.name}` }),
},
// add a divider between `delete` and `sendMessage` items
// 👇 add a divider between `delete` and `sendMessage` items
{ key: 'divider1', divider: true },
{
key: 'sendMessage',
Expand All @@ -375,3 +377,58 @@ export function RowContextMenuExample10() {
// example-end
);
}

export function RowContextMenuExampleInsideModal() {
return (
// example-start inside-modal
<Button
leftIcon={<IconAppWindow size={16} />}
onClick={() =>
modals.open({
title: 'Right-click on a row',
children: (
<DataTable
height={300}
withBorder
borderRadius="sm"
columns={[
{ accessor: 'name', title: 'Company name' },
{ accessor: 'city', textAlignment: 'right' },
]}
records={companies}
rowContextMenu={{
zIndex: 202, // 👈 make sure the context menu is above the modal
// example-skip items
items: (record) => [
{
key: 'edit',
icon: <IconEdit size={16} />,
onClick: () => showNotification({ message: `Should edit company ${record.name}` }),
},
{
key: 'delete',
icon: <IconTrash size={16} />,
color: 'red',
onClick: () => showNotification({ color: 'red', message: `Should delete company ${record.name}` }),
},
{ key: 'divider', divider: true },
{
key: 'sendMessage',
icon: <IconSend size={16} />,
onClick: () => {
showNotification({ message: 'Should send a message to this company' });
},
},
],
}}
// example-resume
/>
),
})
}
>
Open modal
</Button>
// example-end
);
}
4 changes: 2 additions & 2 deletions docs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mantine-datatable-docs",
"version": "2.7.0",
"version": "2.7.1",
"description": "Docs website for mantine-datatable; see ../package/package.json for more info",
"private": true,
"scripts": {
Expand Down Expand Up @@ -38,6 +38,6 @@
"@types/node": "^20.3.2",
"@types/react": "^18.2.14",
"mixpanel-browser": "^2.47.0",
"typescript": "^5.1.5"
"typescript": "^5.1.6"
}
}
20 changes: 14 additions & 6 deletions docs/pages/examples/row-context-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import CodeBlock from '~/components/CodeBlock';
import ExternalLink from '~/components/ExternalLink';
import InternalLink from '~/components/InternalLink';
import PageNavigation from '~/components/PageNavigation';
import PageSubtitle from '~/components/PageSubtitle';
import PageText from '~/components/PageText';
import PageTitle from '~/components/PageTitle';
import { MANTINE_CONTEXTMENU_LINK } from '~/config';
Expand All @@ -19,6 +20,7 @@ import {
RowContextMenuExample7,
RowContextMenuExample8,
RowContextMenuExample9,
RowContextMenuExampleInsideModal,
} from '~/examples/RowContextMenuExamples';
import readCodeExample from '~/lib/readCodeExample';

Expand Down Expand Up @@ -99,12 +101,10 @@ export default function Page({ code }: InferGetStaticPropsType<typeof getStaticP
<CodeBlock language="typescript" content={code[example]} />
<PageText info>
When using a row context menu triggered by click instead of right-click, you might want to{' '}
<InternalLink to="/examples/disabling-text-selection">disable text selection</InternalLink>.
</PageText>
<PageText info>
If you need to combine context menus triggered by <Code>click</Code> instead of <Code>right-click</Code> with
links, buttons, <InternalLink to="/examples/row-actions-cell">row action cells</InternalLink> or any kind of
clickable components inside cells, make sure to intercept the <Code>click</Code> event on those components and{' '}
<InternalLink to="/examples/disabling-text-selection">disable text selection</InternalLink>. If you need to
combine context menus triggered by <Code>click</Code> instead of <Code>right-click</Code> with links, buttons,{' '}
<InternalLink to="/examples/row-actions-cell">row action cells</InternalLink> or any kind of clickable
components inside cells, make sure to intercept the <Code>click</Code> event on those components and{' '}
<ExternalLink to="https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation">
invoke its <Code>.stopPropagation()</Code> method
</ExternalLink>
Expand All @@ -117,6 +117,14 @@ export default function Page({ code }: InferGetStaticPropsType<typeof getStaticP
If you’re interested in using context menus in other places in your application’s UI, have a look at{' '}
<ExternalLink to={MANTINE_CONTEXTMENU_LINK}>Mantine ContextMenu</ExternalLink>.
</PageText>
<PageSubtitle value="Using row context menus inside modals" />
<PageText>
When using row context menus on data tables inside modals, you need to make sure that the context menu is
rendered above the modal. To do so, you need to set its <Code>zIndex</Code> property to a value higher than the
modal’s <Code>zIndex</Code>:
</PageText>
<RowContextMenuExampleInsideModal />
<CodeBlock language="typescript" content={code['inside-modal']} />
<PageText>
If you’re not a fan of context menus,{' '}
<InternalLink to="/examples/row-actions-cell">implementing a row actions cell</InternalLink> should’t be
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-turborepo",
"version": "2.7.0",
"version": "2.7.1",
"description": "This is a monorepo; see package/package.json for more info",
"private": true,
"workspaces": [
Expand Down Expand Up @@ -37,7 +37,7 @@
"jest-environment-jsdom": "^29.5.0",
"prettier": "^2.8.8",
"turbo": "^1.10.6",
"typescript": "^5.1.5"
"typescript": "^5.1.6"
},
"engines": {
"npm": ">=9.5.1",
Expand Down
62 changes: 32 additions & 30 deletions package/DataTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, MantineSize, Table, createStyles, packSx, type MantineTheme } from '@mantine/core';
import { Box, MantineSize, Portal, Table, createStyles, packSx, type MantineTheme } from '@mantine/core';
import { useElementSize, useMergedRef } from '@mantine/hooks';
import {
useCallback,
Expand Down Expand Up @@ -472,7 +472,7 @@ export default function DataTable<T>({
<DataTableEmptyRow />
)}
</tbody>
{effectiveColumns.some((column) => column.footer) && (
{effectiveColumns.some(({ footer }) => footer) && (
<DataTableFooter<T>
ref={footerRef}
className={classNames?.footer}
Expand Down Expand Up @@ -532,34 +532,36 @@ export default function DataTable<T>({
{emptyState}
</DataTableEmptyState>
{rowContextMenu && rowContextMenuInfo && (
<DataTableRowMenu
zIndex={rowContextMenu.zIndex}
borderRadius={rowContextMenu.borderRadius}
shadow={rowContextMenu.shadow}
y={rowContextMenuInfo.y}
x={rowContextMenuInfo.x}
onDestroy={() => setRowContextMenuInfo(null)}
>
{rowContextMenu
.items(rowContextMenuInfo.record, rowContextMenuInfo.recordIndex)
.map(({ divider, key, title, icon, color, hidden, disabled, onClick }) =>
divider ? (
<DataTableRowMenuDivider key={key} />
) : hidden ? null : (
<DataTableRowMenuItem
key={key}
title={title ?? humanize(key)}
icon={icon}
color={color}
disabled={disabled}
onClick={() => {
setRowContextMenuInfo(null);
onClick();
}}
/>
)
)}
</DataTableRowMenu>
<Portal>
<DataTableRowMenu
zIndex={rowContextMenu.zIndex}
borderRadius={rowContextMenu.borderRadius}
shadow={rowContextMenu.shadow}
y={rowContextMenuInfo.y}
x={rowContextMenuInfo.x}
onDestroy={() => setRowContextMenuInfo(null)}
>
{rowContextMenu
.items(rowContextMenuInfo.record, rowContextMenuInfo.recordIndex)
.map(({ divider, key, title, icon, color, hidden, disabled, onClick }) =>
divider ? (
<DataTableRowMenuDivider key={key} />
) : hidden ? null : (
<DataTableRowMenuItem
key={key}
title={title ?? humanize(key)}
icon={icon}
color={color}
disabled={disabled}
onClick={() => {
setRowContextMenuInfo(null);
onClick();
}}
/>
)
)}
</DataTableRowMenu>
</Portal>
)}
</Box>
);
Expand Down
3 changes: 2 additions & 1 deletion package/DataTableRowMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createStyles, Paper, px, type MantineNumberSize, type MantineShadow } from '@mantine/core';
import type { MantineNumberSize, MantineShadow } from '@mantine/core';
import { Paper, createStyles, px } from '@mantine/core';
import { useClickOutside, useElementSize, useMergedRef, useWindowEvent } from '@mantine/hooks';
import type { ReactNode } from 'react';

Expand Down
4 changes: 2 additions & 2 deletions package/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mantine-datatable",
"version": "2.7.0",
"version": "2.7.1",
"description": "The dependency-free datatable component for Mantine UI, featuring asynchronous data loading support, pagination, multple rows selection, column sorting, custom cell data rendering, row context menu, row expansion and more",
"keywords": [
"mantine",
Expand Down Expand Up @@ -63,7 +63,7 @@
"@types/react-dom": "^18.2.6",
"esbuild": "^0.18.10",
"react": "^18.2.0",
"typescript": "^5.1.5"
"typescript": "^5.1.6"
},
"peerDependencies": {
"@mantine/core": ">=6",
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6776,10 +6776,10 @@ typed-array-length@^1.0.4:
for-each "^0.3.3"
is-typed-array "^1.1.9"

typescript@^5.1.5:
version "5.1.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.5.tgz#a3ae755082488b6046fe64345d293ef26af08671"
integrity sha512-FOH+WN/DQjUvN6WgW+c4Ml3yi0PH+a/8q+kNIfRehv1wLhWONedw85iu+vQ39Wp49IzTJEsZ2lyLXpBF7mkF1g==
typescript@^5.1.6:
version "5.1.6"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274"
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==

unbox-primitive@^1.0.2:
version "1.0.2"
Expand Down

0 comments on commit eed129f

Please sign in to comment.