30

I'm trying to create a simple navbar with Material-UI that looks like the one they use on their site. This is the code I wrote to try to replicate it:

import React from 'react'
import {AppBar, Tabs, Tab} from 'material-ui'

class Nav extends React.Component {
  render() {
    return (
      <AppBar title="My App">
        <Tabs>
          <Tab label="Item 1" />
          <Tab label="Item 2" />
          <Tab label="Item 3" />
          <Tab label="Item 4" />
        </Tabs>
      </AppBar>
    )
  }
}

React.render(<Nav />, document.body)

The problem is, the tabs are coming up very weird and clicking on the tabs have no effect whatsoever. Screenshot:

enter image description here

NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
Saad
  • 49,729
  • 21
  • 73
  • 112

7 Answers7

10

Latest Update [2018]

Problem should be fixed in latest version.

Update #1 [2016]

At least, the will is there - Not all hope is lost!

Original Post

Had the same issue.

Turns out, it's a bug (#773).

But you are in luck: This PR provides a solution using CSS. It (kinda) works. Here is a screenshot:

enter image description here

As you can see, it looks a bit ugly, so you might want to keep fiddling with the CSS to get the tabs appear in the right place.

NOTE: Eight months ago, the PR got rejected. Apparently, displaying Tabs in AppBar is not high-priority, so, the hackfix solution is all you got at the moment!

Oh the agony of using pre-release libraries!

Domi
  • 22,151
  • 15
  • 92
  • 122
2

I think Kabir's answer is a good start and I would also wrap the <Tabs> in a <ToolbarGroup > as the AppBar is subset of toolbars.

e.g.

iconElementRight={<ToolbarGroup >{myTabs}</ToolbarGroup>}

see: http://www.material-ui.com/#/components/toolbar

Aleck Landgraf
  • 1,545
  • 14
  • 13
1

A little late to the party, but a solution that has worked for me. FYI, this is a React/Redux app with a Rails backend.

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router'
import AppBar from 'material-ui/AppBar'
import Drawer from 'material-ui/Drawer'
import MenuItem from 'material-ui/MenuItem'
import { getBasename } from '../config/environment'

export default class Navbar extends Component {
  constructor(props) {
    super(props)
    this.state = {open: false}
    this.displayNavbar = this.displayNavbar.bind(this)
  }

  toggleDrawer = () => this.setState({ open: !this.state.open })

  authenticatedNavbar = () => {
    return (
      <div>
        <AppBar
          iconElementRight={
            <MenuItem
              containerElement={<Link to={getBasename() + 'login'} />}
              onTouchTap={() => {this.props.onLogoutClick()}}
              primaryText="Logout"
            />
          }
          onLeftIconButtonTouchTap={() => this.toggleDrawer()}
          title="Your_app"
        />
        <Drawer
          docked={false}
          onRequestChange={(open) => this.setState({open})}
          open={this.state.open}
        >
          <MenuItem
            containerElement={<Link to={getBasename() + 'home'} />}
            onTouchTap={() => { this.toggleDrawer() }}
            primaryText="Home"
          />
          <MenuItem
            containerElement={<Link to={getBasename() + 'some_component'} />}
            onTouchTap={() => { this.toggleDrawer() }}
            primaryText="Some Component"
          />
        </Drawer>
      </div>
    )
  }

  unauthenticatedNavbar = () => {
    return (
      <div>
        <AppBar
          iconElementRight={
            <MenuItem
              containerElement={<Link to={getBasename() + 'login'} />}
              primaryText="Login"
            />
          }
          showMenuIconButton={false}
          title="Your_app"
        />
      </div>
    )
  }

Then some other logic to show the appropriate AppBar according to the users state of authentication.

I don't really think that tabs are meant to be part of the App Bar. The Material spec shows them as a secondary toolbar.

J. Parrish
  • 36
  • 2
0

Have you used the react-tap-event-plugin? According to https://github.com/callemall/material-ui/issues/288 it's needed.

Julia
  • 41
  • 1
  • 7
0

Besides the CSS hack, I found out that you can use HTML Entities as a hack to split the tabs text. You can add &nbsp; to the beginning and ending of the tab labels and you have your space.

It makes the label string ugly but if you don't care that much it does the work pretty well, and it also allow you to add as many spaces as you wish.

Here is the updated code:

import React from 'react'
import {AppBar, Tabs, Tab} from 'material-ui'

class Nav extends React.Component {
  render() {
    return (
      <AppBar title="My App">
        <Tabs>
          <Tab label="&nbsp;Item 1&nbsp;" />
          <Tab label="&nbsp;Item 2&nbsp;" />
          <Tab label="&nbsp;Item 3&nbsp;" />
          <Tab label="&nbsp;Item 4&nbsp;" />
        </Tabs>
      </AppBar>
    )
  }
}

React.render(<Nav />, document.body)

And screenshot: Tabs with spaces

