Mantine Flip

Logo

@gfazioli/mantine-flip

A Mantine component that flips the content of the component when hovered over.

Installation

yarn add @gfazioli/mantine-flip

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

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

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

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

Usage

Norway

Norway Fjord Adventures

On Sale

With Fjord Tours you can explore more of the magical fjord landscapes with tours and activities on and around the fjords of Norway

Edit Widget

Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, voluptatum.

Perspective
Duration
import { Flip } from '@gfazioli/mantine-flip';

function Demo() {
  return (
    <Center>
      <Flip h={200} w={400}>
        <Card shadow="sm" padding="lg" radius="md" withBorder>
          <Card.Section>
            <Image
              src="https://images.unsplash.com/photo-1527004013197-933c4bb611b3?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=720&q=80"
              height={160}
              alt="Norway"
            />
          </Card.Section>

          <Group justify="space-between" mt="md" mb="xs">
            <Text fw={500}>Norway Fjord Adventures</Text>
            <Badge color="pink" variant="light">
              On Sale
            </Badge>
          </Group>

          <Text size="sm" c="dimmed">
            With Fjord Tours you can explore more of the magical fjord landscapes with tours and
            activities on and around the fjords of Norway
          </Text>

          <Group justify="right">
            <Flip.Target>
              <Button color="blue" mt="md" radius="md">
                Edit Widget
              </Button>
            </Flip.Target>
          </Group>
        </Card>

        <Paper bg="dark" radius="md" withBorder p="lg">
          <Stack>
            <Title order={4} c="white">
              Edit Widget
            </Title>
            <Text c="gray" size="sm">
              Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, voluptatum.
            </Text>
            <Switch c="white" defaultChecked label="Display image" />
            <Switch c="white" label="Auto play" />
            <Group justify="left">
              <Flip.Target>
                <Button color="red" mt="md" radius="md">Close</Button>
              </Flip.Target>
            </Group>
          </Stack>
        </Paper>
      </Flip>
    </Center>
  );
}

IMPORTANT

The Flip component must have exactly two children. The first child is the front face, and the second child is the back face.

Compound Components

You can use Flip.Front and Flip.Back compound components for a more explicit and readable API. This makes it clear which child is the front face and which is the back face.

Front Card

Using Flip.Front compound component

Back Card

Using Flip.Back compound component

import { Flip } from '@gfazioli/mantine-flip';
import { Button, Group, Paper } from '@mantine/core';

function Demo() {
  return (
    <Flip h={200} w={400}>
      <Flip.Front>
        <Paper radius="md" withBorder p="lg" shadow="md">
          <h3>Front Card</h3>
          <p>Using Flip.Front compound component</p>
          <Group justify="right">
            <Flip.Target>
              <Button>Show Back</Button>
            </Flip.Target>
          </Group>
        </Paper>
      </Flip.Front>

      <Flip.Back>
        <Paper radius="md" withBorder p="lg" shadow="md">
          <h3>Back Card</h3>
          <p>Using Flip.Back compound component</p>
          <Flip.Target>
            <Button variant="outline">Show Front</Button>
          </Flip.Target>
        </Paper>
      </Flip.Back>
    </Flip>
  );
}

Both approaches are supported: you can either pass two direct children (backward compatible) or use Flip.Front / Flip.Back. Do not mix the two styles.

Uncontrolled

Front Card

The front card

Back Card

import { Flip } from '@gfazioli/mantine-flip';
import { Button, Group, Paper } from '@mantine/core';

function Demo() {
  return (
    <Flip h={200} w={400}>

      <Paper radius="md" withBorder p="lg" shadow="md">
        <h3>Front Card</h3>
        <p>The front card</p>
        <Group justify="right">
          <Flip.Target>
            <Button>Show Back</Button>
          </Flip.Target>
        </Group>
      </Paper>

      <Paper radius="md" withBorder p="lg" shadow="md">
        <h3>Back Card</h3>
        <Flip.Target>
          <Button variant="outline">Back to Front</Button>
        </Flip.Target>
      </Paper>

    </Flip>
  );
}

Controlled

You may control the state of the card by setting the flipped prop to true or false. This is useful when you want to control the state of the card from the parent component.

Front Card

The front card

Back Card

