DEV Community

Cover image for Creating a Custom Navbar with Mantine in ReactJS #2
Sam Preston
Sam Preston

Posted on • Edited on

Creating a Custom Navbar with Mantine in ReactJS #2

Intro

Welcome back (previous) to the series where I show you how to build an web application with Mantine, ReactJS with TypeScript.

Mantine is:

"A fully featured React components library"

Part 1 - Simple Theming

Mantine ships with a very useful MantineProvider this allows us to apply themes and styles globally. This is as simple as inserting it and enclosing the App component in index.tsx with it:

ReactDOM.render(
  <React.StrictMode>
    <MantineProvider>
      <App />
    </MantineProvider>
  </React.StrictMode>,
  document.getElementById('root')
);
Enter fullscreen mode Exit fullscreen mode

We'll use the default dark mode for now so we can create the application without going blind. To do this we need to use the theme prop.

ReactDOM.render(
  <React.StrictMode>
    <MantineProvider
      theme={{
        colorScheme: 'dark'
      }}
    >
      <App />
    </MantineProvider>
  </React.StrictMode>,
  document.getElementById('root')
);
Enter fullscreen mode Exit fullscreen mode

This changes the application to look like so:
Dark Mode Init

Part 2 - Navigation

With great foresight, Mantine ships with a Section component as a child of the Navbar component so this is simply used as <Navbar.Section />.

function App() {
  return (
    <AppShell
      navbar={
        <Navbar
          width={{ base: 300 }}
          height='100vh'
        >
          <Navbar.Section>Assets/Hosts</Navbar.Section>
          <Navbar.Section>Software</Navbar.Section>
          <Navbar.Section>Configurations</Navbar.Section>
        </Navbar>
      }
    >
      {/* Your application here */}
    </AppShell>
  );
}
Enter fullscreen mode Exit fullscreen mode

Ugly Navbar

This creates a very ugly un-styled look to the Navbar, lets fix that by using a Button component.

function App() {
  return (
    <AppShell
      navbar={
        <Navbar
          width={{ base: 300 }}
          height='100vh'
        >
          <Navbar.Section>
            <Button>
              Assets/Hosts
            </Button>
          </Navbar.Section>

          <Navbar.Section>
            <Button>
              Software
            </Button>
          </Navbar.Section>

          <Navbar.Section>
            <Button>
              Configurations
            </Button>
          </Navbar.Section>
        </Navbar>
      }
    >
      {/* Your application here */}
    </AppShell>
  );
}
Enter fullscreen mode Exit fullscreen mode

Unstyled Buttons Navbar

Better, however, it could be better if we styled them. To do so we can use the variant and fullWidth prop. We're going to use the subtle variant as I personally prefer it.

function App() {
  return (
    <AppShell
      navbar={
        <Navbar
          width={{ base: 300 }}
          height='100vh'
        >
          <Navbar.Section>
            <Button variant='subtle' fullWidth>
              Assets/Hosts
            </Button>
          </Navbar.Section>

          <Navbar.Section>
            <Button variant='subtle' fullWidth>
              Software
            </Button>
          </Navbar.Section>

          <Navbar.Section>
            <Button variant='subtle' fullWidth>
              Configurations
            </Button>
          </Navbar.Section>
        </Navbar>
      }
    >
      {/* Your application here */}
    </AppShell>
  );
}
Enter fullscreen mode Exit fullscreen mode

Pretty Navbar

As you can see it looks 10 times better than before, but **STILL **we are not done. I want to centre these vertically so they more accessible from anywhere on the page. To this we need to do some tricky CSS, we're also going to create a Group component to... group the buttons.

Personally, I like to do in-line CSS before moving it anywhere that way I only have to modify a single file. This is what I created:

function App() {
  return (
    <AppShell
      navbar={
        <Navbar
          width={{ base: 300 }}
          height='100vh'
        >
          <Group
            direction='column'
            spacing='lg'
            grow
            sx={{ margin: 'auto 0 auto 0' }}
          >
            <Navbar.Section>
              <Button variant='subtle' fullWidth>
                Assets/Hosts
              </Button>
            </Navbar.Section>

            <Navbar.Section>
              <Button variant='subtle' fullWidth>
                Software
              </Button>
            </Navbar.Section>

            <Navbar.Section>
              <Button variant='subtle' fullWidth>
                Configurations
              </Button>
            </Navbar.Section>
          </Group>
        </Navbar>
      }
    >
      {/* Your application here */}
    </AppShell>
  );
}
Enter fullscreen mode Exit fullscreen mode

Let me explain the Group component quickly.

<Group
  direction='column'
  spacing='lg'
  grow
  sx={{ margin: 'auto 0 auto 0' }}
>
Enter fullscreen mode Exit fullscreen mode

Final Navbar

direction is used to define if the group is in columns or rows. spacing is used to create spaces between the components, this can be customised using themes. grow allows the components to grow horizontally if direction='column' and vertically if direction='row'. sx is used to pass in-line CSS to the component, more of my reasons for my solution can be found here.

Now before we move on let's clean it all up. I'll create a new directory under src, called components/CustomNavbar, and create the CustomNavbar.tsx file. Within it I'll cut the Navbar children and paste it into CustomNavbar.tsx.

CustomNavbar.tsx

function CustomNavbar() {
  return (
    <Group
      direction='column'
      spacing='lg'
      grow
      sx={{ margin: 'auto 0 auto 0' }}
    >
      <Navbar.Section>
        <Button variant='subtle' fullWidth>
          Assets/Hosts
        </Button>
      </Navbar.Section>

      <Navbar.Section>
        <Button variant='subtle' fullWidth>
          Software
        </Button>
      </Navbar.Section>

      <Navbar.Section>
        <Button variant='subtle' fullWidth>
          Configurations
        </Button>
      </Navbar.Section>
    </Group>
  )
}
Enter fullscreen mode Exit fullscreen mode

We'll then import the new CustomNavbar component into the App.tsx file where the original code was.

App.tsx

function App() {
  return (
    <AppShell
      navbar={
        <Navbar
          width={{ base: 300 }}
          height='100vh'
        >
          <CustomNavbar />
        </Navbar>
      }
    >
      {/* Your application here */}
    </AppShell>
  );
}
Enter fullscreen mode Exit fullscreen mode

Part 3 - Further Styling

We're not going to be creating anymore Navbar components and so we'll make the CSS for this global to clean up the files. We do this by moving it to the MantineProvider component in our index.tsx.

ReactDOM.render(
  <React.StrictMode>
    <MantineProvider
      theme={{
        colorScheme: 'dark'
      }}
      styles={{
        Navbar: {
          root: { height: '100vh', width: '300px' }
        }
      }}
    >
      <App />
    </MantineProvider>
  </React.StrictMode>,
  document.getElementById('root')
);
Enter fullscreen mode Exit fullscreen mode

Because our CustomNavbar's Group component will be reused later in this project we'll leave the in-line styling and we'll come back to the CustomNavbar when we create users.

Conclusion

Thanks for joining me on the 2nd part to this series, please leave a like and comment if you have any questions, I will try to answer all questions. Come back next time to see further developments to the Navbar and how we'll create a User component.

Top comments (0)