﻿# Mantine UI

`@lazarv/react-server` is compatible with [Mantine](https://mantine.dev/), a full-featured React component library. You can use Mantine components in your client components with server-side rendering support, PostCSS configuration for Mantine's styling system, and the `MantineProvider` for theming.

## Installation

Install Mantine and its required PostCSS dependencies:

```sh
pnpm add @mantine/core @mantine/hooks
pnpm add -D postcss postcss-preset-mantine postcss-simple-vars
```

## PostCSS configuration

Mantine requires a PostCSS configuration with the `postcss-preset-mantine` plugin and breakpoint variables:

```js filename="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",
      },
    },
  },
};
```

## Provider setup

Import the core Mantine styles and wrap your app with `MantineProvider` in your root layout. Include the `ColorSchemeScript` in the `` to prevent a flash of unstyled content:

```tsx filename="src/pages/layout.tsx"
import "@mantine/core/styles.css";

import { ColorSchemeScript, createTheme, MantineProvider } from "@mantine/core";

const theme = createTheme({
  /** Put your mantine theme override here */
});

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" data-mantine-color-scheme="light" suppressHydrationWarning>
      <head>
        <ColorSchemeScript />
      </head>
      <body suppressHydrationWarning>
        <MantineProvider theme={theme}>
          {children}
        </MantineProvider>
      </body>
    </html>
  );
}
```

## Using components

Mantine components that use React hooks or browser APIs must be used in client components. Create a client component and import the Mantine components you need:

```tsx filename="src/components/Counter.tsx"
"use client";

import { useState } from "react";
import { Button, Group, Text } from "@mantine/core";

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

  return (
    <Group>
      <Button onClick={() => setCount((c) => c - 1)}>-</Button>
      <Text>{count}</Text>
      <Button onClick={() => setCount((c) => c + 1)}>+</Button>
    </Group>
  );
}
```

Then use the client component from your server component page:

```tsx filename="src/pages/index.tsx"
import { Counter } from "../components/Counter";

export default function HomePage() {
  return <Counter />;
}
```

## Navigation

To use Mantine's navigation components like `NavLink` with `@lazarv/react-server`'s client-side navigation, pass the runtime's `Link` component via the `component` prop:

```tsx filename="src/components/MainNavigation.tsx"
"use client";

import { NavLink } from "@mantine/core";
import { Link, usePathname } from "@lazarv/react-server/navigation";

export function MainNavigation() {
  const pathname = usePathname();

  return (
    <>
      <NavLink
        component={Link}
        to="/"
        label="Home"
        active={pathname === "/"}
      />
      <NavLink
        component={Link}
        to="/about"
        label="About"
        active={pathname === "/about"}
      />
    </>
  );
}
```

## Extension packages

Mantine offers many extension packages for additional functionality. Import their styles in the pages or layouts where they are used:

```tsx filename="src/pages/dates.tsx"
import "@mantine/dates/styles.css";

import { MyDates } from "../components/MyDates";

export default function DatesPage() {
  return <MyDates />;
}
```

Some commonly used Mantine extensions and their style imports:

| Package | Style import |
|---------|-------------|
| `@mantine/dates` | `@mantine/dates/styles.css` |
| `@mantine/charts` | `@mantine/charts/styles.css` |
| `@mantine/notifications` | `@mantine/notifications/styles.css` |
| `@mantine/code-highlight` | `@mantine/code-highlight/styles.css` |
| `@mantine/carousel` | `@mantine/carousel/styles.css` |
| `@mantine/spotlight` | `@mantine/spotlight/styles.css` |
| `@mantine/nprogress` | `@mantine/nprogress/styles.css` |
| `@mantine/tiptap` | `@mantine/tiptap/styles.css` |
| `@mantine/dropzone` | `@mantine/dropzone/styles.css` |

## Client-only components

Some components (like charts that depend on browser APIs) cannot be server-side rendered. Use `ClientOnly` from `@lazarv/react-server/client` to render them only on the client:

```tsx filename="src/pages/charts.tsx"
import "@mantine/charts/styles.css";

import { ClientOnly } from "@lazarv/react-server/client";
import { MyAreaChart } from "../components/MyAreaChart";

export default function ChartsPage() {
  return (
    <ClientOnly>
      <MyAreaChart />
    </ClientOnly>
  );
}
```

> Check out the [Mantine example](https://github.com/lazarv/react-server/tree/main/examples/mantine) to see a complete example of using Mantine UI with `@lazarv/react-server`.