Mantine Marquee

@gfazioli/mantine-marquee

A Mantine component that allows you to create a marquee effect with a list of elements.

Installation

yarn add @gfazioli/mantine-marquee

After installation import package styles at the root of your application:

import '@gfazioli/mantine-marquee/styles.css';

You can import styles within a layer @layer mantine-marquee by importing @gfazioli/mantine-marquee/styles.layer.css file.

import '@gfazioli/mantine-marquee/styles.layer.css';

Usage

The Marquee component allows you to create a marquee effect with any content.

Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #5
Hope you like it #6
Have a nice day #7
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #5
Hope you like it #6
Have a nice day #7
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #5
Hope you like it #6
Have a nice day #7
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #5
Hope you like it #6
Have a nice day #7
Repeat
Duration
Gap
Fade edges size
Fade edges size y
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Marquee repeat={4} duration={10} gap="sm" fadeEdgesSize={20}>
      <BoxComponent bg="red">Hello World #1</BoxComponent>
      <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
      <BoxComponent bg="blue">Have a nice day #3</BoxComponent>
      <BoxComponent bg="lime">Goodbye #4</BoxComponent>
    </Marquee>
  );
}

Fade edges

The fadeEdges prop adds a smooth fade effect at the edges of the scroll area using CSS mask-image. It accepts true, "linear", "ellipse", or "rect" — passing true is equivalent to "linear". Use fadeEdgesSize to control how much of the edge is faded ("xs" | "sm" | "md" | "lg" | "xl" or a percentage string).

Linear

fadeEdges="linear" applies a gradient mask on the leading and trailing scroll edges. This works for both horizontal and vertical layouts, and it is ideal for content that enters and exits from the sides.

Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box, Flex } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Flex direction="column" gap="md">
      <Marquee fadeEdges="linear" fadeEdgesSize="sm">
        <BoxComponent bg="blue">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="indigo">Have a nice day #3</BoxComponent>
        <BoxComponent bg="teal">Goodbye #4</BoxComponent>
      </Marquee>
      <Marquee fadeEdges="linear" fadeEdgesSize="sm" reverse>
        <BoxComponent bg="orange">Hello World #1</BoxComponent>
        <BoxComponent bg="red">Hope you like it #2</BoxComponent>
        <BoxComponent bg="pink">Have a nice day #3</BoxComponent>
        <BoxComponent bg="grape">Goodbye #4</BoxComponent>
      </Marquee>
    </Flex>
  );
}

Ellipse

fadeEdges="ellipse" applies a radial elliptical mask that fades all around the border. This is orientation-independent — it works identically for horizontal and vertical marquees. It is particularly effective for logo carousels, icon showcases, or any content where a vignette effect is desired.

import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { ThemeIcon } from '@mantine/core';
import {
  IconBrand4chan,
  IconBrandAmazon,
  IconBrandBing,
  IconBrandGithub,
  IconBrandMantine,
  IconBrandWhatsapp,
  IconBrandWordpress,
} from '@tabler/icons-react';

function Demo() {
  const iconsBrand = [
    <IconBrand4chan style={{ width: '70%', height: '70%' }} />,
    <IconBrandWhatsapp style={{ width: '70%', height: '70%' }} />,
    <IconBrandWordpress style={{ width: '70%', height: '70%' }} />,
    <IconBrandBing style={{ width: '70%', height: '70%' }} />,
    <IconBrandGithub style={{ width: '70%', height: '70%' }} />,
    <IconBrandMantine style={{ width: '70%', height: '70%' }} />,
    <IconBrandAmazon style={{ width: '70%', height: '70%' }} />,
  ];

  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <ThemeIcon {...props} variant="transparent" size="120px">
        {children}
      </ThemeIcon>
    );
  }

  return (
    <Marquee pauseOnHover fadeEdges="ellipse" fadeEdgesSize="md">
      {iconsBrand.map((icon, index) => (
        <BoxComponent key={index}>{icon}</BoxComponent>
      ))}
    </Marquee>
  );
}

Circle

Since the ellipse mask uses radial-gradient(ellipse closest-side), applying fadeEdges="ellipse" to a square element (w and h are equal) produces a perfectly circular mask. No additional prop is needed — the geometry does the work.

