Skip to content

Commit

Permalink
[Tabs] Add variant prop and deprecate fullWidth and scrollable props (#…
Browse files Browse the repository at this point in the history
…13980)

* [Tabs] Add variant prop and deprecate fullWidth and scrollable props

* Update Tabs.d.ts and tabs.md

* Fix wrong comment

* Add backwards compatibility with old props. Add deprecated warnings

* Missing scrollable reference

* Fullwidth docs

* good for me
  • Loading branch information
rfbotto authored and oliviertassinari committed Dec 25, 2018
1 parent 3a43aef commit 0102308
Show file tree
Hide file tree
Showing 12 changed files with 66 additions and 39 deletions.
2 changes: 1 addition & 1 deletion docs/src/pages/demos/tabs/FullWidthTabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class FullWidthTabs extends React.Component {
onChange={this.handleChange}
indicatorColor="primary"
textColor="primary"
fullWidth
variant="fullWidth"
>
<Tab label="Item One" />
<Tab label="Item Two" />
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/tabs/IconLabelTabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class IconLabelTabs extends React.Component {
<Tabs
value={this.state.value}
onChange={this.handleChange}
fullWidth
variant="fullWidth"
indicatorColor="secondary"
textColor="secondary"
>
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/tabs/IconTabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class IconTabs extends React.Component {
<Tabs
value={this.state.value}
onChange={this.handleChange}
fullWidth
variant="fullWidth"
indicatorColor="primary"
textColor="primary"
>
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/tabs/NavTabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class NavTabs extends React.Component {
<NoSsr>
<div className={classes.root}>
<AppBar position="static">
<Tabs fullWidth value={value} onChange={this.handleChange}>
<Tabs variant="fullWidth" value={value} onChange={this.handleChange}>
<LinkTab label="Page One" href="page1" />
<LinkTab label="Page Two" href="page2" />
<LinkTab label="Page Three" href="page3" />
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/tabs/ScrollableTabsButtonAuto.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class ScrollableTabsButtonAuto extends React.Component {
onChange={this.handleChange}
indicatorColor="primary"
textColor="primary"
scrollable
variant="scrollable"
scrollButtons="auto"
>
<Tab label="Item One" />
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/tabs/ScrollableTabsButtonForce.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class ScrollableTabsButtonForce extends React.Component {
<Tabs
value={value}
onChange={this.handleChange}
scrollable
variant="scrollable"
scrollButtons="on"
indicatorColor="primary"
textColor="primary"
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/tabs/ScrollableTabsButtonPrevent.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class ScrollableTabsButtonPrevent extends React.Component {
return (
<div className={classes.root}>
<AppBar position="static">
<Tabs value={value} onChange={this.handleChange} scrollable scrollButtons="off">
<Tabs value={value} onChange={this.handleChange} variant="scrollable" scrollButtons="off">
<Tab icon={<PhoneIcon />} />
<Tab icon={<FavoriteIcon />} />
<Tab icon={<PersonPinIcon />} />
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/tabs/tabs.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Fixed tabs should be used with a limited number of tabs and when consistent plac

### Full width

The `fullWidth` property should be used for smaller views.
The `variant="fullWidth"` property should be used for smaller views.
This demo also uses [react-swipeable-views](https://github.com/oliviertassinari/react-swipeable-views) to animate the Tab transition, and allowing tabs to be swiped on touch devices.

{{"demo": "pages/demos/tabs/FullWidthTabs.js"}}
Expand Down
1 change: 1 addition & 0 deletions packages/material-ui/src/Tabs/Tabs.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface TabsProps
TabIndicatorProps?: Partial<TabIndicatorProps>;
textColor?: 'secondary' | 'primary' | 'inherit' | string;
value: any;
variant?: 'scrollable' | 'fullWidth';
width?: string;
}

Expand Down
48 changes: 35 additions & 13 deletions packages/material-ui/src/Tabs/Tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ScrollbarSize from './ScrollbarSize';
import withStyles from '../styles/withStyles';
import TabIndicator from './TabIndicator';
import TabScrollButton from './TabScrollButton';
import deprecatedPropType from '../utils/deprecatedPropType';

export const styles = theme => ({
/* Styles applied to the root element. */
Expand All @@ -25,7 +26,7 @@ export const styles = theme => ({
flexContainer: {
display: 'flex',
},
/* Styles applied to the flex container element if `centered={true}` & `scrollable={false}`. */
/* Styles applied to the flex container element if `centered={true}` & `!variant="scrollable"`. */
centered: {
justifyContent: 'center',
},
Expand All @@ -36,12 +37,12 @@ export const styles = theme => ({
flex: '1 1 auto',
whiteSpace: 'nowrap',
},
/* Styles applied to the tablist element if `scrollable={false}`. */
/* Styles applied to the tablist element if `!variant="scrollable"`. */
fixed: {
overflowX: 'hidden',
width: '100%',
},
/* Styles applied to the tablist element if `scrollable={true}`. */
/* Styles applied to the tablist element if `variant="scrollable"`. */
scrollable: {
overflowX: 'scroll',
},
Expand Down Expand Up @@ -112,8 +113,16 @@ class Tabs extends React.Component {
}

getConditionalElements = () => {
const { classes, scrollable, ScrollButtonComponent, scrollButtons, theme } = this.props;
const {
classes,
scrollable: deprecatedScrollable,
ScrollButtonComponent,
scrollButtons,
theme,
variant,
} = this.props;
const conditionalElements = {};
const scrollable = variant === 'scrollable' || deprecatedScrollable;
conditionalElements.scrollbarSizeListener = scrollable ? (
<ScrollbarSize onChange={this.handleScrollbarSizeChange} />
) : null;
Expand Down Expand Up @@ -234,7 +243,8 @@ class Tabs extends React.Component {
};

updateScrollButtonState = () => {
const { scrollable, scrollButtons, theme } = this.props;
const { scrollable: deprecatedScrollable, scrollButtons, theme, variant } = this.props;
const scrollable = variant === 'scrollable' || deprecatedScrollable;

if (scrollable && scrollButtons !== 'off') {
const { scrollWidth, clientWidth } = this.tabsRef;
Expand Down Expand Up @@ -293,22 +303,25 @@ class Tabs extends React.Component {
classes,
className: classNameProp,
component: Component,
fullWidth,
fullWidth = false,
indicatorColor,
onChange,
scrollable,
scrollable: deprecatedScrollable = false,
ScrollButtonComponent,
scrollButtons,
TabIndicatorProps = {},
textColor,
theme,
value,
variant,
...other
} = this.props;

const scrollable = variant === 'scrollable' || deprecatedScrollable;

warning(
!centered || !scrollable,
'Material-UI: you can not use the `centered={true}` and `scrollable={true}` properties ' +
'Material-UI: you can not use the `centered={true}` and `variant="scrollable"` properties ' +
'at the same time on a `Tabs` component.',
);

Expand Down Expand Up @@ -354,7 +367,7 @@ class Tabs extends React.Component {

childIndex += 1;
return React.cloneElement(child, {
fullWidth,
fullWidth: variant === 'fullWidth' || fullWidth,
indicator: selected && !this.state.mounted && indicator,
selected,
onChange,
Expand Down Expand Up @@ -427,7 +440,7 @@ Tabs.propTypes = {
* If `true`, the tabs will grow to use all the available space.
* This property is intended for small views, like on mobile.
*/
fullWidth: PropTypes.bool,
fullWidth: deprecatedPropType(PropTypes.bool, 'Instead, use the `variant="fullWidth"` property.'),
/**
* Determines the color of the indicator.
*/
Expand All @@ -443,7 +456,10 @@ Tabs.propTypes = {
* True invokes scrolling properties and allow for horizontally scrolling
* (or swiping) the tab bar.
*/
scrollable: PropTypes.bool,
scrollable: deprecatedPropType(
PropTypes.bool,
'Instead, use the `variant="scrollable"` property.',
),
/**
* The component used to render the scroll buttons.
*/
Expand Down Expand Up @@ -472,14 +488,20 @@ Tabs.propTypes = {
* If you don't want any selected `Tab`, you can set this property to `false`.
*/
value: PropTypes.any,
/**
* Determines additional display behavior of the tabs:
* - `scrollable` will invoke scrolling properties and allow for horizontally
* scrolling (or swiping) of the tab bar.
* -`fullWidth` will make the tabs grow to use all the available space,
* which should be used for small views, like on mobile.
*/
variant: PropTypes.oneOf(['scrollable', 'fullWidth']),
};

Tabs.defaultProps = {
centered: false,
component: 'div',
fullWidth: false,
indicatorColor: 'secondary',
scrollable: false,
ScrollButtonComponent: TabScrollButton,
scrollButtons: 'auto',
textColor: 'inherit',
Expand Down
26 changes: 13 additions & 13 deletions packages/material-ui/src/Tabs/Tabs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ describe('<Tabs />', () => {
});

it('should warn if the input is invalid', () => {
shallow(<Tabs onChange={noop} value={0} centered scrollable />);
shallow(<Tabs onChange={noop} value={0} centered variant="scrollable" />);
assert.match(
consoleErrorMock.args()[0][0],
/Material-UI: you can not use the `centered={true}` and `scrollable={true}`/,
/Material-UI: you can not use the `centered={true}` and `variant="scrollable"`/,
);
});
});
Expand Down Expand Up @@ -347,14 +347,14 @@ describe('<Tabs />', () => {
});
});

describe('prop: scrollable', () => {
describe('prop: variant="scrollable"', () => {
let clock;
let wrapper;

before(() => {
clock = useFakeTimers();
wrapper = shallow(
<Tabs width="md" onChange={noop} value={0} scrollable>
<Tabs width="md" onChange={noop} value={0} variant="scrollable">
<Tab />
<Tab />
</Tabs>,
Expand Down Expand Up @@ -388,7 +388,7 @@ describe('<Tabs />', () => {
it('should get a scrollbar size listener', () => {
// use mount to ensure that handleScrollbarSizeChange gets covered
const mountWrapper = mount(
<Tabs width="md" onChange={noop} value={0} scrollable>
<Tabs width="md" onChange={noop} value={0} variant="scrollable">
<Tab />
<Tab />
</Tabs>,
Expand All @@ -398,7 +398,7 @@ describe('<Tabs />', () => {
});
});

describe('prop: !scrollable', () => {
describe('prop: !variant="scrollable"', () => {
it('should not render with the scrollable class', () => {
const wrapper = shallow(
<Tabs width="md" onChange={noop} value={0}>
Expand Down Expand Up @@ -426,7 +426,7 @@ describe('<Tabs />', () => {

it('should render scroll buttons', () => {
const wrapper = shallow(
<Tabs width="md" onChange={noop} value={0} scrollable scrollButtons="on">
<Tabs width="md" onChange={noop} value={0} variant="scrollable" scrollButtons="on">
<Tab />
<Tab />
</Tabs>,
Expand All @@ -436,7 +436,7 @@ describe('<Tabs />', () => {

it('should render scroll buttons automatically', () => {
const wrapper = shallow(
<Tabs width="md" onChange={noop} value={0} scrollable scrollButtons="auto">
<Tabs width="md" onChange={noop} value={0} variant="scrollable" scrollButtons="auto">
<Tab />
<Tab />
</Tabs>,
Expand All @@ -446,7 +446,7 @@ describe('<Tabs />', () => {

it('should should not render scroll buttons automatically', () => {
const wrapper = shallow(
<Tabs width="sm" onChange={noop} value={0} scrollable scrollButtons="auto">
<Tabs width="sm" onChange={noop} value={0} variant="scrollable" scrollButtons="auto">
<Tab />
<Tab />
</Tabs>,
Expand All @@ -460,7 +460,7 @@ describe('<Tabs />', () => {

it('should handle window resize event', () => {
const wrapper = shallow(
<Tabs width="md" onChange={noop} value={0} scrollable scrollButtons="on">
<Tabs width="md" onChange={noop} value={0} variant="scrollable" scrollButtons="on">
<Tab />
<Tab />
</Tabs>,
Expand All @@ -482,7 +482,7 @@ describe('<Tabs />', () => {
let instance;
before(() => {
wrapper = shallow(
<Tabs width="md" onChange={noop} value={0} scrollable scrollButtons="on">
<Tabs width="md" onChange={noop} value={0} variant="scrollable" scrollButtons="on">
<Tab />
<Tab />
</Tabs>,
Expand Down Expand Up @@ -527,7 +527,7 @@ describe('<Tabs />', () => {
const dimensions = { scrollLeft: 100, clientWidth: 200, scrollWidth: 1000 };
before(() => {
wrapper = shallow(
<Tabs width="md" onChange={noop} value={0} scrollable scrollButtons="on">
<Tabs width="md" onChange={noop} value={0} variant="scrollable" scrollButtons="on">
<Tab />
<Tab />
</Tabs>,
Expand Down Expand Up @@ -566,7 +566,7 @@ describe('<Tabs />', () => {

beforeEach(() => {
const wrapper = shallow(
<Tabs width="md" onChange={noop} value={0} scrollable>
<Tabs width="md" onChange={noop} value={0} variant="scrollable">
<Tab />
<Tab />
</Tabs>,
Expand Down
14 changes: 9 additions & 5 deletions pages/api/tabs.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,19 @@ import Tabs from '@material-ui/core/Tabs';
| <span class="prop-name">children</span> | <span class="prop-type">node</span> |   | The content of the component. |
| <span class="prop-name">classes</span> | <span class="prop-type">object</span> |   | Override or extend the styles applied to the component. See [CSS API](#css-api) below for more details. |
| <span class="prop-name">component</span> | <span class="prop-type">componentPropType</span> | <span class="prop-default">'div'</span> | The component used for the root node. Either a string to use a DOM element or a component. |
| <span class="prop-name">fullWidth</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, the tabs will grow to use all the available space. This property is intended for small views, like on mobile. |
| ~~<span class="prop-name">fullWidth</span>~~ | <span class="prop-type">bool</span> |   | *Deprecated*. Instead, use the `variant="fullWidth"` property.<br><br>If `true`, the tabs will grow to use all the available space. This property is intended for small views, like on mobile. |
| <span class="prop-name">indicatorColor</span> | <span class="prop-type">enum:&nbsp;'secondary'&nbsp;&#124;<br>&nbsp;'primary'<br></span> | <span class="prop-default">'secondary'</span> | Determines the color of the indicator. |
| <span class="prop-name">onChange</span> | <span class="prop-type">func</span> |   | Callback fired when the value changes.<br><br>**Signature:**<br>`function(event: object, value: number) => void`<br>*event:* The event source of the callback<br>*value:* We default to the index of the child |
| <span class="prop-name">scrollable</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | True invokes scrolling properties and allow for horizontally scrolling (or swiping) the tab bar. |
| <span class="prop-name">scrollable</span> | <span class="prop-type">deprecatedPropType(
PropTypes.bool,
'Instead, use the `variant="scrollable"` property.',
)</span> |   | True invokes scrolling properties and allow for horizontally scrolling (or swiping) the tab bar. |
| <span class="prop-name">ScrollButtonComponent</span> | <span class="prop-type">componentPropType</span> | <span class="prop-default">TabScrollButton</span> | The component used to render the scroll buttons. |
| <span class="prop-name">scrollButtons</span> | <span class="prop-type">enum:&nbsp;'auto'&nbsp;&#124;<br>&nbsp;'on'&nbsp;&#124;<br>&nbsp;'off'<br></span> | <span class="prop-default">'auto'</span> | Determine behavior of scroll buttons when tabs are set to scroll `auto` will only present them on medium and larger viewports `on` will always present them `off` will never present them |
| <span class="prop-name">TabIndicatorProps</span> | <span class="prop-type">object</span> |   | Properties applied to the `TabIndicator` element. |
| <span class="prop-name">textColor</span> | <span class="prop-type">enum:&nbsp;'secondary'&nbsp;&#124;<br>&nbsp;'primary'&nbsp;&#124;<br>&nbsp;'inherit'<br></span> | <span class="prop-default">'inherit'</span> | Determines the color of the `Tab`. |
| <span class="prop-name">value</span> | <span class="prop-type">any</span> |   | The value of the currently selected `Tab`. If you don't want any selected `Tab`, you can set this property to `false`. |
| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'scrollable'&nbsp;&#124;<br>&nbsp;'fullWidth'<br></span> |   | Determines additional display behavior of the tabs: - `scrollable` will invoke scrolling properties and allow for horizontally scrolling (or swiping) of the tab bar. -`fullWidth` will make the tabs grow to use all the available space, which should be used for small views, like on mobile. |

Any other properties supplied will be spread to the root element (native element).

Expand All @@ -45,10 +49,10 @@ This property accepts the following keys:
|:-----|:------------|
| <span class="prop-name">root</span> | Styles applied to the root element.
| <span class="prop-name">flexContainer</span> | Styles applied to the flex container element.
| <span class="prop-name">centered</span> | Styles applied to the flex container element if `centered={true}` & `scrollable={false}`.
| <span class="prop-name">centered</span> | Styles applied to the flex container element if `centered={true}` & `!variant="scrollable"`.
| <span class="prop-name">scroller</span> | Styles applied to the tablist element.
| <span class="prop-name">fixed</span> | Styles applied to the tablist element if `scrollable={false}`.
| <span class="prop-name">scrollable</span> | Styles applied to the tablist element if `scrollable={true}`.
| <span class="prop-name">fixed</span> | Styles applied to the tablist element if `!variant="scrollable"`.
| <span class="prop-name">scrollable</span> | Styles applied to the tablist element if `variant="scrollable"`.
| <span class="prop-name">scrollButtons</span> | Styles applied to the `ScrollButtonComponent` component.
| <span class="prop-name">scrollButtonsAuto</span> | Styles applied to the `ScrollButtonComponent` component if `scrollButtons="auto"`.
| <span class="prop-name">indicator</span> | Styles applied to the `TabIndicator` component.
Expand Down

0 comments on commit 0102308

Please sign in to comment.