Skip to content

Commit

Permalink
Merge pull request #149 from icflorescu/next
Browse files Browse the repository at this point in the history
Next
  • Loading branch information
icflorescu authored Feb 28, 2024
2 parents 2f52a45 + 695a225 commit ab315d3
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
The following is a list of notable changes to the Mantine ContextMenu component.
Minor versions that are not listed in the changelog are minor bug fixes and small internal improvements or refactorings.

## 7.6.1 (2024-02-28)

- Implement `iconRight` property (see [#147](https://github.com/icflorescu/mantine-contextmenu/pull/147) by [@JTson8](https://github.com/JTson8))

## 7.6.0 (2024-02-28)

- Update dev dependencies to ensure compatibility with Mantine 7.6.0
Expand Down
19 changes: 17 additions & 2 deletions app/examples/action-icons/ActionIconsExample.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { IconCopy, IconDownload } from '@tabler/icons-react';
import { notifications } from '@mantine/notifications';
import { IconCopy, IconDownload, IconExclamationCircle, IconTrash } from '@tabler/icons-react';
import { useContextMenu } from '__PACKAGE__';
import { Picture } from '~/components/Picture';
import { copyImageToClipboard, downloadImage, unsplashImages } from '~/lib/images';
Expand All @@ -11,6 +12,14 @@ export function ActionIconsExample() {
// example-skip
const image = unsplashImages[4];
const { src } = image.file;

const handleDelete = () => {
notifications.show({
color: 'red',
title: 'Can’t do that',
message: 'You know you can’t delete an image from the Internet, right?',
});
};
// example-resume
return (
<Picture
Expand All @@ -23,9 +32,15 @@ export function ActionIconsExample() {
},
{
key: 'download',
icon: <IconDownload size={16} />,
iconRight: <IconDownload size={16} />,
onClick: () => downloadImage(src),
},
{
key: 'delete',
icon: <IconTrash size={16} />,
iconRight: <IconExclamationCircle size={16} />,
onClick: () => handleDelete,
},
])}
/>
);
Expand Down
6 changes: 5 additions & 1 deletion app/examples/action-icons/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Code } from '@mantine/core';
import type { Route } from 'next';
import { CodeBlock } from '~/components/CodeBlock';
import { PageNavigation } from '~/components/PageNavigation';
Expand All @@ -17,7 +18,10 @@ export default async function ActionIconsExamplePage() {
return (
<>
<PageTitle of={PATH} />
<Txt>You can provide action icons to the context menu items, like so:</Txt>
<Txt>
You can provide action icons to the context menu items by setting the <Code>icon</Code> and{' '}
<Code>iconRight</Code> properties, like so:
</Txt>
<CodeBlock code={code} />
<Txt>Right-click on the image to trigger the context menu:</Txt>
<ActionIconsExample />
Expand Down
105 changes: 104 additions & 1 deletion app/examples/submenus/SubmenuExamples.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
'use client';

import { IconCopy, IconDownload, IconUser } from '@tabler/icons-react';
import {
IconArrowRight,
IconChevronRight,
IconCopy,
IconDownload,
IconFlipHorizontal,
IconFlipVertical,
IconUser,
IconView360,
} from '@tabler/icons-react';
import { useContextMenu } from '__PACKAGE__';
import { useState } from 'react';
import { Picture } from '~/components/Picture';
import { copyImageToClipboard, downloadImage, unsplashImages } from '~/lib/images';

export function SubmenuExample() {
// example-start submenu
const { showContextMenu } = useContextMenu();

const [flipVertical, setFlipVertical] = useState(false);
const [flipHorizontal, setFlipHorizontal] = useState(false);
// example-skip
const image = unsplashImages[1];
const { src } = image.file;
// example-resume
return (
<Picture
image={image}
flipVertical={flipVertical}
flipHorizontal={flipHorizontal}
onContextMenu={showContextMenu([
{
icon: <IconCopy size={16} />,
Expand All @@ -40,6 +55,22 @@ export function SubmenuExample() {
},
],
},
{
key: 'flip',
icon: <IconView360 size={16} />,
items: [
{
key: 'flipVertical',
icon: <IconFlipVertical size={16} />,
onClick: () => setFlipVertical((v) => !v),
},
{
key: 'flipHorizontal',
icon: <IconFlipHorizontal size={16} />,
onClick: () => setFlipHorizontal((v) => !v),
},
],
},
])}
/>
);
Expand Down Expand Up @@ -121,3 +152,75 @@ export function NestedSubmenuExample() {
);
// example-end
}

export function SubmenuExampleCustomArrowIcon() {
// example-start submenu-custom-arrow-icon
const { showContextMenu } = useContextMenu();

const [flipVertical, setFlipVertical] = useState(false);
const [flipHorizontal, setFlipHorizontal] = useState(false);
// example-skip
const image = unsplashImages[1];
const { src } = image.file;
// example-resume
return (
<Picture
image={image}
flipVertical={flipVertical}
flipHorizontal={flipHorizontal}
onContextMenu={showContextMenu([
// example-skip some items
{
icon: <IconCopy size={16} />,
key: 'copy',
onClick: () => copyImageToClipboard(src),
},
{
icon: <IconDownload size={16} />,
key: 'download',
onClick: () => downloadImage(src),
},
// example-resume
{
key: 'author',
icon: <IconUser size={16} />,
// 👇 custom arrow icon
iconRight: <IconChevronRight size={16} />,
items: [
// example-skip some nested items
{
key: 'open-in-new-tab',
onClick: () => window.open(`http://unsplash.com/@${image.author.profile}`, '_blank'),
},
{
key: 'another-item',
onClick: () => console.log('another item clicked'),
},
// example-resume
],
},
{
key: 'flip',
icon: <IconView360 size={16} />,
// 👇 custom arrow icon
iconRight: <IconArrowRight size={16} />,
items: [
// example-skip more nested items
{
key: 'flipVertical',
icon: <IconFlipVertical size={16} />,
onClick: () => setFlipVertical((v) => !v),
},
{
key: 'flipHorizontal',
icon: <IconFlipHorizontal size={16} />,
onClick: () => setFlipHorizontal((v) => !v),
},
// example-resume
],
},
])}
/>
);
// example-end
}
14 changes: 12 additions & 2 deletions app/examples/submenus/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ import { Txt } from '~/components/Txt';
import { readCodeFile } from '~/lib/code';
import { allPromiseProps, getRouteMetadata } from '~/lib/utils';
import { SubmenuDelayExample } from './SubmenuDelayExample';
import { NestedSubmenuExample, SubmenuExample } from './SubmenuExamples';
import { NestedSubmenuExample, SubmenuExample, SubmenuExampleCustomArrowIcon } from './SubmenuExamples';

const PATH: Route = '/examples/submenus';

export const metadata = getRouteMetadata(PATH);

export default async function ActionColorsExamplePage() {
const code = await allPromiseProps({
default: readCodeFile<Record<'submenu' | 'nested-submenu', string>>(`${PATH}/SubmenuExamples.tsx`),
default: readCodeFile<Record<'submenu' | 'nested-submenu' | 'submenu-custom-arrow-icon', string>>(
`${PATH}/SubmenuExamples.tsx`
),
submenuDelayProviderProp: readCodeFile<string>(`${PATH}/SubmenuDelayProviderPropExample.tsx`),
});

Expand Down Expand Up @@ -47,6 +49,14 @@ export default async function ActionColorsExamplePage() {
<CodeBlock code={code['submenuDelayProviderProp']} />
<Txt>Right-click on the image to trigger the context menu:</Txt>
<SubmenuDelayExample />
<PageSubtitle value="Using a custom arrow icon" />
<Txt>
You can customize the submenu arrow icon by setting the <Code>iconRight</Code> property like in the following
example:
</Txt>
<CodeBlock code={code['default']['submenu-custom-arrow-icon']} />
<Txt>Right-click on the image to trigger the context menu:</Txt>
<SubmenuExampleCustomArrowIcon />
<Txt>Head over to the next example to discover other features.</Txt>
<PageNavigation of={PATH} />
</>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mantine-contextmenu",
"version": "7.6.0",
"version": "7.6.1",
"description": "Craft your applications for productivity and meet your users’ expectations by enhancing your Mantine-based UIs with a desktop-grade, lightweight yet fully-featured, dark-theme aware context-menu component, built by the creator of Mantine DataTable",
"keywords": [
"ui",
Expand Down
7 changes: 6 additions & 1 deletion package/ContextMenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function ContextMenuItem({
className,
style,
icon,
iconRight,
title,
color,
disabled,
Expand Down Expand Up @@ -97,7 +98,11 @@ export function ContextMenuItem({
</Box>
)}
<div className="mantine-contextmenu-item-button-title">{title}</div>
{items && (
{ iconRight ? (
<Box fz={0} ml="xs" mt={-2}>
{iconRight}
</Box>
) : items && (
<Box fz={10} mt={-2} ml="xs">
</Box>
Expand Down
7 changes: 7 additions & 0 deletions package/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ export type ContextMenuItemOptions = {
*/
icon?: React.ReactNode;

/**
* Optional context menu item icon for the right side of the title.
* If provided this will overwrite the submenu's ▶ icon
*/
iconRight?: React.ReactNode;

/**
* Optional context menu item title.
* If not provided, one will be generated automatically by "humanizing" the key.
Expand Down Expand Up @@ -143,6 +149,7 @@ export type ContextMenuItemOptions = {
))
| {
icon?: never;
iconRight?: never;
title?: never;
color?: never;
disabled?: never;
Expand Down

0 comments on commit ab315d3

Please sign in to comment.