How to have multiple row tabs in Material UI Tabs

Viewed 3045

I have almost 30 tabs inside Material UI Tabs, the user has to scroll two times to see all the tabs, I would like to show the tabs in two rows with scroll instead of one row with scroll, this will help the user to see most of the tabs in one glance.
How can I do something like this ?, I looked over Material UI document but i couldn't find anything useful, I tried manually giving it CSS style but I wasn't able to achieve my goal (my CSS skills are mediocre).
To show what I mean by multiple row tabs, here is a sample image :
enter image description here
Any help is much appreciated.

4 Answers

I did a little hack:

Use 2 different Tabs components and adjust indexes:

<Box sx={{ display: 'flex',justifyContent: 'center', flexWrap: 'wrap'}}>
    <Tabs value={value} onChange={handleChange}>
        <Tab label='Precios'/>
        <Tab label='Usuarios'/>
        <Tab label='Plan'/>
    </Tabs>
    <Tabs value={value - 3 } onChange={handleChange2}>
        <Tab label='Empleados'/>
    </Tabs>
</Box>

And manage change for this adjustment:

const handleChange = (event, newValue) => {
    setValue(newValue);
};
const handleChange2 = (event, newValue) => {
    setValue(newValue + 3);
};

You just change the number 3 for the number of tabs in your first component.

Saludos

I am struggling with similar problem. I have gone throw the documentation and looks like this is not possible using Tabs/Tab features. For now I can see two options:

  1. Use properties variant="scrollable" and scrollButtons="auto" like mentioned above. This will not give you what you expected but at least it is working.
  2. Implement your own tabs. You can use Grid for it. Below example is just to show an approach. It is not redy solution, but it can be easily adjusted.

const useStyles = makeStyles((theme) => ({
  navigationLinkContainer: { 
    // up to you
  },
  navigationLinkButtonActive: {
    color: '#ffffff',
    // up to you
  },
 
}));

const NavigationLink = (props) => {
  const classes = useStyles();
  return (
    <Grid item className={classes.navigationLinkContainer}>
      <Button
        component={Link}
        onClick={props.onClick}
      >
        {props.children}
      </Button>
    </Grid>
  );
};

const NavigationHeaders = (props) => {
  const classes = useStyles();
  const { headers, className } = props;
  const [activeTab, setActiveTab] = React.useState('');

  const isActive = (headerId) => headerId === activeTab;

  return (
    <>
     <Grid container >
      {headers.map((header) => (
        <NavigationLink
          className={classnames(isActive(header.id) && classes.navigationLinkButtonActive)}
          key={header.id}
          onClick={() => setActiveTab(header.id)}
        >
          {header.title}
        </NavigationLink>
      ))}
     </Grid>
     {/* some content here shown base on activeTab */}
   </>
  );
};

I also came to the conclusion that this is not currently possible with Tabs/Tab. I tried using <br />, <hr />, <Divider />, functions to insert breaks, making multiple rows of tabs (which messed up selection), wrapping Tabs in span with max-width (also messed up selection), you name it. I ultimately decided to use scroll on small screens.

I figured out the smallest screen size that would show my tabs properly, then used scroll for any smaller.

const mql = window.matchMedia('(max-width: 2000px)');
const smallScreen = mql.matches;

<Tabs
  value={tabValue}
  onChange={handleTabChange}
  orientation="horizontal"
  variant={smallScreen ? 'scrollable' : 'standard'}
  centered={!smallScreen}
 >
   <Tab label="1" />
   <Tab label="1" />
   <Tab label="3" />
   <Tab label="4" />
   <Tab label="5" />
  </Tabs>

You could add an event handler to change on resize, but was not necessary for my use case

Try going through the doc of any stuff you use to safe unnecessary problems in future

visit this for more details and full code https://material-ui.com/components/tabs/

<div className={classes.root}>
  <AppBar position="static">
    <Tabs value={value}
     onChange={handleChange} 
      aria-label="simple tabs example" 
      indicatorColor="primary"
      textColor="primary"
      variant="scrollable"
      scrollButtons="auto"
      aria-label="scrollable auto tabs example"
    >
      <Tab label="Item One" {...a11yProps(0)} />
      <Tab label="Item Two" {...a11yProps(1)} />
      <Tab label="Item Three" {...a11yProps(2)} />
    </Tabs>
  </AppBar>
  <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>

Edit: please notice the variant in Tabs

Related