GitHub

@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';

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.

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>
  );
}

Uncontrollded

Front Card

The front card

Back Card

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

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

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

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

  </Flip>
  );
}

Controllded

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>
  );
}

Inital 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>
  );
}

More examples

Credit card

The Bank

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

  const theme = useMantineTheme();

  function FrontCreditCard() {
    return (
      <Paper
        onClick={() => setFlipped(true)}
        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={getGradient({ deg: 180, from: 'gray.1', to: 'indigo.1' }, theme)}
        w={400}
        h={220}
        withBorder
        shadow="md"
        p={30}
        radius="md"
        autoFocus
      >
        <Stack>
          <TextInput
            label="Number"
            type="tel"
            pattern="[0-9s]{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>
        </Stack>
      </Paper>
    );
  }

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

Signin form

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={200} w={400} flipped={flipped} mt={30}>
        <SignIn />
        <SignUp />
      </Flip>
      
    </Container>
  );
}