John Doe

Jane Doe

Jessica Doe

Jack Doe

Jill Doe

John Doe

Jane Doe

Jessica Doe

Jack Doe

Jill Doe

import { Marquee } from '@gfazioli/mantine-marquee';
import { Avatar, Card, Center, Rating, Stack, Text } from '@mantine/core';

function Demo() {
  const testimonials = [
    { name: 'John Doe', avatar: '...', rating: 4 },
    { name: 'Jane Doe', avatar: '...', rating: 4 },
    { name: 'Jessica Doe', avatar: '...', rating: 2 },
    { name: 'Jack Doe', avatar: '...', rating: 5 },
    { name: 'Jill Doe', avatar: '...', rating: 3 },
  ];

  return (
    <Center>
      {/* Ellipse on a square element (w=h) produces a circular mask */}
      <Marquee
        w={300}
        h={300}
        pauseOnHover
        fadeEdges="ellipse"
        fadeEdgesSize="md"
        style={{ justifyContent: 'center' }}
      >
        {testimonials.map((t, index) => (
          <Card key={index} w={120} shadow="sm" padding="sm" radius="md" withBorder>
            <Stack align="center" gap="xs">
              <Avatar size="lg" radius="xl" src={t.avatar} />
              <Text size="xs" fw={600} ta="center">
                {t.name}
              </Text>
              <Rating value={t.rating} size="xs" />
            </Stack>
          </Card>
        ))}
      </Marquee>
    </Center>
  );
}

Rect

fadeEdges="rect" uses two intersected linear gradients (mask-composite: intersect) to fade all 4 edges independently. The horizontal gradient controls left/right, the vertical gradient controls top/bottom — at the corners the alpha values multiply naturally, creating a smooth diagonal falloff.

fadeEdgesSize accepts a [horizontal, vertical] tuple for independent axis control. For example fadeEdgesSize={['lg', 'xs']} applies a large fade on left/right and a small fade on top/bottom.

Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box, Flex } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Flex direction="column" gap="md">
      {/* Uniform fade on all 4 edges */}
      <Marquee fadeEdges="rect" fadeEdgesSize="md" h={60}>
        <BoxComponent bg="blue">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="indigo">Have a nice day #3</BoxComponent>
        <BoxComponent bg="teal">Goodbye #4</BoxComponent>
      </Marquee>
      {/* Tuple: more fade on left/right (lg), less on top/bottom (xs) */}
      <Marquee fadeEdges="rect" fadeEdgesSize={['lg', 'xs']} reverse h={60}>
        <BoxComponent bg="orange">Hello World #1</BoxComponent>
        <BoxComponent bg="red">Hope you like it #2</BoxComponent>
        <BoxComponent bg="pink">Have a nice day #3</BoxComponent>
        <BoxComponent bg="grape">Goodbye #4</BoxComponent>
      </Marquee>
    </Flex>
  );
}

Multiple

The Marquee component allows you to create a marquee effect with multiple items.

Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <>
      <Marquee mb={16} fadeEdges>
        <BoxComponent bg="red">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="blue">Have a nice day #3</BoxComponent>
        <BoxComponent bg="lime">Goodbye #4</BoxComponent>
      </Marquee>
      <Marquee reverse fadeEdges>
        <BoxComponent bg="red">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="blue">Have a nice day #3</BoxComponent>
        <BoxComponent bg="lime">Goodbye #4</BoxComponent>
      </Marquee>
    </>
  );
}

Vertical

The Marquee component allows you to create a marquee effect with multiple items in vertical direction.

Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box, Flex } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Flex w={500}>
      <Marquee h={300} fadeEdges vertical>
        <BoxComponent bg="red">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="blue">Have a nice day #3</BoxComponent>
        <BoxComponent bg="lime">Goodbye #4</BoxComponent>
      </Marquee>
      <Marquee h={300} reverse fadeEdges vertical>
        <BoxComponent bg="red">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="blue">Have a nice day #3</BoxComponent>
        <BoxComponent bg="lime">Goodbye #4</BoxComponent>
      </Marquee>
    </Flex>
  );
}