function Demo() {
  const [flipped, setFlipped] = useState(false);

  return (
    <Stack>
      <Group>
        <Switch checked={flipped}
                onChange={(event) => setFlipped(event.currentTarget.checked)}
                label="Show settings" />
      </Group>

    <Flip h={200} w={400} flipped={flipped}>

      <Paper radius="md" withBorder p="lg" shadow="md">
        <h3>Front Card</h3>
        <p>The front card</p>
        <Group justify="right">
          <Button onClick={()=>setFlipped(true)}>Show Settings</Button>
        </Group>
      </Paper>

      <Paper radius="md" withBorder p="lg" shadow="md">
        <h3>Back Card</h3>
        <Button onClick={()=>setFlipped(false)} variant="outline">Back to Front</Button>
      </Paper>

    </Flip>
    </Stack>
  );
}

Initial face and Flip.Target

For controlled Flip components, you will use useState to determine which side of the component to initially show. Additionally, you will not need to use Flip.Target for buttons, but you can control them manually to keep the states synchronized.

Default Flipped (face)

You may display the initial face of the card by setting the defaultFlipped prop to true.

Front Card

The front card

Back Card

In this case the defaultFlipped prop is set to true, and the back card is visible

import { Flip } from '@gfazioli/mantine-flip';

function Demo() {
  return (
    <Flip h={200} w={400} defaultFlipped={true}>

      <Paper radius="md" withBorder p="lg" shadow="md">
        <h3>Front Card</h3>
            <p>The front card</p>
            <Group justify="right">
              <Flip.Target>
                  <Button>Flip to Back</Button>
              </Flip.Target>
            </Group>
      </Paper>

      <Paper radius="md" withBorder p="lg" shadow="md">
        <h3>Back Card</h3>
        <p>In this case the <Code>defaultFlipped</Code> prop is set to <Code>true</Code>, and the back card is visible</p>
          <Flip.Target>
            <Button variant="outline">Flip to Front</Button>
          </Flip.Target>
      </Paper>

    </Flip>
  );
}

Direction

You can change the flip rotation direction to vertical using the direction prop.

Front Side

Click the button below to flip vertically

Back Side

Click the button below to flip back

import { Flip } from '@gfazioli/mantine-flip';
import { Button, Group, Paper, Text } from '@mantine/core';

function Demo() {
  return (
    <Group justify="center">
      <Flip w={200} h={300} direction="vertical">
        <Paper shadow="md" p="xl" withBorder w="100%" h="100%">
          <Text>Front Side</Text>
          <Text size="sm" c="dimmed" mt="md">
            Click the button below to flip vertically
          </Text>
          <Flip.Target>
            <Button fullWidth mt="xl">
              Flip Vertical
            </Button>
          </Flip.Target>
        </Paper>

        <Paper shadow="md" p="xl" withBorder w="100%" h="100%">
          <Text>Back Side</Text>
          <Text size="sm" c="dimmed" mt="md">
            Click the button below to flip back
          </Text>
          <Flip.Target>
            <Button fullWidth mt="xl" color="red">
              Flip Back
            </Button>
          </Flip.Target>
        </Paper>
      </Flip>
    </Group>
  );
}

Spring Easing

Set easing="spring" for a physics-based spring animation that gives the flip a natural, bouncy feel. Compare it side by side with the default ease-in-out.

ease-in-out (default)

Front

Back

spring

Front

Back

import { Flip } from '@gfazioli/mantine-flip';
import { Button, Group, Paper, Text } from '@mantine/core';

