Skip to content

Commit

Permalink
[Tabs] Add demo for routing with Tabs (#25827)
Browse files Browse the repository at this point in the history
Co-authored-by: Olivier Tassinari <[email protected]>
  • Loading branch information
ahmed-28 and oliviertassinari authored Apr 19, 2021
1 parent 96380e3 commit d479fc1
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 35 deletions.
14 changes: 7 additions & 7 deletions docs/src/pages/components/buttons/buttons.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@ In cards, text buttons help maintain an emphasis on card content.

## Outlined buttons

[Outlined buttons](https://material.io/components/buttons#outlined-button)
are medium-emphasis buttons. They contain actions that are important,
but aren't the primary action in an app.
[Outlined buttons](https://material.io/components/buttons#outlined-button) are medium-emphasis buttons.
They contain actions that are important but aren't the primary action in an app.

Outlined buttons are also a lower emphasis alternative to contained buttons,
or a higher emphasis alternative to text buttons.
Expand Down Expand Up @@ -77,7 +76,7 @@ Note that the documentation [avoids](/guides/api/#native-properties) mentioning

## Sizes

For larger or smaller buttons use the `size` prop.
For larger or smaller buttons, use the `size` prop.

{{"demo": "pages/components/buttons/ButtonSizes.js"}}

Expand Down Expand Up @@ -126,8 +125,9 @@ You can take advantage of this lower-level component to build custom interaction

One common use case is to use the button to trigger navigation to a new page.
The `ButtonBase` component provides the `component` prop to handle this use case.
However for certain focus polyfills `ButtonBase` requires the DOM node of the provided
component. This is achieved by attaching a ref to the component and expecting that the
However, for certain focus polyfills `ButtonBase` requires the DOM node of the provided
component.
This is achieved by attaching a ref to the component and expecting that the
component forwards this ref to the underlying DOM node.
Given that many of the interactive components rely on `ButtonBase`, you should be
able to take advantage of it everywhere.
Expand All @@ -142,7 +142,7 @@ The ButtonBase component sets `pointer-events: none;` on disabled buttons, which

If you wish to use `not-allowed`, you have two options:

1. **CSS only**. You can remove the pointer events style on the disabled state of the `<button>` element:
1. **CSS only**. You can remove the pointer-events style on the disabled state of the `<button>` element:

```css
.MuiButtonBase-root:disabled {
Expand Down
14 changes: 11 additions & 3 deletions docs/src/pages/components/tabs/tabs.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ following [WAI-ARIA authoring practices](https://www.w3.org/TR/wai-aria-practice

## Wrapped labels

Long labels will automatically wrap on tabs. If the label is too long for the tab, it will overflow and the text will not be visible.
Long labels will automatically wrap on tabs.
If the label is too long for the tab, it will overflow, and the text will not be visible.

{{"demo": "pages/components/tabs/TabsWrappedLabel.js"}}

Expand All @@ -45,7 +46,7 @@ A tab can be disabled by setting the `disabled` prop.

## Fixed tabs

Fixed tabs should be used with a limited number of tabs, and when consistent placement will aid muscle memory.
Fixed tabs should be used with a limited number of tabs, and when a consistent placement will aid muscle memory.

### Full width

Expand Down Expand Up @@ -87,7 +88,7 @@ If you want to make sure the buttons are always visible, you should customize th
### Prevent scroll buttons

Left and right scroll buttons are never be presented with `scrollButtons={false}`.
All scrolling must be initiated through user agent scrolling mechanisms (e.g. left/right swipe, shift-mousewheel, etc.)
All scrolling must be initiated through user agent scrolling mechanisms (e.g. left/right swipe, shift mouse wheel, etc.)

{{"demo": "pages/components/tabs/ScrollableTabsButtonPrevent.js", "bg": true}}

Expand Down Expand Up @@ -122,6 +123,13 @@ Tab labels may be either all icons or all text.

{{"demo": "pages/components/tabs/IconLabelTabs.js"}}

## Third-party routing library

One common use case is to perform navigation on the client only, without an HTTP round-trip to the server.
The `Link` component provides the `component` prop to handle this use case.

Here is an [integration example with react-router](/guides/routing/#tabs).

## Accessibility

(WAI-ARIA: https://www.w3.org/TR/wai-aria-practices/#tabpanel)
Expand Down
18 changes: 6 additions & 12 deletions docs/src/pages/guides/routing/ListRouter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import Box from '@material-ui/core/Box';
import ListItem from '@material-ui/core/ListItem';
import Paper from '@material-ui/core/Paper';
import ListItemIcon from '@material-ui/core/ListItemIcon';
Expand Down Expand Up @@ -40,21 +40,15 @@ ListItemLink.propTypes = {
to: PropTypes.string.isRequired,
};

const useStyles = makeStyles({
root: {
width: 360,
},
});

export default function ListRouter() {
const classes = useStyles();

return (
<MemoryRouter initialEntries={['/drafts']} initialIndex={0}>
<div className={classes.root}>
<Box sx={{ width: 360 }}>
<Route>
{({ location }) => (
<Typography gutterBottom>Current route: {location.pathname}</Typography>
<Typography variant="body2" sx={{ pb: 2 }} color="text.secondary">
Current route: {location.pathname}
</Typography>
)}
</Route>
<Paper elevation={0}>
Expand All @@ -68,7 +62,7 @@ export default function ListRouter() {
<ListItemLink to="/spam" primary="Spam" />
</List>
</Paper>
</div>
</Box>
</MemoryRouter>
);
}
18 changes: 6 additions & 12 deletions docs/src/pages/guides/routing/ListRouter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import Box from '@material-ui/core/Box';
import ListItem from '@material-ui/core/ListItem';
import Paper from '@material-ui/core/Paper';
import ListItemIcon from '@material-ui/core/ListItemIcon';
Expand Down Expand Up @@ -39,21 +39,15 @@ function ListItemLink(props: ListItemLinkProps) {
);
}

const useStyles = makeStyles({
root: {
width: 360,
},
});

export default function ListRouter() {
const classes = useStyles();

return (
<MemoryRouter initialEntries={['/drafts']} initialIndex={0}>
<div className={classes.root}>
<Box sx={{ width: 360 }}>
<Route>
{({ location }) => (
<Typography gutterBottom>Current route: {location.pathname}</Typography>
<Typography variant="body2" sx={{ pb: 2 }} color="text.secondary">
Current route: {location.pathname}
</Typography>
)}
</Route>
<Paper elevation={0}>
Expand All @@ -67,7 +61,7 @@ export default function ListRouter() {
<ListItemLink to="/spam" primary="Spam" />
</List>
</Paper>
</div>
</Box>
</MemoryRouter>
);
}
40 changes: 40 additions & 0 deletions docs/src/pages/guides/routing/TabsRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from 'react';
import Box from '@material-ui/core/Box';
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import Typography from '@material-ui/core/Typography';
import { MemoryRouter, Route, Link, useRouteMatch } from 'react-router-dom';

function MyTabs() {
// You need to provide the routes in descendant order.
// This means that if you have nested routes like:
// users, users/new, users/edit.
// Then the order should be ['users/add', 'users/edit', 'users'].
const routeMatch = useRouteMatch(['/inbox/:id', '/drafts', '/trash']);
const currentTab = routeMatch?.path;

return (
<Tabs value={currentTab}>
<Tab label="Inbox" value="/inbox/:id" to="/inbox/1" component={Link} />
<Tab label="Drafts" value="/drafts" to="/drafts" component={Link} />
<Tab label="Trash" value="/trash" to="/trash" component={Link} />
</Tabs>
);
}

export default function TabsRouter() {
return (
<MemoryRouter initialEntries={['/drafts']} initialIndex={0}>
<Box sx={{ width: '100%' }}>
<Route>
{({ location }) => (
<Typography variant="body2" sx={{ pb: 2 }} color="text.secondary">
Current route: {location.pathname}
</Typography>
)}
</Route>
<MyTabs />
</Box>
</MemoryRouter>
);
}
40 changes: 40 additions & 0 deletions docs/src/pages/guides/routing/TabsRouter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from 'react';
import Box from '@material-ui/core/Box';
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import Typography from '@material-ui/core/Typography';
import { MemoryRouter, Route, Link, useRouteMatch } from 'react-router-dom';

function MyTabs() {
// You need to provide the routes in descendant order.
// This means that if you have nested routes like:
// users, users/new, users/edit.
// Then the order should be ['users/add', 'users/edit', 'users'].
const routeMatch = useRouteMatch(['/inbox/:id', '/drafts', '/trash']);
const currentTab = routeMatch?.path;

return (
<Tabs value={currentTab}>
<Tab label="Inbox" value="/inbox/:id" to="/inbox/1" component={Link} />
<Tab label="Drafts" value="/drafts" to="/drafts" component={Link} />
<Tab label="Trash" value="/trash" to="/trash" component={Link} />
</Tabs>
);
}

export default function TabsRouter() {
return (
<MemoryRouter initialEntries={['/drafts']} initialIndex={0}>
<Box sx={{ width: '100%' }}>
<Route>
{({ location }) => (
<Typography variant="body2" sx={{ pb: 2 }} color="text.secondary">
Current route: {location.pathname}
</Typography>
)}
</Route>
<MyTabs />
</Box>
</MemoryRouter>
);
}
6 changes: 5 additions & 1 deletion docs/src/pages/guides/routing/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ You can apply the same strategy with all the components (BottomNavigation, Card,

{{"demo": "pages/guides/routing/LinkRouter.js"}}

### Tabs

{{"demo": "pages/guides/routing/TabsRouter.js", "defaultCodeOpen": false}}

### Button

{{"demo": "pages/guides/routing/ButtonRouter.js"}}
Expand Down Expand Up @@ -131,4 +135,4 @@ The [example folder](https://github.com/mui-org/material-ui/tree/HEAD/examples/n

The [Link](https://www.gatsbyjs.com/docs/linking-between-pages/) component of Gatsby is built on `@reach/router`.
You can use the same previous documentation for react-router.
Unlike Next.js, it doesn't require to create an adapter.
Unlike Next.js, it doesn't require you to create an adapter.

0 comments on commit d479fc1

Please sign in to comment.