Isometric variant

Set variant="isometric" to lay the marquee on a plane tilted back in 3D space — content scrolls across a surface, as if the items were resting on a table. The existing scroll loop is reused unchanged, so every other prop (reverse, duration, pauseOnHover, gap, vertical) keeps working.

Use tilt to control the plane inclination in degrees and perspective to control the depth in pixels (smaller values exaggerate the effect). Add rotate (in-plane rotateZ) and skew (horizontal skewX) to dial in a classic ¾ isometric (2.5D) look. The 3D scene is composited as a flat image on the root element, so fadeEdges masks still apply on top of the tilted plane — the linear fade automatically follows the projected scroll axis, so it keeps fading the leading and trailing items even when the plane is rotated.

Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #5
Hope you like it #6
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #5
Hope you like it #6
Tilt
Perspective
Rotate
Skew
Fade edges size
Duration
Gap
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box } from '@mantine/core';

function Demo() {
  function Card({ children, ...rest }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...rest} p="md" w={200} h={120} c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Marquee variant="isometric" tilt={48} perspective={750} fadeEdgesSize={15} duration={12} gap="md">
      <Card bg="red">Hello World #1</Card>
      <Card bg="cyan">Hope you like it #2</Card>
      <Card bg="blue">Have a nice day #3</Card>
      <Card bg="lime">Goodbye #4</Card>
      <Card bg="orange">Hello World #5</Card>
      <Card bg="grape">Hope you like it #6</Card>
    </Marquee>
  );
}

Circle variant

Set variant="circle" to distribute the children around a 3D ellipse ring that rotates continuously, like a carousel. Each child is positioned once around the ring (no clones) and the whole ring spins — rotateY(360deg) equals rotateY(0deg), so the loop is perfectly seamless.

The items are mounted on the rim facing outward, so the ring reads as a 3D carousel/cylinder. Use radius to size the ring (a single number for a circular ring, or a [rx, ry] tuple for an explicit ellipse), tilt for the viewing angle (positive views the ring from above, negative from below), and perspective for the depth. reverse, duration and pauseOnHover work as usual; repeat, gap and vertical do not apply to a ring.

The circle variant needs a height — set h (or mih) on the component.

Radius
Tilt
Perspective
Duration
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box, Flex } from '@mantine/core';

const SITES = [
  { label: 'Findergit', href: 'https://www.findergit.app/', bg: 'red' },
  { label: 'Netfox', href: 'https://netfox.app', bg: 'cyan' },
  { label: 'Octoscope', href: 'https://gfazioli.github.io/octoscope/', bg: 'blue' },
  { label: 'MEH', href: 'https://mantine-extensions.vercel.app', bg: 'grape' },
  { label: 'Clock', href: 'https://gfazioli.github.io/mantine-clock', bg: 'lime' },
  { label: 'Scene', href: 'https://gfazioli.github.io/mantine-scene', bg: 'teal' },
  { label: 'Book', href: 'https://gfazioli.github.io/mantine-book', bg: 'orange' },
  { label: 'Marquee', href: 'https://gfazioli.github.io/mantine-marquee', bg: 'pink' },
];

const cardCss = `
  .circle-card {
    transition: transform 160ms ease, box-shadow 160ms ease, filter 160ms ease;
  }
  .circle-card:hover {
    transform: scale(1.12);
    filter: brightness(1.12);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  }
`;

function Demo() {
  return (
    <>
      <style>{cardCss}</style>
      <Flex w="100%" h={440} align="center" justify="center">
        <Marquee variant="circle" w="100%" h={440} radius={250} tilt={-15} perspective={700} duration={16} pauseOnHover>
          {SITES.map((site) => (
            <Box
              key={site.label}
              component="a"
              href={site.href}
              target="_blank"
              rel="noreferrer"
              className="circle-card"
              bg={site.bg}
              w={150}
              h={90}
              c="white"
              fw={600}
              style={{ display: 'grid', placeItems: 'center', borderRadius: '8px', textDecoration: 'none' }}
            >
              {site.label}
            </Box>
          ))}
        </Marquee>
      </Flex>
    </>
  );
}

