Mantine
02 / 02

Forms, Overlays, Hooks & Notifications

Mantine: Forms, Overlays, Hooks & Notifications

@mantine/form

import { useForm } from '@mantine/form';
import { TextInput, Button } from '@mantine/core';

function SignupForm() {
  const form = useForm({
    initialValues: { email: '', password: '' },
    validate: {
      email: (value) => (/^\S+@\S+$/.test(value) ? null : 'Invalid email'),
      password: (value) => (value.length >= 8 ? null : 'Min 8 characters'),
    },
  });

  return (
    <form onSubmit={form.onSubmit((values) => console.log(values))}>
      {/* getInputProps wires value/onChange/error directly into the input */}
      <TextInput label="Email" {...form.getInputProps('email')} />
      <TextInput label="Password" type="password" {...form.getInputProps('password')} />
      <Button type="submit">Sign up</Button>
    </form>
  );
}

Overlays: useDisclosure + Modal

import { useDisclosure } from '@mantine/hooks';
import { Modal, Button } from '@mantine/core';

function DeleteConfirmation() {
  const [opened, { open, close }] = useDisclosure(false);

  return (
    <>
      <Button onClick={open} color="red">Delete</Button>
      <Modal opened={opened} onClose={close} title="Confirm delete">
        <Button onClick={close}>Cancel</Button>
        <Button color="red" onClick={handleDelete}>Delete</Button>
      </Modal>
    </>
  );
}
// Mantine components ship with accessibility handled by default --
// focus trapping in Modal, correct ARIA roles, keyboard navigation --
// so this doesn't need to be reimplemented per component.

@mantine/hooks

import { useLocalStorage, useDebouncedValue, useMediaQuery, useClickOutside } from '@mantine/hooks';

// Usable independently of Mantine's components, in any React code
const [theme, setTheme] = useLocalStorage({ key: 'theme', defaultValue: 'light' });
const [debouncedSearch] = useDebouncedValue(search, 300);
const isMobile = useMediaQuery('(max-width: 768px)');
const ref = useClickOutside(() => setOpen(false));

Notifications & Package Structure

import { notifications, Notifications } from '@mantine/notifications';

// Mounted once near the app root
<Notifications />

// Triggered imperatively from anywhere -- an API handler, a form submit
notifications.show({
  title: 'Saved',
  message: 'Your changes were saved.',
  color: 'green',
});
  • @mantine/core: the foundational package (MantineProvider, base components, theming) most other Mantine packages build on.

  • @mantine/dates, @mantine/form, @mantine/notifications, @mantine/charts: separate installable packages -- only bundle what your app actually uses.

  • Trade-off vs. unstyled primitives (Radix + Tailwind): Mantine's breadth speeds up building common UI at the cost of a larger footprint and more opinionated default styling to override.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free