function Demo() {
  return (
    <Group justify="center" gap="xl">
      <div>
        <Text size="sm" fw={500} mb="xs" ta="center">ease-in-out (default)</Text>
        <Flip h={180} w={200}>
          <Paper radius="md" withBorder p="lg" shadow="md" h="100%">
            <Text fw={500}>Front</Text>
            <Flip.Target>
              <Button mt="md" fullWidth>Flip</Button>
            </Flip.Target>
          </Paper>
          <Paper radius="md" withBorder p="lg" shadow="md" h="100%" bg="var(--mantine-color-blue-light)">
            <Text fw={500}>Back</Text>
            <Flip.Target>
              <Button mt="md" fullWidth variant="outline">Flip</Button>
            </Flip.Target>
          </Paper>
        </Flip>
      </div>

      <div>
        <Text size="sm" fw={500} mb="xs" ta="center">spring</Text>
        <Flip h={180} w={200} easing="spring">
          <Paper radius="md" withBorder p="lg" shadow="md" h="100%">
            <Text fw={500}>Front</Text>
            <Flip.Target>
              <Button mt="md" fullWidth>Flip</Button>
            </Flip.Target>
          </Paper>
          <Paper radius="md" withBorder p="lg" shadow="md" h="100%" bg="var(--mantine-color-teal-light)">
            <Text fw={500}>Back</Text>
            <Flip.Target>
              <Button mt="md" fullWidth variant="outline">Flip</Button>
            </Flip.Target>
          </Paper>
        </Flip>
      </div>
    </Group>
  );
}

Custom Flip Transitions

You can customize the flip transition direction using directionFlipIn and directionFlipOut props.

Custom Transitions

Flip In: Positive
Flip Out: Negative

Back Side

Notice the different rotation direction

import { Flip } from '@gfazioli/mantine-flip';
import { Button, Group, Paper, Text } from '@mantine/core';

function Demo() {
  return (
    <Group justify="center">
      <Flip w={300} h={200} directionFlipIn="positive" directionFlipOut="negative">
        <Paper shadow="md" p="xl" withBorder w="100%" h="100%">
          <Text fw={700}>Custom Transitions</Text>
          <Text size="sm" mt="xs">
            Flip In: Positive
            <br />
            Flip Out: Negative
          </Text>
          <Flip.Target>
            <Button mt="md">Flip Me</Button>
          </Flip.Target>
        </Paper>

        <Paper shadow="md" p="xl" withBorder w="100%" h="100%" bg="var(--mantine-color-blue-light)">
          <Text fw={700}>Back Side</Text>
          <Text size="sm" mt="xs">
            Notice the different rotation direction
          </Text>
          <Flip.Target>
            <Button mt="md" variant="white">
              Flip Back
            </Button>
          </Flip.Target>
        </Paper>
      </Flip>
    </Group>
  );
}

Lazy Back

Use the lazyBack prop to defer rendering of the back face until the first flip occurs. This is useful for grids with many flip cards where the back content is heavy — it reduces the initial DOM size and improves performance.

Front Card

The back face is not rendered until you flip for the first time. Inspect the DOM to verify.

import { Flip } from '@gfazioli/mantine-flip';
import { Button, Group, Paper, Text } from '@mantine/core';

function Demo() {
  return (
    <Flip h={200} w={400} lazyBack>
      <Paper radius="md" withBorder p="lg" shadow="md">
        <h3>Front Card</h3>
        <Text size="sm" c="dimmed">
          The back face is not rendered until you flip for the first time.
          Inspect the DOM to verify.
        </Text>
        <Group justify="right" mt="md">
          <Flip.Target>
            <Button>Flip to Back</Button>
          </Flip.Target>
        </Group>
      </Paper>

      <Paper radius="md" withBorder p="lg" shadow="md">
        <h3>Back Card</h3>
        <Text size="sm" c="dimmed">
          This content was lazily mounted on first flip.
        </Text>
        <Flip.Target>
          <Button variant="outline">Flip to Front</Button>
        </Flip.Target>
      </Paper>
    </Flip>
  );
}

Disabled

You can disable the flip interaction by setting the disabled prop to true. When disabled, Flip.Target clicks and toggleFlip calls are ignored.

Front Card

The flip is disabled, click the switch to enable it

Back Card

import { useState } from 'react';
import { Flip } from '@gfazioli/mantine-flip';
import { Button, Group, Paper, Switch } from '@mantine/core';

function Demo() {
  const [disabled, setDisabled] = useState(true);

  return (
    <>
      <Group mb="md">
        <Switch
          checked={disabled}
          onChange={(event) => setDisabled(event.currentTarget.checked)}
          label="Disabled"
        />
      </Group>

      <Flip h={200} w={400} disabled={disabled}>
        <Paper radius="md" withBorder p="lg" shadow="md">
          <h3>Front Card</h3>
          <p>The flip is disabled, click the switch to enable it</p>
          <Group justify="right">
            <Flip.Target>
              <Button>Flip to Back</Button>
            </Flip.Target>
          </Group>
        </Paper>

        <Paper radius="md" withBorder p="lg" shadow="md">
          <h3>Back Card</h3>
          <Flip.Target>
            <Button variant="outline">Flip to Front</Button>
          </Flip.Target>
        </Paper>
      </Flip>
    </>
  );
}