Responsive vertical

The vertical prop accepts a responsive breakpoint object in addition to a plain boolean. This lets you switch between vertical and horizontal layouts at different viewport widths using Mantine's useMatches hook under the hood.

// Vertical on mobile, horizontal from md breakpoint up
<Marquee vertical={{ base: true, md: false }}>{/* ... */}</Marquee>
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Marquee vertical={{ base: true, md: false }} h={300} fadeEdges>
      <BoxComponent bg="blue">Hello World #1</BoxComponent>
      <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
      <BoxComponent bg="indigo">Have a nice day #3</BoxComponent>
      <BoxComponent bg="teal">Goodbye #4</BoxComponent>
    </Marquee>
  );
}

Responsive gap

The gap prop also accepts a responsive breakpoint object. This is useful when switching layout direction at a breakpoint — you can pair it with a different gap size.

// Small gap on mobile, large gap from md breakpoint up
<Marquee gap={{ base: 'xs', md: 'xl' }}>{/* ... */}</Marquee>
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Marquee gap={{ base: 'xs', md: 'xl' }} fadeEdges="linear" w="100%">
      <BoxComponent bg="blue">Hello World #1</BoxComponent>
      <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
      <BoxComponent bg="indigo">Have a nice day #3</BoxComponent>
      <BoxComponent bg="teal">Goodbye #4</BoxComponent>
    </Marquee>
  );
}

Drop-in for Mantine core Marquee

This component is a superset of the built-in @mantine/core Marquee — existing snippets keep working after changing the import path, with a few notes:

  • orientation="horizontal" | "vertical" is accepted as an alias of vertical.
  • fadeEdgeSize is accepted as an alias of fadeEdgesSize (singular spelling).
  • fadeEdgeColor is accepted but ignored — fade edges use CSS masks (true alpha, background-independent), so no fade color is required.
  • duration is expressed in seconds here, while @mantine/core measures it in milliseconds: core duration={100000} corresponds to duration={100}.

On top of that you get responsive gap and vertical, fade-edge shapes (linear, ellipse, rect), per-axis fade sizes, and the isometric and circle 3D variants.

Example: Testimonials

Your customers feedback is important to you. Use Marquee to display your testimonials.

John Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jane Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jessica Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jack Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jill Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

John Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jane Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jessica Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jack Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jill Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

import { Marquee } from '@gfazioli/mantine-marquee';
import { Avatar, Card, Group, Rating, Stack, Text, Title } from '@mantine/core';
import { ReactNode } from 'react';
import { testimonials } from './testimonials';

function Demo() {
  function BoxComponent({
    children,
    avatar,
    name,
    rating,
    ...props
  }: {
    children: ReactNode;
    avatar: string;
    name: string;
    [key: string]: any;
  }) {
    return (
      <Card w={200} shadow="sm" padding="lg" radius="md" withBorder>
        <Card.Section p="md">
          <Group>
            <Avatar size="md" radius="xl" src={avatar} />
            <Title order={4}>{name}</Title>
          </Group>
        </Card.Section>
        <Stack>
          <Text size="sm" c="dimmed">
            {children}
          </Text>
          <Group justify="end">
            <Rating value={rating} />
          </Group>
        </Stack>
      </Card>
    );
  }

  return (
    <Marquee pauseOnHover fadeEdges>
      {testimonials.map(({ text, ...testimonial }, index) => (
        <BoxComponent key={index} {...testimonial}>
          {text}
        </BoxComponent>
      ))}
    </Marquee>
  );
}

Example: Branding

One of the most common use cases for Marquee is to create branding banners.

import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { ThemeIcon } from '@mantine/core';
import {
  IconBrand4chan,
  IconBrandAmazon,
  IconBrandBing,
  IconBrandGithub,
  IconBrandMantine,
  IconBrandWhatsapp,
  IconBrandWordpress,
} from "@tabler/icons-react";