  • Using ` ` is frowned upon above CSS hacks. ` ` is for total and utter exasperation to save you from punching a wall because it won't work any other way. Or else it's 1994 and no-one is looking. – icc97 Mar 12 '17 at 00:08
0

If you want to display multiple items horizontally in the AppBar, put them inside a Toolbar and it will display nicely. See this answer here to know the reason why.

If you want to push the navbar to the right side, add a Box with the flexGrow set to 1 before the Tabs. This will create an empty div element. It works because Toobar container uses flex layout.

<AppBar position="static">
  <Toolbar>
    <IconButton size="large" edge="start" color="inherit" sx={{ mr: 2 }}>
      <MenuIcon />
    </IconButton>
    <Box flexGrow={1} />
    <Tabs textColor="inherit">
      <Tab label="One" />
      <Tab label="Two" />
      <Tab label="Three" />
    </Tabs>
  </Toolbar>
</AppBar>

Full Example

export default function Demo() {
  const [value, setValue] = React.useState(0);
  const handleChange = (_, newValue) => setValue(newValue);

  return (
    <>
      <AppBar position="static">
        <Toolbar>
          <IconButton size="large" edge="start" color="inherit" sx={{ mr: 2 }}>
            <MenuIcon />
          </IconButton>
          <Typography
            variant="h6"
            noWrap
            component="div"
            sx={{ display: { xs: "none", sm: "block" } }}
          >
            MUI
          </Typography>
          <Box flexGrow={1} />
          <Tabs value={value} onChange={handleChange} textColor="inherit">
            <Tab label="One" />
            <Tab label="Two" />
            <Tab label="Three" />
          </Tabs>
        </Toolbar>
      </AppBar>
      <div index={value} onChangeIndex={setValue}>
        <TabPanel value={value} index={0}>
          Item One
        </TabPanel>
        <TabPanel value={value} index={1}>
          Item Two
        </TabPanel>
        <TabPanel value={value} index={2}>
          Item Three
        </TabPanel>
      </div>
    </>
  );
}
function TabPanel(props) {
  const { children, value, index, ...other } = props;

  return (
    <div role="tabpanel" hidden={value !== index} {...other}>
      {value === index && (
        <Box sx={{ p: 3 }}>
          <Typography>{children}</Typography>
        </Box>
      )}
    </div>
  );
}

Live Demo

Edit 33005883/creating-a-navbar-with-material-ui

NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
-2

Did you read the Material-UI documentation?

Try passing your content as the iconElementRight prop.

ie:

render() {
    var myTabs = (
        <Tabs>
            <Tab label="item 1" />
            <Tab label="item 2" />
        </Tabs>
    );
    return <AppBar title="My App" iconElementRight={myTabs} />
}

Although, it does appear there are only 3 styles that are supported (as seen by the 3 examples in the docs). You might have to get creative with the styling, because it doesn't appear to be very flexible.

PS good luck, because since their switch to inline-styles and their own custom themes, it's pretty hard to change things or integrate other non-mui components (I was so put-off by this I created a fork that uses SASS https://www.npmjs.com/package/material-ui-with-sass)

bw_0x7c6
  • 17
  • 3
Kabir Sarin
  • 18,092
  • 10
  • 50
  • 41
  • I tried doing it like that, it ended up coming out like this: http://i.imgur.com/kJDEQe4.png Is there really no way to create a navbar like the one they use on their site without doing additional styling and customizing? I thought a simple navbar would be a standard component. – Saad Oct 08 '15 at 18:12
  • It looks like you're pretty close, no? Why don't you just style the tabs, give them some widths and margins? I agree with you, you should be able to just put the tabs there and have them be unaffected by the app bar (and look like they should, as if you had placed them in middle of the page or whatever). The "mui way or the highway" and their non-standard theming/inline styles still makes me mad. Things like this shouldn't be an issue. Anyways, that's all I've got. Maybe someone else will reply with a magical answer (but probably not). Good luck. – Kabir Sarin Oct 09 '15 at 04:38
  • I'm pretty sure he wants the tabs and other content to show up below the navbar, in the main body of the page, not inside the navbar. – tksfz Sep 29 '16 at 16:53