mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.9k stars 32.26k forks source link

v1: tabs that are scrollable do not center #10235

Closed barbalex closed 6 years ago

barbalex commented 6 years ago

Expected Behavior

Tabs that receive the prop centered should always center.

Current Behavior

They remain left aligned if they are also set scrollable.

Steps to Reproduce

https://codesandbox.io/s/kk371k1w75

Your Environment

Tech Version
Material-UI @next
React 16.2.0
browser chrome
oliviertassinari commented 6 years ago

@barbalex Good catch! We should add a warning about it. It's not possible.

barbalex commented 6 years ago

@oliviertassinari Sad that it is not possible. Because this seems like the feature that would make tabs work well from huge to tiny screen sizes.

barbalex commented 6 years ago

@oliviertassinari Would this not work if the tabs were per css centered div's whose bottom border is highlighted when the tab is active?

I'm sure this is very naive and there are good reasons it is not solved that way. But I'm curious.

dbarabashh commented 6 years ago

@barbalex I try to do some changes for this issue and I think we can to do something. I should think

KyleAsaff commented 6 years ago

any update on this? or a work around? I would love to use scrollable tabs at smaller viewports while keeping them centered at larger viewports

oliviertassinari commented 6 years ago

any update on this? or a work around?

@KyleAsaff The plan going forward is to add a warning to prevent people from reaching this set of properties.

I would love to use scrollable tabs at smaller viewports while keeping them centered at larger viewports

You can dynamically toggle properties based on the screen width with the withWidth() higher order component. I think that we should better document this module.

KyleAsaff commented 6 years ago

Thanks @oliviertassinari! For anyone looking for a workaround, I created one using react-measure. I have pasted the relevant portion of the code in the snippet below:

import React from 'react';
import { Link, withRouter } from 'react-router-dom';
import AppBar from 'material-ui/AppBar';
import Tabs, { Tab } from 'material-ui/Tabs';
import Measure from 'react-measure';

class Navigation extends React.Component {

  state = {
    appBarWidth: 1179,
  }

  render() {
    const { navigation } = this.props;
    const { appBarWidth } = this.state;

    return (
      <div>
        <Measure
          bounds
          onResize={(contentRect) => {
            this.setState({ appBarWidth: contentRect.bounds.width });
          }}
        >
          {({ measureRef }) => (
            <div ref={measureRef}>
              <AppBar position="static" color="default">
                <Tabs
                  value={navigation.value}
                  onChange={this.handleChange}
                  indicatorColor="primary"
                  textColor="primary"
                  scrollButtons="auto"
                  centered={appBarWidth > 1179}
                  scrollable={appBarWidth < 1179}
                >
                  <Tab label="Overview" component={Link} to="/overview" />
                  <Tab label="PDP" component={Link} to="/ecomm/pdp" />
                  <Tab label="Shoppable Galleries" component={Link} to="/ecomm/shoppable_galleries" />
                  <Tab label="Shoppable Instagram" component={Link} to="/ecomm/shoppable_instagram" />
                  <Tab label="Brand Emails" component={Link} to="/email/brand_emails" />
                  <Tab label="Shopping Cart Abandonment" component={Link} to="/email/shopping_cart_abandonment" />
                </Tabs>
              </AppBar>
            </div>
            )}
        </Measure>
      </div>
    );
  }
}
oliviertassinari commented 6 years ago

@KyleAsaff react-measure is a good solution you can also use material-ui/withWidth or react-virtualized/AutoSizer.

norasteria commented 6 years ago

@KyleAsaff thank you for sharing your code, it helped me so much for this kind of problem

michael-ecb commented 6 years ago

What about dynamic tabs? This won't work when I build the tabs dynamically. centered on scrolleable is a must. Any suggestions?

oltodo commented 6 years ago

I don't understand why centered tabs can't be scrollable (therefore left-aligned) after the container width has been becoming smaller than its content 🤔

jacobweber commented 6 years ago