function Demo() {
  const iconsBrand = [
    <IconBrand4chan style={{ width: '70%', height: '70%' }} />,
    <IconBrandWhatsapp style={{ width: '70%', height: '70%' }} />,
    <IconBrandWordpress style={{ width: '70%', height: '70%' }} />,
    <IconBrandBing style={{ width: '70%', height: '70%' }} />,
    <IconBrandGithub style={{ width: '70%', height: '70%' }} />,
    <IconBrandMantine style={{ width: '70%', height: '70%' }} />,
    <IconBrandAmazon style={{ width: '70%', height: '70%' }} />,
  ];

  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <ThemeIcon {...props} variant="transparent" size="120px">
        {children}
      </ThemeIcon>
    );
  }

  return (
    <Marquee pauseOnHover fadeEdges>
      {iconsBrand.map((icon, index) => (
        <BoxComponent key={index}>{icon}</BoxComponent>
      ))}
    </Marquee>
  );
}

Example: Isometric tech stack

The isometric variant turns a plain logo strip into a 3D "tech stack on a desk" hero — perfect for landing pages, integrations sections, or a tools showcase.

React

TypeScript

Next.js

Mantine

Vercel

Tailwind

Figma

GitHub

React

TypeScript

Next.js

Mantine

Vercel

Tailwind

Figma

GitHub

import { Marquee } from '@gfazioli/mantine-marquee';
import { Group, Paper, Text, ThemeIcon } from '@mantine/core';
import {
  IconBrandFigma,
  IconBrandGithub,
  IconBrandMantine,
  IconBrandNextjs,
  IconBrandReact,
  IconBrandTailwind,
  IconBrandTypescript,
  IconBrandVercel,
} from '@tabler/icons-react';

const stack = [
  { label: 'React', icon: <IconBrandReact />, color: 'cyan' },
  { label: 'TypeScript', icon: <IconBrandTypescript />, color: 'blue' },
  { label: 'Next.js', icon: <IconBrandNextjs />, color: 'dark' },
  { label: 'Mantine', icon: <IconBrandMantine />, color: 'indigo' },
  { label: 'Vercel', icon: <IconBrandVercel />, color: 'dark' },
  { label: 'Tailwind', icon: <IconBrandTailwind />, color: 'teal' },
  { label: 'Figma', icon: <IconBrandFigma />, color: 'grape' },
  { label: 'GitHub', icon: <IconBrandGithub />, color: 'gray' },
];

function Demo() {
  return (
    <Marquee
      variant="isometric"
      tilt={50}
      rotate={30}
      skew={10}
      perspective={650}
      duration={16}
      gap="xl"
      fadeEdges="ellipse"
      pauseOnHover
      h={340}
    >
      {stack.map((tech) => (
        <Paper key={tech.label} withBorder radius="md" p="md" w={210} shadow="md">
          <Group gap="sm" wrap="nowrap">
            <ThemeIcon variant="light" color={tech.color} size={42} radius="md">
              {tech.icon}
            </ThemeIcon>
            <Text fw={600}>{tech.label}</Text>
          </Group>
        </Paper>
      ))}
    </Marquee>
  );
}

Example: Circle avatar ring

The circle variant arranges items around a rotating 3D ring — a carousel for team avatars, community members, or a brand showcase. A slightly negative tilt views the ring from just below; hover to pause and click an avatar.

import { Marquee } from '@gfazioli/mantine-marquee';
import { Avatar, Flex } from '@mantine/core';

const base = 'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars';
const avatars = [
  `${base}/avatar-1.png`,
  `${base}/avatar-2.png`,
  `${base}/avatar-3.png`,
  `${base}/avatar-4.png`,
  `${base}/avatar-5.png`,
  `${base}/avatar-6.png`,
  `${base}/avatar-7.png`,
  `${base}/avatar-8.png`,
];

function Demo() {
  return (
    <Flex w="100%" h={360} align="center" justify="center">
      <Marquee
        variant="circle"
        radius={240}
        tilt={-14}
        perspective={900}
        duration={22}
        pauseOnHover
        w="100%"
        h={360}
      >
        {avatars.map((src, index) => (
          <Avatar
            key={index}
            src={src}
            size={96}
            radius="xl"
            style={{
              border: '3px solid var(--mantine-color-body)',
              boxShadow: 'var(--mantine-shadow-lg)',
            }}
          />
        ))}
      </Marquee>
    </Flex>
  );
}