React router link messes up MUI tab component styling - reactjs

I'm having certain styling for the <Tab> component from MUI and currently I'm wrapping this tab with a <Link> from react-router-dom. The <Tab> has some styling which handles the active tab etc. but the Link messes this up.
What is the cleanest way to make sure the <Link> styling gets removed and it displays the <Tab> styling instead?
Code is as follow:
<Link to='/app/listings'>
<Tab value="one" icon={<FormatListBulletedIcon />} label="Challenges" iconPosition='start' />
</Link>`
edit:
The <Tab> is styled in my MUI Theme as followed:
components: {
MuiTab: {
styleOverrides: {
root: {
minHeight:24,
fontSize: 12,
padding: '6px 10px',
justifyContent: 'flex-start'
},
},
},
},
The <Link tag wrapping it overwrites this.
Simple example: https://codesandbox.io/s/confident-framework-u01mdk?file=/src/App.js
Remove the Link tag and styling changes.

You can render the Tab component as a Link.
Instead of
<Link color="inherit" to="/app/listings">
<Tab
value="one"
icon={<FormatListBulletedIcon />}
label="Challenges"
iconPosition="start"
/>
</Link>
use the Tab component's component prop to really render the Link component and pass all the link props to the Tab.
<Tab
component={Link}
color="inherit"
to="/app/listings"
value="one"
icon={<FormatListBulletedIcon />}
label="Challenges"
iconPosition="start"
/>

Related

Mapping Horizontal divider using Material UI react

I'm working on menu component storybook where i have mapped icon & text , problem is i have horizontal divider in between , how do i Map it with icons & text.From below code i'm getting divider at the bottom of the Menu. I'm trying to achieve as it is in the image. In the storybook i have to map few menu variants as in mui, for that i cannot hardcode divider, if there is any way i can manage it with Map or any other method. Thanks.
export const Menu= ({ icons }) => {
return (
<Paper sx={{ width: 320, maxWidth: '100%' }} >
<MenuList>
{icons.map((item) => (
<MenuItem>
<ListItemIcon fontSize="small">{item.icon}</ListItemIcon>
<ListItemText>{item.label}</ListItemText>
<Typography variant="body2" color="text.secondary">{item.typography}</Typography>
</MenuItem>
))}
<Divider /> /* how do i map this */
</MenuList>
</Paper >
);
}
Stories.js
icons: [
{ icon: <ContentCut fontSize="small" />, typography: "⌘X", label: "Cut" },
{ icon: <ContentCopy fontSize="small" />, typography: "⌘C", label: "Copy" },
]
Answer:
If you want the divider to be just one then don't map over it . thats the purpose of the .map() method.
and To Acheive the required results i just removed <Menu></Menu> Component and Just Kept the <Papper></Papper> Component
Notes :
In terms of how to Map the Divider with the below example ,you can just wrap it in a empty react fragment<></> and map over the <MenuItem></MenuItem> .
Only issue is that youll get an error in your key props which will say its not unique it can be fixed by assigning index key like the example below and wrap the <MenuItem></MenuItem> Component in It. However thats not best practice ,
<React.Fragment></React.Fragment> Is better practice according to Keyed Fragment React 18 Docs to add a key prop However that's giving a New Error in MUI.
Thats not an issue since were mapping over the MenuItem Component , However if we use for example in #Nathan Comments <React.Fragment key={index}></React.Fragment> or my previous answer to use <></> we would be mapping over the React.Fragment Itself or the empty fragment and would get a new error MUI: The Menu component doesn't accept a Fragment as a child. Uncomment the Examples in the Sandbox Check the sandbox console.
Check Code Code SandBox
Solution
export const MenuIcon = ({ menuicons }) => {
return (
<Paper sx={{ width: 320, maxWidth: "100%" }}>
{menuicons.map((item, index) => (
<MenuItem key={item + index}>
<ListItemIcon fontSize="small">{item.icon}</ListItemIcon>
<ListItemText>{item.label}</ListItemText>
<Typography variant="body2" color="text.secondary">
{item.typography}
</Typography>
</MenuItem>
))}
<Divider />
<ListItemIcon fontSize="small">
ClipBoard <ContentCopyIcon fontSize="small" />
</ListItemIcon>
</Paper>
);
}
References
Empty Fragment Syntax React Docs
Stack OverFlow Question MUI Icons - as props
.map() method Syntax - MDN Docs

Change the position of Tabs' indicator in Material UI

I'm trying to set the position of the indicator to the top of TAB instead of the bottom like:
I checked and tried to update CSS but it didn't work. I'm new to react so I couldn't customize the components.
I create an example in codesandbox that I share with you.
https://codesandbox.io/s/usage-p0y9t?file=/index.js
You can pass to Tabs the property classes to override internal classes.
In this case you can pass a new class to the indicator and override his style.
Take a look at the link below
https://material-ui.com/api/tabs/#css
To reinforce #Xavier 's answer, I found that we could use the TabIndicatorProps prop for Tabs component as below.
<Tabs
TabIndicatorProps={{
sx: {
top: 0
}
}}
>
<Tab label="One" />
<Tab label="Two" />
<Tab label="Three" />
</Tabs>
2022 Solution
https://mui.com/styles/basics/
#mui/styles is the legacy styling solution for MUI. It depends on JSS as a styling solution, which is not used in the #mui/material anymore, deprecated in v5. If you don't want to have both emotion & JSS in your bundle, please refer to the #mui/system documentation which is the recommended alternative.
⚠️ #mui/styles is not compatible with React.StrictMode or React 18.
You can utilise the sx property on the component to access any css classes directly.
https://mui.com/api/tabs/#css
<Tabs
orientation="vertical"
value={value}
onChange={handleChange}
sx={{
'.MuiTabs-indicator': {
left: 0,
},
}}
>
<Tab label="One" />
<Tab label="Two" />
<Tab label="Three" />
</Tabs>

How to make material ui icon clickable and redirect to url

I want to make GitHub icon <GitHubIcon /> clickable and make it redirect to external url, looking in the api it doesn't seem to have link prop ... https://material-ui.com/api/svg-icon/
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<Typography variant="h6" className={classes.title}>
Made with <FavoriteIcon /> by
<GitHubIcon /> //Not working
</Typography>
</Toolbar>
</AppBar>
</div>
How is it done usually ??
Add this:
<GitHubIcon onClick={handlePageChange} />
and on the function definition:
const handlePageChange() {
window.location.href="pagelink"
}
or directly using an arrow function:
<GitHubIcon onClick={event => window.location.href='pagelink'} />
If looking to add effects on hover with material-ui styles:
How to add stlyes on Material-UI:
Import makeStyles:
import { makeStyles } from '#material-ui/core/styles';
Create the class:
const useStyles = makeStyles(theme => ({
clickableIcon: {
color: 'green',
'&:hover': {
color: 'yellow',
},
},
}));
Add the API call on your function declaration:
const classes = useStyles();
And add this class to your element:
<GitHubIcon
onClick={event => window.location.href='pagelink'}
className={classes.clickableIcon}
/>
You could also use directly a css file.
I'm not really happy with css styling over material-ui api, specially because this horrible CSS-in-JS syntaxi, but it works well, here you'll find some documentation: Material-ui Styles

React / Material UI complex styling

I have an issue related with styling in React / Material UI. I think is an issue related with TouchRipple from Material-UI
<div key={indexP}>
<Link className={classes.link} to={parent.link}>
<ListItem button selected={this.state.treeParentOpen[indexP] === true} onClick={this.handleClick(indexP)}>
<ListItemIcon>
<ParentIcon />
</ListItemIcon>
<ListItemText primary={parent.title} />
</ListItem>
</Link>
<Divider />
</div>
I have the above code inside a Drawer component (this is a small extract just to exemplify), for a Sidebar menu.
The issue i am having is related with the styling interaction of the ListItem and Link Components.
If i take the Link out of the code i have a normal ListItemripple behaviour (onclick and offclick), everything is pretty and in grey shades.
When i had the Link to the code (as is), the ripple behaviour of the ListItem changes and onClick is Blue and offClick purple. How should i address the styling of the ripple effect associated with buttonBase used in ListItem.
Thanks!

How can I have full-height Tabs inside of a Toolbar using material-ui?

I am trying to have a fixed header where on the right side should be tabs. The <Toolbar /> component is responsible for the responsiveness of the block but doesn't allow for stretched tabs so easily.
https://codesandbox.io/s/jv8v6vwqpv
The problem is that the Toolbar responsively changes its height and the Tabs and Tab component do not (Tabs sets a min-height of 48px in its root class, Tab sets a height in its root class).
Fortunately, the behavior Toolbar uses is available in a theme mixin, so you can create classes that also use this logic:
const styles = theme => ({
fullHeight: {
...theme.mixins.toolbar,
},
});
This will create a class that has the same responsive height logic used in the Toolbar component. Using withStyles, you can make this class accessible to your component:
import { withStyles } from "material-ui/styles";
// ...
export default withStyles(styles)(Header);
This will add a classes prop, which is an object containing a string attribute for each class defined in the object provided to withStyles. You can apply this to the Tabs component and each Tab component by overriding their root classes to ensure that they fill the AppBar:
render() {
const { classes } = this.props;
return (
<AppBar>
<Toolbar>
<Grid container alignItems="center" justify="space-between">
<Grid item>
<Typography color="inherit" variant="title">
BackTube
</Typography>
</Grid>
<Grid item>
<Tabs classes={{ root: classes.fullHeight }} onChange={this.changeTab} value={this.state.currentTab}>
<Tab classes={{ root: classes.fullHeight }} icon={<Magnify />} value="search" />
<Tab classes={{ root: classes.fullHeight }} icon={<FormatListBulleted />} value="lists" />
<Tab classes={{ root: classes.fullHeight }} icon={<Settings />} value="settings" />
</Tabs>
</Grid>
</Grid>
</Toolbar>
</AppBar>
);
Please note that the above solution was written for MUI v1 beta.
UPDATED 5/2022: The same thing can be accomplished in MUI 5, here is a codesandbox

Resources