onTransitionEnd

The onTransitionEnd callback is called when the flip animation completes. This is useful for triggering actions after the flip, such as focusing an input or fetching data.

Front Card

Flip to trigger onTransitionEnd

Back Card

Flip again

Transitions completed: 0
import { useState } from 'react';
import { Flip } from '@gfazioli/mantine-flip';
import { Badge, Button, Group, Paper, Stack, Text } from '@mantine/core';

function Demo() {
  const [count, setCount] = useState(0);

  return (
    <Stack align="center">
      <Flip
        h={200}
        w={400}
        onTransitionEnd={() => setCount((c) => c + 1)}
      >
        <Paper radius="md" withBorder p="lg" shadow="md">
          <h3>Front Card</h3>
          <Text size="sm" c="dimmed">Flip to trigger onTransitionEnd</Text>
          <Group justify="right" mt="md">
            <Flip.Target>
              <Button>Flip</Button>
            </Flip.Target>
          </Group>
        </Paper>

        <Paper radius="md" withBorder p="lg" shadow="md">
          <h3>Back Card</h3>
          <Text size="sm" c="dimmed">Flip again</Text>
          <Group justify="right" mt="md">
            <Flip.Target>
              <Button variant="outline">Flip</Button>
            </Flip.Target>
          </Group>
        </Paper>
      </Flip>

      <Badge size="lg" variant="light">
        Transitions completed: {count}
      </Badge>
    </Stack>
  );
}

Swipeable

Enable swipe gestures on touch devices with the swipeable prop. The swipe direction follows the direction prop automatically (horizontal by default). You can also customize the minimum swipe distance with swipeThreshold (default 50px).

Front Card

Swipe horizontally to flip, or use the button below.

Back Card

Swipe again to flip back.

import { Flip } from '@gfazioli/mantine-flip';
import { Button, Paper, Text } from '@mantine/core';

function Demo() {
  return (
    <Flip h={200} w={300} swipeable>
      <Paper radius="md" withBorder p="lg" shadow="md" h="100%">
        <h3>Front Card</h3>
        <Text size="sm" c="dimmed">
          Swipe horizontally to flip, or use the button below.
        </Text>
        <Flip.Target>
          <Button mt="md">Flip</Button>
        </Flip.Target>
      </Paper>

      <Paper radius="md" withBorder p="lg" shadow="md" h="100%">
        <h3>Back Card</h3>
        <Text size="sm" c="dimmed">
          Swipe again to flip back.
        </Text>
        <Flip.Target>
          <Button variant="outline" mt="md">Flip Back</Button>
        </Flip.Target>
      </Paper>
    </Flip>
  );
}

Flip Target

You can use Flip.Target to make any element clickable to toggle the flip state. This is useful when you want to trigger the flip from a button or a specific area of the card.

This card has multiple targets

Text Target

Back Side

import { Flip } from '@gfazioli/mantine-flip';
import { Button, Group, Paper, Text } from '@mantine/core';

function Demo() {
  return (
    <Group justify="center">
      <Flip w={300} h={200}>
        <Paper shadow="md" p="xl" withBorder w="100%" h="100%">
          <Text>This card has multiple targets</Text>
          
          <Group mt="xl">
            <Flip.Target>
              <Button>Button Target</Button>
            </Flip.Target>
            
            <Flip.Target>
              <Text style={{ cursor: 'pointer' }} td="underline" c="blue">
                Text Target
              </Text>
            </Flip.Target>
          </Group>
        </Paper>

        <Paper shadow="md" p="xl" withBorder w="100%" h="100%">
          <Text>Back Side</Text>
          <Flip.Target>
            <Button mt="xl" color="gray">
              Go Back
            </Button>
          </Flip.Target>
        </Paper>
      </Flip>
    </Group>
  );
}

