Examples › Custom styling

There are more ways to style a context menu besides setting its basic configuration options and its items action colors.

The ContextMenuProvider wrapper component accepts the following properties: className, style, classNames and styles.
Have a look at Mantine Styles API documentation to make a general idea of how these properties work.

The className and style properties can be used to target the component root, while the classNames and styles properties can be used to target the individual component parts, root, item and divider.

If you provide the above properties to the ContextMenuProvider component, they will be passed down to all the context menus that are rendered within the provider.

import { MantineProvider } from '@mantine/core';
import { ContextMenuProvider } from 'mantine-contextmenu';
import classes from './ProviderPropsExample.module.css';

export default function ProviderPropsExample({ children }: React.PropsWithChildren) {
  return (
    <MantineProvider>
      <ContextMenuProvider
        classNames={{
          root: classes.contextMenuRoot,
          item: classes.contextMenuItem,
        }}
      >
        {children}
      </ContextMenuProvider>
    </MantineProvider>
  );
}

The ContextMenuProvider styling values can be overriden by setting the similarly-named properties of an options object passed as the second argument to the showContextMenufunction returned by useContextMenu hook to target the individual context menu instances, in which case they will override the initial provider properties.
The examples below will use this approach.

Styling the container with a className

You can specify a className that will target the component root:

'use client';

import { IconCopy, IconDownload } from '@tabler/icons-react';
import { useContextMenu } from 'mantine-contextmenu';
import { Picture } from '~/components/Picture';
import { copyImageToClipboard, downloadImage, unsplashImages } from '~/lib/images';
import classes from './StylingWithClassNameExample.module.css';

export function StylingWithClassNameExample() {
  const { showContextMenu } = useContextMenu();
  // ...

  return (
    <Picture
      // component props...
      onContextMenu={showContextMenu(
        [
          // context menu items...
        ],
        { className: classes.contextMenu }
      )}
    />
  );
}
Picture by Manja Vitolic | Mantine ContextMenu

Picture by Manja Vitolic

Styling the container with a style object

You can specify a style object with CSS properties that will be applied to the component root:

export function StylingWithStyleObjectExample() {
  const { showContextMenu } = useContextMenu();
  // ...

  return (
    <Picture
      // component props...
      onContextMenu={showContextMenu(
        [
          // context menu items...
        ],
        { style: { border: '1px dashed #d3c22f' } }
      )}
    />
  );
}
Picture by Pacto Visual | Mantine ContextMenu

Picture by Pacto Visual

The style property can also point to a function that will receive the current theme as an argument and return a style object:

export function StylingWithStyleFunctionExample() {
  const { showContextMenu } = useContextMenu();
  // ...

  return (
    <Picture
      // component props...
      onContextMenu={showContextMenu(
        [
          // context menu items...
        ],
        { style: (theme) => ({ border: `1px dashed ${theme.colors.grape[6]}` }) }
      )}
    />
  );
}
Picture by Daria Shatova | Mantine ContextMenu

Picture by Daria Shatova

Styling with multiple class names

Here’s an example of how you can use classNames property to target the individual component parts:

'use client';

import { IconCopy, IconDownload } from '@tabler/icons-react';
import { useContextMenu } from 'mantine-contextmenu';
import { Picture } from '~/components/Picture';
import { copyImageToClipboard, downloadImage, unsplashImages } from '~/lib/images';
import classes from './StylingWithClassNamesExample.module.css';

export default function StylingWithClassNamesExample() {
  const { showContextMenu } = useContextMenu();
  // ...

  return (
    <Picture
      // component props...
      onContextMenu={showContextMenu(
        [
          // context menu items...
        ],
        {
          classNames: {
            root: classes.contextMenuRoot,
            item: classes.contextMenuItem,
          },
        }
      )}
    />
  );
}
Picture by Lloyd Henneman | Mantine ContextMenu

Picture by Lloyd Henneman

Styling with multiple style objects

Here’s an example of how you can use the styles property to target the individual component parts:

export function StylingWithStylesObjectExample() {
  const { showContextMenu } = useContextMenu();
  // ...

  return (
    <Picture
      // component props...
      onContextMenu={showContextMenu(
        [
          // context menu items...
        ],
        {
          styles: {
            root: { border: '1px solid #d30e0e' },
            divider: { background: 'transparent', borderTop: '1px dashed #116d09' },
            item: { color: '#d30e0e' },
          },
        }
      )}
    />
  );
}
Picture by Michael Sum | Mantine ContextMenu

Picture by Michael Sum

You can also use functions that receive the current theme as an argument and return styles objects:

export function StylingWithStylesFunctionsExample() {
  const { showContextMenu } = useContextMenu();
  // ...

  return (
    <Picture
      // component props...
      onContextMenu={showContextMenu(
        [
          // context menu items...
        ],
        {
          styles: {
            root: (theme) => ({ border: `1px solid ${theme.colors.indigo[6]}` }),
            item: (theme) => ({ color: theme.colors.orange[6] }),
          },
        }
      )}
    />
  );
}
Picture by Zeke Tucker | Mantine ContextMenu

Picture by Zeke Tucker

Styling individual actions with className and style

You can also style individual actions by passing a className or style property to the object describing an individual menu item:

'use client';

import { IconCopy, IconDownload, IconFlipHorizontal, IconFlipVertical } from '@tabler/icons-react';
import { useContextMenu } from 'mantine-contextmenu';
import { useState } from 'react';
import { Picture } from '~/components/Picture';
import { copyImageToClipboard, downloadImage, unsplashImages } from '~/lib/images';
import classes from './IndividualActionStylingExample.module.css';

export default function IndividualActionStylingExample() {
  const { showContextMenu } = useContextMenu();
  // ...
  return (
    <Picture
      // component props...
      onContextMenu={showContextMenu(
        [
          {
            key: 'copy',
            icon: <IconCopy size={16} />,
            onClick: () => copyImageToClipboard(src),
            className: classes.copyAction, // 👈 action styled with className
          },
          {
            key: 'download',
            icon: <IconDownload size={16} />,
            onClick: () => downloadImage(src),
            // 👇 action styled with a style object
            style: {
              fontStyle: 'italic',
              color: '#0d8527',
            },
          },
          {
            key: 'div-1',
            // 👇 divider styled with a style function
            style: (theme) => ({ background: theme.colors.orange[6] }),
          },
          {
            key: 'flipVertical',
            icon: <IconFlipVertical size={16} />,
            onClick: () => setFlipVertical((v) => !v),
          },
          {
            key: 'flipHorizontal',
            icon: <IconFlipHorizontal size={16} />,
            onClick: () => setFlipHorizontal((v) => !v),
          },
        ],
        {
          // 👇 menu styled with class names
          classNames: {
            root: classes.contextMenuRoot,
            item: classes.contextMenuItem,
          },
        }
      )}
    />
  );
}
Picture by Nathalie Jolie | Mantine ContextMenu

Picture by Nathalie Jolie

Head over to the next example to discover other features.