I'd also like to be able to combine these, if it's feasible.

jacobweber commented 6 years ago

Found a simple solution if you want the fullWidth style (where the tabs spread to cover the entire area) instead of the centered style (where they're bunched up in the middle).

First, turn off centered, and turn on fullWidth and scrollable. Then just add a flexShrink: 0 style to each of the Tab components. This overrides the shrinking that fullWidth normally allows. Since we're scrolling, we don't want shrinking.

jdunc commented 5 years ago

what's good @jacobweber !! that's clutch, great call right there. Seconding that as a solution. It's super slick to use the fullWidth and scrollable, definitely looks the best. And setting each tab to flexShrink: 0 prevents them from overlapping as they would without the additional css. Thanks again!

barbalex commented 5 years ago

Oops. @jacobweber 's great workaround seems not to work any more since last update: https://github.com/mui-org/material-ui/pull/13980

:-(

Not being able to center and scroll looks broken on desktop.

jacobweber commented 5 years ago

@barbalex Try adding flexGrow: 1 instead. Looks like the defaults have changed.

mpodlasin commented 5 years ago

Did something change?

I was able to make it centered with two lines of css.

Setting flex-grow: 0 on MuiTabs-scroller and justify-content: center on first MuiTabs-flexContainer in the tabs tree.

Works perfectly, unless I am missing something. @oliviertassinari do you want me to make a PR?

jessemezini commented 5 years ago

Add variant="scrollable" prop to Tabs and omit centered prop.

Then add

@media (min-width: 768px) {
  .MuiTabs-flexContainer {
    justify-content: center;
  }
}

to center on larger screens.

amakk commented 5 years ago

I have an alternate solution for centered + scrollable tabs and is not dependent on media queries, so works with dynamic number of tabs. Seems to work in Chrome, Firefox and Safari. Does anyone see any issues with this approach?

https://codesandbox.io/s/material-ui-centered-scrollable-tabs-ud26w

aaadipop commented 5 years ago

related to @jacobweber answer, the magic margin: auto instead of flexShrink: 0 works for me :)

adisher commented 4 years ago

variant: fullWidth and styling margin: 'auto' works for me.

I would suggest to please address this issue in the API section. centered is still not working..

adityapatnaik commented 4 years ago

A workaround that works across all viewports could be this. Not adding the breakpoint breaks the tabs on small viewports.

variant="scrollable"

tabs:{
    [theme.breakpoints.up("md")]: {
      margin:'auto'
    }

  }

Hope this helps!

abhisheksarka commented 4 years ago

If anyone is still looking for a solution. Here is my approach

const scrollableTabs = useMediaQuery(theme.breakpoints.down('sm'));
<Tabs variant={scrollableTabs ? "scrollable" : "centered" } scrollButtons="on" centered>
</Tabs>
CristianCucunuba commented 3 years ago

@abhisheksarka I don't think there is a centered variant, the prop centered will make it work but only for desktop

thiagohoh commented 3 years ago

I modified @abhisheksarka code to:

 const scrollableTabs = useMediaQuery(theme.breakpoints.down('sm'));
<Tabs variant={scrollableTabs ? "scrollable" : "standard" } scrollButtons="on" centered={!scrollableTabs}>
</Tabs>

And it worked.

talah221 commented 2 years ago

Still doesnt work. my workaround is:

<Tabs variant="scrollable" scrollButtons={"auto"} sx={{ margin:'auto', maxWidth:'100%' }} ...restProps> </Tabs>

ItsTonyDavid commented 2 years ago

With help of @amakk , my workaround was:

<Tabs
     variant="scrollable"
     scrollButtons
     allowScrollButtonsMobile
     style={{ justifyContent: 'center' }}
     sx={{
         [`& .${tabsClasses.scroller}`]: {
            '&.MuiTabs-scrollableX': { flexGrow: '0' },
         }
     }}
 >
ShohanMir commented 12 months ago

the easiest solution. Thanks @ItsTonyDavid