Styled Flip component

You can style the Flip component using the classNames prop to target specific inner elements. This allows for granular customization of the component's appearance.

Front Card

Back Card

import { Flip } from '@gfazioli/mantine-flip';

function Demo() {
  return (
    <Flip h={200} w={200}{{props}}>
      <Paper radius="md" withBorder p="lg" shadow="md">
        <h3>Front Card</h3>
        <Flip.Target>
          <Button>Show Back</Button>
        </Flip.Target>
      </Paper>

      <Paper radius="md" withBorder p="lg" shadow="md">
        <h3>Back Card</h3>
        <Flip.Target>
          <Button>Show Front</Button>
        </Flip.Target>
      </Paper>
    </Flip>
  );
}

Styles API

Flip supports Styles API, you can add styles to any inner element of the component with classNames prop. Follow Styles API documentation to learn more.

You can customize the appearance of the Flip component using the Styles API. This allows you to modify styles for various parts of the component, such as the container, front face, back face, and other inner elements.

Front Card

Back Card

Component Styles API

Hover over selectors to highlight corresponding elements

/*
 * Hover over selectors to apply outline styles
 *
 */

Example: Credit card

The Bank

Press ESC to flip back

import { useEffect, useState } from 'react';
import { Flip } from '@gfazioli/mantine-flip';
import {
  Container,
  getGradient,
  Group,
  Paper,
  Stack,
  Text,
  TextInput,
  Title,
  useMantineColorScheme,
  useMantineTheme,
} from '@mantine/core';
import { MonthPickerInput } from '@mantine/dates';
import { useDisclosure, useHotkeys } from '@mantine/hooks';

function Demo() {
  const [flipped, { toggle, close, open }] = useDisclosure(false);
  const [mounted, setMounted] = useState(false);

  const theme = useMantineTheme();
  const { colorScheme } = useMantineColorScheme();
  useHotkeys([['escape', close]]);

  useEffect(() => {
    setMounted(true);
  }, []);

  function FrontCreditCard() {
    return (
      <Paper
        onClick={() => open()}
        style={{ cursor: 'pointer' }}
        bg={getGradient({ deg: 180, from: 'blue', to: 'cyan.7' }, theme)}
        w={400}
        h={220}
        withBorder
        shadow="md"
        p={30}
        radius="md"
      >
        <Stack>
          <Title order={3} c="white" style={{ textAlign: 'right' }}>
            The Bank
          </Title>
          <Paper
            w={60}
            h={40}
            radius="sm"
            shadow="none"
            p={10}
            bg={getGradient({ deg: 45, from: 'yellow.1', to: 'yellow.6' }, theme)}
          />
        </Stack>
      </Paper>
    );
  }

  function BackCreditCard() {
    return (
      <Paper
        bg={
          !mounted || colorScheme === 'light'
            ? getGradient({ deg: 180, from: 'gray.1', to: 'indigo.1' }, theme)
            : getGradient({ deg: 180, from: 'dark.8', to: 'dark.9' }, theme)
        }
        w={400}
        h={220}
        withBorder
        shadow="md"
        p={30}
        radius="md"
      >
        <Stack>
          <TextInput
            label="Number"
            onKeyUp={(event) => {
              if (event.key === 'Escape') {
                event.preventDefault();
                close();
              }
            }}
            type="tel"
            pattern="[0-9\s]{13,19}"
            autoComplete="cc-number"
            maxLength={16}
            placeholder="xxxx xxxx xxxx xxxx"
            required
          />
          <Group>
            <MonthPickerInput
              w={100}
              required
              label="Expire"
              placeholder="MM/YY"
              valueFormat="MM/YY"
            />
            <TextInput w={100} label="CVV" placeholder="" required />
          </Group>
          <Group justify="right">
            <Text fs={'italic'} c="dimmed" size="xs">
              Press ESC to flip back
            </Text>
          </Group>
        </Stack>
      </Paper>
    );
  }

  return (
    <Container size={420} my={40}>
      <Flip h={200} w={400} flipped={flipped} mt={30}>
        <FrontCreditCard />
        <BackCreditCard />
      </Flip>
    </Container>
  );
}

Example: Signin form

Click on "Create account" to flip the card.

Welcome back!

