I’ve been using Mantine for one of my side projects and came across this easy way to use the Theme hooks to help responsiveness.
Lets say you are using something like Tabs and you want to have a vertical
layout on a larger screen and a horizontal
layout in a smaller screen. Unfortunately, the Tab orientation is set with a component prop, so, as far as I know, there’s no way to toggle the orientation using the Styles API. There are two tools we can use together to set the initial orientation, based on the viewport (“screen”) size and the defined breakpoints. Here’s the code:
import { Paper, Tabs, useMantineTheme } from '@mantine/core';
import { useViewportSize } from '@mantine/hooks';
export default function ResponsiveTabs() {
const { width } = useViewportSize(); // height is also available here
const theme = useMantineTheme();
const breakpoint = Boolean(width >= theme.breakpoints.md);
const padX = breakpoint ? 10 : 0;
const padY = breakpoint ? 0 : 10;
return (
<Tabs
variant="outline"
orientation={breakpoint ? 'vertical' : 'horizontal'}
defaultValue="start"
>
<Tabs.List>
<Tabs.Tab value="start">
First Tab
</Tabs.Tab>
<Tabs.Tab value="middle">
Second Tab
</Tabs.Tab>
<Tabs.Tab value="end">
Last Tab
</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="start">
<Paper px={padX} py={padY}>
First tab content
</Paper>
</Tabs.Panel>
<Tabs.Panel value="middle">
<Paper px={padX} py={padY}>
Second tab content
</Paper>
</Tabs.Panel>
<Tabs.Panel value="end">
<Paper px={padX} py={padY}>
Last tab content
</Paper>
</Tabs.Panel>
</Tabs>
);
}
What’s going on here?
We use the useViewportSize() hook to get the viewport (screen) width
:
const { width } = useViewportSize();
We then use the useMantineTheme() hook to set the theme
object, which provides us with the theme’s defined breakpoints. The width
and the breakpoints are both numbers, so we can easily compare a specific breakpoint width to the current viewport width.
const theme = useMantineTheme();
const breakpoint = Boolean(width >= theme.breakpoints.md);
I chose the Medium breakpoint for this example, but you could use sm
(small) or even lg
(large) if desired. Now we need to conditionally set the Tab orientation:
<Tabs
variant="outline"
orientation={breakpoint ? 'vertical' : 'horizontal'}
defaultValue="start"
>
The above will set the Tab orientation to vertical
if the screen size is the same as md
(medium) or larger. If the screen size is sm
(small) or smaller, then the Tab orientation will be horizontal
.
If you are using the Styles API, you could easily adjust other styling, but for simplicity I decided to use the same condition to set padding. For vertical Tabs, some padding on the sides is more appealing. For horizontal Tabs, I prefer some padding on the top and bottom.
<Tabs.Panel value="middle">
<Paper px={breakpoint ? 10 : 0} py={breakpoint ? 0 : 10}>
Second tab content
This prevents creating another dependency, which is basically adding no further benefit. If you are already using the createStyles() hook, then it makes more sense to put it in a class instead. I have no further need for createStyles(), so I just put each padding type in constants in the original code example.
So that’s it, that’s how you can use the Theme object to add responsiveness to Mantine Tabs or any other component limited in the Styles API. This method also doesn’t limit the responsiveness to the initial viewport size, like it may in other frameworks. If you are on a larger screen and resize the window, it should swap orientation as it crosses the medium breakpoint.