Claude-skill-registry-data mantine
Builds React applications with Mantine's 100+ components, hooks, and form library. Use when creating feature-rich UIs with built-in dark mode, accessibility, and TypeScript support.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry-data
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry-data "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/mantine" ~/.claude/skills/majiayu000-claude-skill-registry-data-mantine && rm -rf "$T"
manifest:
data/mantine/SKILL.mdsource content
Mantine
Full-featured React component library with 100+ customizable components and 50+ hooks.
Quick Start
npm install @mantine/core @mantine/hooks npm install -D postcss postcss-preset-mantine postcss-simple-vars
// postcss.config.cjs module.exports = { plugins: { 'postcss-preset-mantine': {}, 'postcss-simple-vars': { variables: { 'mantine-breakpoint-xs': '36em', 'mantine-breakpoint-sm': '48em', 'mantine-breakpoint-md': '62em', 'mantine-breakpoint-lg': '75em', 'mantine-breakpoint-xl': '88em', }, }, }, };
// App.tsx import '@mantine/core/styles.css'; import { MantineProvider, createTheme } from '@mantine/core'; const theme = createTheme({ primaryColor: 'blue', fontFamily: 'Inter, sans-serif', }); function App() { return ( <MantineProvider theme={theme}> <YourApp /> </MantineProvider> ); }
// Usage import { Button, TextInput, Group, Stack } from '@mantine/core'; function Demo() { return ( <Stack> <TextInput label="Email" placeholder="you@example.com" /> <Group> <Button>Submit</Button> <Button variant="outline">Cancel</Button> </Group> </Stack> ); }
Core Components
Button
import { Button, ActionIcon } from '@mantine/core'; import { IconSettings } from '@tabler/icons-react'; // Variants <Button variant="filled">Filled</Button> <Button variant="light">Light</Button> <Button variant="outline">Outline</Button> <Button variant="subtle">Subtle</Button> <Button variant="transparent">Transparent</Button> <Button variant="white">White</Button> // Sizes <Button size="xs">Extra Small</Button> <Button size="sm">Small</Button> <Button size="md">Medium</Button> <Button size="lg">Large</Button> <Button size="xl">Extra Large</Button> // Colors <Button color="blue">Blue</Button> <Button color="red">Red</Button> <Button color="green">Green</Button> // With icons <Button leftSection={<IconSettings size={16} />}>Settings</Button> <Button rightSection={<IconArrow size={16} />}>Next</Button> // Loading <Button loading>Processing...</Button> // Icon button <ActionIcon variant="filled" size="lg"> <IconSettings size={18} /> </ActionIcon>
TextInput
import { TextInput, PasswordInput, Textarea, NumberInput } from '@mantine/core'; <TextInput label="Email" description="We'll never share your email" placeholder="you@example.com" required error="Invalid email" /> <PasswordInput label="Password" placeholder="Enter password" visible={visible} onVisibilityChange={toggle} /> <Textarea label="Message" placeholder="Your message" autosize minRows={3} maxRows={6} /> <NumberInput label="Amount" placeholder="Enter amount" min={0} max={100} step={5} prefix="$" thousandSeparator="," />
Select and MultiSelect
import { Select, MultiSelect, Combobox } from '@mantine/core'; <Select label="Framework" placeholder="Pick one" data={['React', 'Vue', 'Angular', 'Svelte']} searchable clearable /> <Select label="User" data={[ { value: '1', label: 'John Doe' }, { value: '2', label: 'Jane Smith' }, ]} /> <MultiSelect label="Technologies" placeholder="Select technologies" data={['TypeScript', 'JavaScript', 'Python', 'Rust']} searchable maxSelectedValues={3} />
Modal and Drawer
import { Modal, Button } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; function ModalDemo() { const [opened, { open, close }] = useDisclosure(false); return ( <> <Modal opened={opened} onClose={close} title="Authentication"> Modal content here... </Modal> <Button onClick={open}>Open modal</Button> </> ); } // Drawer import { Drawer } from '@mantine/core'; <Drawer opened={opened} onClose={close} title="Navigation" position="left" // left, right, top, bottom size="md" > Drawer content... </Drawer>
Notifications
npm install @mantine/notifications
import '@mantine/notifications/styles.css'; import { Notifications, notifications } from '@mantine/notifications'; // Add to app root <MantineProvider> <Notifications position="top-right" /> <App /> </MantineProvider> // Show notification notifications.show({ title: 'Success', message: 'Your changes have been saved', color: 'green', autoClose: 5000, }); // Update existing notification const id = notifications.show({ loading: true, title: 'Loading...', message: 'Please wait', autoClose: false, }); notifications.update({ id, loading: false, title: 'Complete', message: 'Data loaded successfully', color: 'green', autoClose: 3000, });
Tabs
import { Tabs } from '@mantine/core'; <Tabs defaultValue="gallery"> <Tabs.List> <Tabs.Tab value="gallery">Gallery</Tabs.Tab> <Tabs.Tab value="messages">Messages</Tabs.Tab> <Tabs.Tab value="settings">Settings</Tabs.Tab> </Tabs.List> <Tabs.Panel value="gallery" pt="md"> Gallery content </Tabs.Panel> <Tabs.Panel value="messages" pt="md"> Messages content </Tabs.Panel> <Tabs.Panel value="settings" pt="md"> Settings content </Tabs.Panel> </Tabs>
Card
import { Card, Image, Text, Badge, Button, Group } from '@mantine/core'; <Card shadow="sm" padding="lg" radius="md" withBorder> <Card.Section> <Image src="/product.jpg" height={160} alt="Product" /> </Card.Section> <Group justify="space-between" mt="md" mb="xs"> <Text fw={500}>Product Name</Text> <Badge color="pink">On Sale</Badge> </Group> <Text size="sm" c="dimmed"> Product description goes here. </Text> <Button fullWidth mt="md" radius="md"> Add to Cart </Button> </Card>
Forms
npm install @mantine/form
import { useForm } from '@mantine/form'; import { TextInput, Button, Stack } from '@mantine/core'; function ContactForm() { const form = useForm({ mode: 'uncontrolled', initialValues: { name: '', email: '', message: '', }, validate: { name: (value) => value.length < 2 ? 'Name is too short' : null, email: (value) => /^\S+@\S+$/.test(value) ? null : 'Invalid email', message: (value) => value.length < 10 ? 'Message too short' : null, }, }); return ( <form onSubmit={form.onSubmit((values) => console.log(values))}> <Stack> <TextInput label="Name" placeholder="Your name" key={form.key('name')} {...form.getInputProps('name')} /> <TextInput label="Email" placeholder="your@email.com" key={form.key('email')} {...form.getInputProps('email')} /> <Textarea label="Message" placeholder="Your message" key={form.key('message')} {...form.getInputProps('message')} /> <Button type="submit">Submit</Button> </Stack> </form> ); }
Form with Zod Validation
import { useForm, zodResolver } from '@mantine/form'; import { z } from 'zod'; const schema = z.object({ name: z.string().min(2, 'Name must be at least 2 characters'), email: z.string().email('Invalid email'), age: z.number().min(18, 'Must be 18 or older'), }); const form = useForm({ mode: 'uncontrolled', initialValues: { name: '', email: '', age: 18 }, validate: zodResolver(schema), });
Hooks
import { useDisclosure, useToggle, useDebouncedValue, useClipboard, useLocalStorage, useMediaQuery, useClickOutside, useHotkeys, useForm, } from '@mantine/hooks'; // Disclosure (modals, menus) const [opened, { open, close, toggle }] = useDisclosure(false); // Toggle between values const [value, toggle] = useToggle(['light', 'dark']); // Debounced value const [search, setSearch] = useState(''); const [debounced] = useDebouncedValue(search, 300); // Clipboard const clipboard = useClipboard({ timeout: 2000 }); clipboard.copy('Text to copy'); clipboard.copied // true after copy // Local storage const [value, setValue] = useLocalStorage({ key: 'user-preference', defaultValue: 'dark', }); // Media query const isMobile = useMediaQuery('(max-width: 768px)'); // Click outside const ref = useClickOutside(() => setOpened(false)); // Keyboard shortcuts useHotkeys([ ['mod+K', () => openSearch()], ['mod+S', () => saveDocument()], ['Escape', () => closeModal()], ]);
Theming
Custom Theme
import { createTheme, MantineProvider } from '@mantine/core'; const theme = createTheme({ // Primary color primaryColor: 'brand', primaryShade: { light: 6, dark: 8 }, // Custom colors (10 shades each) colors: { brand: [ '#e6f2ff', '#b3d9ff', '#80bfff', '#4da6ff', '#1a8cff', '#0073e6', '#005cb3', '#004480', '#002d4d', '#00161a', ], }, // Typography fontFamily: 'Inter, sans-serif', fontFamilyMonospace: 'Fira Code, monospace', headings: { fontFamily: 'Inter, sans-serif', fontWeight: '600', sizes: { h1: { fontSize: '2.5rem', lineHeight: '1.2' }, h2: { fontSize: '2rem', lineHeight: '1.3' }, }, }, // Spacing scale spacing: { xs: '0.5rem', sm: '0.75rem', md: '1rem', lg: '1.5rem', xl: '2rem', }, // Border radius radius: { xs: '2px', sm: '4px', md: '8px', lg: '16px', xl: '32px', }, defaultRadius: 'md', // Shadows shadows: { xs: '0 1px 2px rgba(0, 0, 0, 0.05)', sm: '0 1px 3px rgba(0, 0, 0, 0.1)', md: '0 4px 6px rgba(0, 0, 0, 0.1)', lg: '0 10px 15px rgba(0, 0, 0, 0.1)', xl: '0 20px 25px rgba(0, 0, 0, 0.15)', }, // Focus styles focusRing: 'auto', // 'auto' | 'always' | 'never' // Other cursorType: 'pointer', // 'default' | 'pointer' autoContrast: true, });
Dark Mode
import { MantineProvider, useMantineColorScheme, Button } from '@mantine/core'; // Provider setup <MantineProvider defaultColorScheme="auto"> <App /> </MantineProvider> // Toggle button function ColorSchemeToggle() { const { colorScheme, toggleColorScheme } = useMantineColorScheme(); return ( <Button onClick={() => toggleColorScheme()}> {colorScheme === 'dark' ? 'Light' : 'Dark'} mode </Button> ); }
Styles API
import { Button, createStyles } from '@mantine/core'; // Using classNames prop <Button classNames={{ root: 'my-button-root', label: 'my-button-label', }} > Styled Button </Button> // Using styles prop <Button styles={{ root: { backgroundColor: 'red' }, label: { color: 'white' }, }} > Inline Styled </Button> // CSS Modules (recommended) // Button.module.css .root { background-color: var(--mantine-color-blue-6); } .label { font-weight: 700; } // Component import classes from './Button.module.css'; <Button classNames={classes}>CSS Modules</Button>
CSS Variables
// Access theme tokens via CSS variables .myComponent { background-color: var(--mantine-color-blue-6); padding: var(--mantine-spacing-md); border-radius: var(--mantine-radius-md); font-size: var(--mantine-font-size-sm); /* Dark mode specific */ @mixin dark { background-color: var(--mantine-color-dark-6); } /* Responsive */ @media (max-width: $mantine-breakpoint-sm) { padding: var(--mantine-spacing-xs); } }
Layout
import { AppShell, Container, Grid, Group, Stack, Flex, SimpleGrid, Center, } from '@mantine/core'; // App shell layout <AppShell header={{ height: 60 }} navbar={{ width: 300, breakpoint: 'sm', collapsed: { mobile: !opened } }} padding="md" > <AppShell.Header>Header</AppShell.Header> <AppShell.Navbar>Navbar</AppShell.Navbar> <AppShell.Main>Content</AppShell.Main> </AppShell> // Container with max width <Container size="md">Content</Container> // Grid <Grid> <Grid.Col span={6}>Half</Grid.Col> <Grid.Col span={6}>Half</Grid.Col> <Grid.Col span={{ base: 12, md: 6, lg: 4 }}>Responsive</Grid.Col> </Grid> // Simple grid (equal columns) <SimpleGrid cols={3}> <div>1</div> <div>2</div> <div>3</div> </SimpleGrid> // Flex layouts <Group justify="space-between" align="center"> <Text>Left</Text> <Text>Right</Text> </Group> <Stack gap="md"> <Text>Item 1</Text> <Text>Item 2</Text> </Stack> <Flex gap="md" wrap="wrap" justify="center"> <Box>Item</Box> <Box>Item</Box> </Flex>
Best Practices
- Use CSS modules - Most performant styling approach
- Leverage hooks -
,useDisclosure
,useDebouncedValue
for common patternsuseForm - Use Styles API - Override component parts with
propclassNames - Theme tokens - Use CSS variables for consistent theming
- Form validation - Use
with Zod for type-safe forms@mantine/form
Reference Files
- references/components.md - Complete component list
- references/hooks.md - All available hooks