Do not have an account yet?

function Demo() {

  const [flipped, setFlipped] = useState(false);

  function SignIn() {
    return (
        <Paper withBorder shadow="md" p={30} radius="md">
          <TextInput label="Email" placeholder="you@mantine.dev" required />
          <PasswordInput label="Password" placeholder="Your password" required mt="md" />
          <Group justify="space-between" mt="lg">
            <Checkbox label="Remember me" />
            <Anchor component="button" size="sm">
              Forgot password?
            </Anchor>
          </Group>
          <Button fullWidth mt="xl">
            Sign in
          </Button>
        </Paper>
    );
  }

  function SignUp() {
    return (
        <Paper withBorder shadow="md" p={30} radius="md">
          <TextInput label="Email" placeholder="you@mantine.dev" required />
          <PasswordInput label="Password" placeholder="Your password" required mt="md" />
          <PasswordInput label="Confirm Password" placeholder="Your password" required mt="md" />
          <Button fullWidth mt="xl">
            Sign Up
          </Button>
        </Paper>
    );
  }

  return (
    <Container size={420} my={40}>
      <Title ta="center" className={classes.title}>
      {!flipped ? "Welcome back!" : "Create an account"}
      </Title>
      
      {!flipped ?
        <Text c="dimmed" size="sm" ta="center" mt={5}>
          Do not have an account yet?{' '}
          <Anchor size="sm" component="button" onClick={()=>setFlipped(true)}>
            Create account
          </Anchor>
        </Text> :
        <Text c="dimmed" size="sm" ta="center" mt={5}>
          Do you already have an account?{' '}
          <Anchor size="sm" component="button" onClick={()=>setFlipped(false)}>
            Sign in
          </Anchor>
        </Text>
      }
      
      <Flip h={300} w={400} flipped={flipped} mt={30}>
        <SignIn />
        <SignUp />
      </Flip>
      
    </Container>
  );
}

Example: Profile Card

Jane Fingerlicker

Fullstack Engineer

34K

Followers

187

Following

1.9K

Posts

Contact Info

jane@fingerlicker.dev

Socials

React
TypeScript
Mantine
import { Flip } from '@gfazioli/mantine-flip';
import { Avatar, Badge, Button, Card, Center, Group, Text, ActionIcon, useMantineTheme } from '@mantine/core';
import { IconBrandGithub, IconBrandTwitter, IconBrandLinkedin, IconX } from '@tabler/icons-react';

function Demo() {
  const theme = useMantineTheme();

  return (
    <Center>
      <Flip w={300} h={400}>
        {/* Front Face */}
        <Card shadow="sm" padding="lg" radius="md" withBorder h="100%">
          <Card.Section>
            <div
              style={{
                height: 100,
                backgroundColor: theme.colors.blue[6],
              }}
            />
          </Card.Section>

          <Avatar
            src="https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-1.png"
            size={80}
            radius={80}
            mx="auto"
            mt={-30}
            style={{ border: `2px solid ${theme.white}` }}
          />

          <Text ta="center" fz="lg" fw={500} mt="sm">
            Jane Fingerlicker
          </Text>
          <Text ta="center" c="dimmed" fz="sm">
            Fullstack Engineer
          </Text>

          <Group mt="md" justify="center" gap={30}>
            <div style={{ textAlign: 'center' }}>
              <Text ta="center" fw={500} fz="lg">
                34K
              </Text>
              <Text ta="center" fz="xs" c="dimmed">
                Followers
              </Text>
            </div>
            <div style={{ textAlign: 'center' }}>
              <Text ta="center" fw={500} fz="lg">
                187
              </Text>
              <Text ta="center" fz="xs" c="dimmed">
                Following
              </Text>
            </div>
            <div style={{ textAlign: 'center' }}>
              <Text ta="center" fw={500} fz="lg">
                1.9K
              </Text>
              <Text ta="center" fz="xs" c="dimmed">
                Posts
              </Text>
            </div>
          </Group>

          <Flip.Target>
            <Button fullWidth radius="md" mt="xl" size="md" variant="default">
              View Profile
            </Button>
          </Flip.Target>
        </Card>

        {/* Back Face */}
        <Card shadow="sm" padding="lg" radius="md" withBorder h="100%" style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
            <div>
                <Group justify="space-between" mb="xs">
                    <Text fw={500}>Contact Info</Text>
                    <Flip.Target>
                        <ActionIcon variant="subtle" color="gray">
                            <IconX size={16} />
                        </ActionIcon>
                    </Flip.Target>
                </Group>
                
                <Text size="sm" c="dimmed" mb="md">
                    jane@fingerlicker.dev
                </Text>

                <Text fw={500} mb="xs">Socials</Text>
                <Group gap="md">
                    <ActionIcon size="lg" variant="default" radius="xl">
                        <IconBrandGithub size={18} />
                    </ActionIcon>
                    <ActionIcon size="lg" variant="default" radius="xl">
                        <IconBrandTwitter size={18} />
                    </ActionIcon>
                    <ActionIcon size="lg" variant="default" radius="xl">
                        <IconBrandLinkedin size={18} />
                    </ActionIcon>
                </Group>
            </div>

            <Group gap="xs" mt="xl">
                <Badge color="pink" variant="light">React</Badge>
                <Badge color="blue" variant="light">TypeScript</Badge>
                <Badge color="cyan" variant="light">Mantine</Badge>
            </Group>
            
            <Flip.Target>
                <Button fullWidth mt="md">
                    Back to Card
                </Button>
            </Flip.Target>
        </Card>
      </Flip>
    </Center>
  );
}

