Skip to main content
Version: 3.xx.xx

Theme

http://localhost:3000
Live previews only work with the latest documentation.
import { useNavigation, useRouterContext } from '@pankod/refine-core'
import {
List,
Create,
Edit,
Table,
Pagination,
EditButton,
useForm,
TextInput,
} from '@pankod/refine-mantine'
import { useTable, ColumnDef, flexRender } from '@pankod/refine-react-table'

const PostList: React.FC = () => {
const columns = React.useMemo<ColumnDef<IPost>[]>(
() => [
{
id: 'id',
header: 'ID',
accessorKey: 'id',
},
{
id: 'title',
header: 'Title',
accessorKey: 'title',
},
{
id: 'actions',
header: 'Actions',
accessorKey: 'id',
cell: function render({ getValue }) {
return <EditButton hideText recordItemId={getValue() as number} />
},
},
],
[],
)

const {
getHeaderGroups,
getRowModel,
refineCore: { setCurrent, pageCount, current },
} = useTable({
columns,
refineCoreProps: {
initialPageSize: 5,
},
})

return (
<List>
<Table>
<thead>
{getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{getRowModel().rows.map((row) => (
<tr key={row.id}>
{row.getVisibleCells().map((cell) => (
<td key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</Table>
<br />
<Pagination
position="right"
total={pageCount}
page={current}
onChange={setCurrent}
/>
</List>
)
}

const PostEdit: React.FC = () => {
const { saveButtonProps, getInputProps } = useForm({
initialValues: {
title: '',
},
validate: {
title: (value) => (value.length < 2 ? 'Too short title' : null),
},
})

return (
<Edit saveButtonProps={saveButtonProps}>
<form>
<TextInput
mt={8}
label="Title"
placeholder="Title"
{...getInputProps('title')}
/>
</form>
</Edit>
)
}

const PostCreate: React.FC = () => {
const { saveButtonProps, getInputProps } = useForm({
initialValues: {
title: '',
},
validate: {
title: (value) => (value.length < 2 ? 'Too short title' : null),
},
})

return (
<Create saveButtonProps={saveButtonProps}>
<form>
<TextInput
mt={8}
label="Title"
placeholder="Title"
{...getInputProps('title')}
/>
</form>
</Create>
)
}

interface IPost {
id: number
title: string
}

Mantine theme is an object where your application's colors, fonts, spacing, border-radius and other design tokens are stored. You can either create your own theme object or use themes that provide from refine. There are two types of themes: LightTheme and DarkTheme. LightTheme tend to have dark text on a light background, while DarkTheme have light text on a dark background. Theme provides a way to your app's design to meet them.

Refer to the Mantine documentation for more information about theme object. &#8594

Theme customization

<MantineProvider/> component can be used to change theme. It is not required if you decide to use the default theme. You can also use LightTheme and DarkTheme provided by refine.

http://localhost:3000
Live previews only work with the latest documentation.
import { Refine } from '@pankod/refine-core'
import routerProvider from '@pankod/refine-react-router-v6'
import dataProvider from '@pankod/refine-simple-rest'
import {
Layout,
MantineProvider,
Global,
NotificationsProvider,
notificationProvider,
DarkTheme,
} from '@pankod/refine-mantine'

import { PostCreate, PostEdit, PostList } from './pages'

const App = () => {
return (
<MantineProvider theme={DarkTheme} withNormalizeCSS withGlobalStyles>
<Global styles={{ body: { WebkitFontSmoothing: 'auto' } }} />
<NotificationsProvider position="top-right">
<Refine
routerProvider={routerProvider}
dataProvider={dataProvider('https://api.fake-rest.refine.dev')}
notificationProvider={notificationProvider}
Layout={Layout}
resources={[
{
name: 'posts',
list: PostList,
edit: PostEdit,
create: PostCreate,
},
]}
/>
</NotificationsProvider>
</MantineProvider>
)
}

Refer to the <MantineProvider/> documentation for more information. &#8594

Overriding the refine themes

You can override or extend the default refine themes. You can also create your own theme. Let's see how to do this.

http://localhost:3000
Live previews only work with the latest documentation.
import { Refine } from '@pankod/refine-core'
import routerProvider from '@pankod/refine-react-router-v6'
import dataProvider from '@pankod/refine-simple-rest'
import {
Layout,
MantineProvider,
Global,
NotificationsProvider,
notificationProvider,
LightTheme,
} from '@pankod/refine-mantine'

import { PostCreate, PostEdit, PostList } from './pages'

const App = () => {
return (
<MantineProvider
theme={{
...LightTheme,
colors: {
primary: [
'#ECF9F8',
'#C9EEEC',
'#A6E2E1',
'#84D7D5',
'#61CCC9',
'#3EC1BD',
'#329A97',
'#257471',
'#194D4B',
'#0C2726',
],
},
}}
withNormalizeCSS
withGlobalStyles
>
<Global styles={{ body: { WebkitFontSmoothing: 'auto' } }} />
<NotificationsProvider position="top-right">
<Refine
routerProvider={routerProvider}
dataProvider={dataProvider('https://api.fake-rest.refine.dev')}
notificationProvider={notificationProvider}
Layout={Layout}
resources={[
{
name: 'posts',
list: PostList,
edit: PostEdit,
create: PostCreate,
},
]}
/>
</NotificationsProvider>
</MantineProvider>
)
}

Refer to the Mantine colors documentation for more information. &#8594

Theme switching

You can switch between themes as Mantine mentioned in its documentation. You can see an example of using local storage to store the theme below.

http://localhost:3000
Live previews only work with the latest documentation.
import { Refine } from '@pankod/refine-core'
import routerProvider from '@pankod/refine-react-router-v6'
import dataProvider from '@pankod/refine-simple-rest'
import {
Layout,
MantineProvider,
Global,
NotificationsProvider,
notificationProvider,
MantineHeader,
Group,
ActionIcon,
ColorSchemeProvider,
ColorScheme,
LightTheme,
DarkTheme,
useLocalStorage,
useMantineColorScheme,
} from '@pankod/refine-mantine'
import { IconSun, IconMoonStars } from '@tabler/icons'

import { PostCreate, PostEdit, PostList } from './pages'

const Header = () => {
const { colorScheme, toggleColorScheme } = useMantineColorScheme()
const dark = colorScheme === 'dark'

return (
<MantineHeader height={50} p="xs">
<Group position="right">
<ActionIcon
variant="outline"
color={dark ? 'yellow' : 'primary'}
onClick={() => toggleColorScheme()}
title="Toggle color scheme"
>
{dark ? <IconSun /> : <IconMoonStars />}
</ActionIcon>
</Group>
</MantineHeader>
)
}

const App = () => {
const [colorScheme, setColorScheme] = useLocalStorage<ColorScheme>({
key: 'mantine-color-scheme',
defaultValue: 'light',
getInitialValueInEffect: true,
})

const toggleColorScheme = (value?: ColorScheme) =>
setColorScheme(value || (colorScheme === 'dark' ? 'light' : 'dark'))

return (
<ColorSchemeProvider
colorScheme={colorScheme}
toggleColorScheme={toggleColorScheme}
>
<MantineProvider
theme={colorScheme === 'dark' ? DarkTheme : LightTheme}
withNormalizeCSS
withGlobalStyles
>
<Global styles={{ body: { WebkitFontSmoothing: 'auto' } }} />
<NotificationsProvider position="top-right">
<Refine
routerProvider={routerProvider}
dataProvider={dataProvider('https://api.fake-rest.refine.dev')}
notificationProvider={notificationProvider}
Layout={Layout}
Header={Header}
resources={[
{
name: 'posts',
list: PostList,
edit: PostEdit,
create: PostCreate,
},
]}
/>
</NotificationsProvider>
</MantineProvider>
</ColorSchemeProvider>
)
}

Refer to the Mantine dark theme documentation for more information. &#8594