Example: Grid Widget

Given that the Flip component behaves like a MacOS Widget, it is important to understand where and how to set the dimensions to avoid overflow issues.

Test 1

Test 1

Test 1 description

Test 1

Test 1 description

Additional information about Test 1.

Category
Test 2

Test 2

Test 2 description

Test 2

Test 2 description

Additional information about Test 2.

Category
Test 3

Test 3

Test 3 description

Test 3

Test 3 description

Additional information about Test 3.

Category
Test 4

Test 4

Test 4 description

Test 4

Test 4 description

Additional information about Test 4.

Category
Test 5

Test 5

Test 5 description

Test 5

Test 5 description

Additional information about Test 5.

Category
Test 6

Test 6

Test 6 description

Test 6

Test 6 description

Additional information about Test 6.

Category
Test 7

Test 7

Test 7 description

Test 7

Test 7 description

Additional information about Test 7.

Category
Test 8

Test 8

Test 8 description

Test 8

Test 8 description

Additional information about Test 8.

Category
Test 9

Test 9

Test 9 description

Test 9

Test 9 description

Additional information about Test 9.

Category
import { Flip } from '@gfazioli/mantine-flip';
import { Badge, Button, Card, Flex, Image, SimpleGrid, Stack, Text, Title } from '@mantine/core';

import testData from './data';

function Demo() {
  const WIDGET_HEIGHT = 360;
  const IMAGE_HEIGHT = 200;

  return (
    <SimpleGrid cols={3} verticalSpacing="lg">
      {testData.map((item) => (
        <Flip key={item.title} h={WIDGET_HEIGHT} directionFlipIn="positive">
          <Card h={WIDGET_HEIGHT} shadow="sm" radius="md" withBorder>
            <Card.Section>
              <Image h={IMAGE_HEIGHT} src={item.image} alt={item.title} />
            </Card.Section>

            <Stack mt={8}>
              <Title>{item.title}</Title>
              <Text>{item.description}</Text>
              <Flex justify="right">
                <Flip.Target>
                  <Button>More info</Button>
                </Flip.Target>
              </Flex>
            </Stack>
          </Card>
          <Card h={WIDGET_HEIGHT} shadow="sm" radius="md" withBorder>
            <Stack mt={8} justify="space-between" h="100%">
              <Stack>
                <Title>{item.title}</Title>
                <Text>{item.description}</Text>
                <Text>Additional information about {item.title}.</Text>
                <Badge color="green" variant="light">
                  Category
                </Badge>
              </Stack>

              <Flex justify="right">
                <Flip.Target>
                  <Button size="xs" rightSection={<IconArrowRight />} variant="outline">
                    Back
                  </Button>
                </Flip.Target>
              </Flex>
            </Stack>
          </Card>
        </Flip>
      ))}
    </SimpleGrid>
  );
}