Adjusting the gap between svg icon and text on Material-UI's List component - material-ui

I've been trying to figure out how to lessen the gap using css with no luck. I created the style object and used leftPosition key but the result was not the one I expected. I was expecting that the text is the only thing that will move. However, if you look at the screenshot specifically the first menu, the icon also moved. What I'd like to achieve is reduce the gap between the svn icon and the text.
import React from 'react';
import List from 'material-ui/lib/lists/list';
import ListItem from 'material-ui/lib/lists/list-item';
import ActionGrade from 'material-ui/lib/svg-icons/action/grade';
import ActionInfo from 'material-ui/lib/svg-icons/action/info';
import ContentInbox from 'material-ui/lib/svg-icons/content/inbox';
import ContentDrafts from 'material-ui/lib/svg-icons/content/drafts';
import ContentSend from 'material-ui/lib/svg-icons/content/send';
import Divider from 'material-ui/lib/divider';
import Assignment from 'material-ui/lib/svg-icons/action/assignment';
import Settings from 'material-ui/lib/svg-icons/action/settings';
import ManageDB from 'material-ui/lib/svg-icons/content/unarchive';
const style = {
menu: {
marginRight: 32,
marginBottom: 32,
float: 'left',
position: 'relative',
zIndex: 0,
width: 235,
},
rightIcon: {
textAlign: 'center',
lineHeight: '24px',
},
width: {
width: 235
},
leftPosition: {
left: 50
}
};
const LeftNavigation = () => (
<div>
<List>
<ListItem style={style.leftPosition} primaryText="Logs" leftIcon={<Assignment />} />
<ListItem primaryText="Manage DB" leftIcon={<ManageDB style={style.gap}/>} />
<ListItem primaryText="Top Issues" leftIcon={<ContentSend style={style.gap}/>} />
<ListItem primaryText="Settings" leftIcon={<Settings style={style.gap}/>} />
<ListItem primaryText="Logout" leftIcon={<ContentInbox style={style.gap}/>} />
</List>
<Divider />
<List>
<ListItem primaryText="All mail" rightIcon={<ActionInfo />} />
<ListItem primaryText="Trash" rightIcon={<ActionInfo />} />
<ListItem primaryText="Spam" rightIcon={<ActionInfo />} />
<ListItem primaryText="Follow up" rightIcon={<ActionInfo />} />
</List>
</div>
);
export default LeftNavigation;

The accepted solution didn't work for me. Here is what I ended up doing after exploring the DOM.
const useStyles = makeStyles((theme) => ({
icon: {
minWidth: '30px',
}
}));
and then apply this class for the ListItemIcon as:
<ListItemIcon className={classes.icon}> <HelpOutlineIcon/> </ListItemIcon>
Hope it helps someone save time.

You can add style in ListItemIcon.
<ListItemIcon style={{minWidth: '40px'}} >

This is what worked for me. I set this in my global css file.
.MuiListItemIcon-root {
min-width: 40px !important;
}

If you want to do it globally use overrides in createMuiTheme
const theme = createMuiTheme({
overrides: {
MuiListItemIcon: {
root: {
minWidth: 40,
},
},
},
})
Note:
If you're using MUI version 5 then locate createTheme instead of createMuiTheme

This is my 2¢:
<ListItemText primary={<div style={{ margin: -25, marginTop: -7, color: 'white', fontSize: 11 }}>Your text here</div>} />
Adjusting margin (n.b., it's a negative number) and the top margin you can align the icon (on the left) with your text

You can also use sx prop instead of style, if you want access to the theme object, e.g.:
<ListItemIcon sx={{minWidth: (theme) => theme.spacing(4)}}>

This is only applicable to Mui 1.x.x. For later versions, please see responses to this answer below.
The ListItem renders a div called innerDiv with 72px left/right padding to render the left/right icon and label with sufficient space. You should try this in the Style -
<ListItem innerDivStyle={{paddingLeft: 60}} primaryText="Logs" leftIcon={<Assignment />} />
Replace 60 with whatever pleases you.

Just information for #Adam Mańkowski 's answer.
In MUI v5.5, you can config your theme like this.
createTheme({
components: {
MuiListItemIcon: {
styleOverrides: {
root: {
minWidth: 0
}
}
}
}
});

Related

How can I ensure that switch label is aligned veritical with the actual control

I have a component that opens/closes a material-ui table. I use a switch to open/close that component. This largely works exactly as I want. I have a minor aesthetic issue with the placement of the Hide/Show text. The top of the text aligns with the horizontal center of the switch control.
Here is the switch code.
<FormControlLabel
className={classes.switch}
control={<Switch checked={show} onChange={handleChangeShow} />}
label={show ? "Hide" : "Show"}
/>
Notice that the Show/Hide label is not aligned with the switch itself. It's too low. How can I fix this?
Here is the makeStyles function.
const useStyles = makeStyles((theme) => ({
root: {
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(1),
flexDirection: "column",
display: 'flex'
},
container: {
width: (props) => (props.show ? "inherit" : "0px"),
height: (props) => (props.show ? "inherit" : "0px")
},
switch: {
justifyContent: "flex-end",
alignItems: "flex-end"
},
}
Here is the wrapper code:
return (
<div className={classes.root}>
<Typography>{title}</Typography>
<div className={classes.container}>
<Fade in={show}>
<Paper className={classes.paper}>{frames_view}</Paper>
</Fade>
</div>
<FormControlLabel
className={classes.switch}
control={<Switch checked={show} onChange={handleChangeShow} />}
label={show ? "Hide" : "Show"}
/>
</div>
Ok.. Looks like it was solved by wrapping in a FormGroup:
<FormGroup
className={classes.switch}
row
>
<FormControlLabel
control={<Switch checked={show} onChange={handleChangeShow} />}
label={show ? "Hide" : "Show"}
/>
</FormGroup>

How should a set width nav be made into a sticky in Material UI?

New to Material UI I'm trying to create a sticky div with a set width similar to how Material UI has their side nav on the right of their docs. For some reason I'm unable to get the div to stick. Per research and the docs I've read through several questions and here are my attempts:
Attempt 1
I tried utilizing Box but it scrolls with the page:
import React from 'react'
import { Hidden, Box, List,ListItem } from '#material-ui/core/'
import { makeStyles } from '#material-ui/core/styles'
const useStyles = makeStyles(theme => ({
box: {
background: 'red',
position: 'sticky',
top: 70,
bottom: 20,
paddingTop: 100,
marginTop: theme.spacing(2),
width: 300,
},
sub: {
display: 'block',
overflow: 'auto',
},
}))
const SideToc = ({ nav }) => {
const { box, sub } = useStyles()
return (
<>
<Hidden smDown>
<Box className={box}>
Contents
<List className={sub} component="nav" aria-label="main mailbox folders">
<ListItem button>Monday</ListItem>
<ListItem button>Tuesday</ListItem>
<ListItem button>Wednesday</ListItem>
</List>
</Box>
</Hidden>
</>
)
}
export default SideToc
Attempt 2
after research I've found a few mentions of Drawer but when I deploy the below component my green drawerPaper is fixed to the left and my blue Drawer is to the right a correct width.
import React from 'react'
import Drawer from '#material-ui/core/Drawer'
import Hidden from '#material-ui/core/Hidden'
import List from '#material-ui/core/List'
import ListItem from '#material-ui/core/ListItem'
import { makeStyles } from '#material-ui/core/styles'
const SideToc = ({ nav }) => {
const useStyles = makeStyles(theme => ({
toolbar: theme.mixins.toolbar, // necessary for content to be below app bar
drawer: {
background: 'blue',
width: 300,
flexShrink: 0,
},
drawerPaper: {
marginTop: 120,
background: 'green',
},
}))
const { toolbar, drawer, drawerPaper } = useStyles()
return (
<>
<div className={toolbar} />
<Hidden smDown>
<nav className={drawer} aria-label="mailbox folders">
<Drawer
classes={{
paper: drawerPaper,
}}
variant="permanent"
>
Contents
<List component="nav" aria-label="main mailbox folders">
<ListItem button>Monday</ListItem>
<ListItem button>Tuesday</ListItem>
<ListItem button>Wednesday</ListItem>
</List>
</Drawer>
</nav>
</Hidden>
</>
)
}
export default SideToc
Here is my parent component that has the content with the set width nav:
import React from 'react'
import { makeStyles } from '#material-ui/core/styles'
// Components
import SideToc from './SideToc'
const useStyles = makeStyles(theme => ({
toolbar: theme.mixins.toolbar, // necessary for content to be below app bar
content: {
flexGrow: 1,
padding: theme.spacing(3),
overflow: 'hidden',
background: 'orange',
},
}))
const Parent = ({ nav, children }) => {
const { content, toolbar } = useStyles()
return (
<>
<main className={content}>
<div className={toolbar} />
{children}
</main>
<SideToc className={toolbar} nav={nav} />
</>
)
}
export default Parent
Research
How to make a Material UI grid element sticky?
Reactjs Material-ui hide appBar sticky or static
Make a React Material-UI component to stick to the bottom-right of the screen
React Material-Ui Sticky Table Header with Dynamic Height
In Material UI if I want a div to be sticky that will not scroll and have a fixed width how should that be done? Is my issue due to my parent? Should I be using Material's Grid in this approach?
Edit
After further testing I am able to get the side nav to stick but the content, if outside the viewport, will not allow scrolling. The parent component has been modified with just a div surrounding the SideToc component:
<>
<main className={content}>
<div className={toolbar} />
{children}
</main>
<div>
<SideToc toc={toc} />
</div>
</>
SideToc Component:
import React from 'react'
import { Hidden, Box, List, ListItem } from '#material-ui/core/'
import { makeStyles } from '#material-ui/core/styles'
const useStyles = makeStyles(theme => ({
box: {
marginTop: theme.spacing(8),
top: theme.spacing(8),
width: 250,
position: 'sticky',
right: 0,
overflowY: 'auto',
flexShrink: 0,
},
}))
const SideToc = ({ nav }) => {
const { box } = useStyles()
return (
<>
<Hidden smDown>
<Box className={box} component="nav">
Contents
<List component="nav">
<ListItem button>Monday</ListItem>
<ListItem button>Tuesday</ListItem>
<ListItem button>Wednesday</ListItem>
</List>
</Box>
</Hidden>
</>
)
}
export default SideToc
Per request:

In Material UI how can I modify MuiBotton-endIcon's margin left?

New to Material UI I'm building a navigation component while reading through the docs and I ran across Buttons with icons and label. Wanting to build a button I created my component but there is a large gap between the text and icon.
Button:
<Button
onClick={selected}
{...{
size: 'small',
'aria-label': 'menu',
'aria-haspopup': 'true',
}}
className={navBtn}
endIcon={<MenuIcon />}
>
Menu
</Button>
When I review button in the browser the rendered element is:
<span class="MuiButton-endIcon">
<svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path>
</svg>
</span>
followed with the CSS of:
.MuiButton-endIcon {
display: inherit;
margin-left: 8px;
margin-right: -4px;
}
Wanting to modify the CSS of the margin left I attempted to target MuiButton-endIcon:
navBtn: {
color: '#363537',
verticalAlign: 'middle',
'&:hover': {
backgroundColor: '#FFFFFF',
boxShadow: 'none',
},
'&:focus': {
boxShadow: 'none',
},
MuiButtonEndIcon: {
marginLeft: '2px',
},
},
which did not work. The only hack I can get to work is to add a span with inline styling:
<Button
onClick={selected}
{...{
size: 'small',
'aria-label': 'menu',
'aria-haspopup': 'true',
}}
className={navBtn}
endIcon={<MenuIcon />}
>
<span style={{ marginRight: '-6px' }}>Menu</span>
</Button>
the full component:
import React from 'react'
// Material UI
import { Button } from '#material-ui/core'
import MenuIcon from '#material-ui/icons/Menu'
// Styles
import useStyles from '../styles'
const NavIcon = ({ selected }) => {
const { navBtn } = useStyles()
return (
<Button
onClick={selected}
{...{
size: 'small',
'aria-label': 'menu',
'aria-haspopup': 'true',
}}
className={navBtn}
endIcon={<MenuIcon />}
>
<span style={{ marginRight: '-6px' }}>Menu</span>
</Button>
)
}
export default NavIcon
Research:
Align material icon vertically
How to Align tab-label and tab-icon horizontally in material-UI using Tabs API
Centered icon and text (React Material-UI)
Material UI - Align icon to center with the Typography text
In Material UI is there a way to modify the margin from the <MenuIcon /> to the text with a <Button /> without implementing an inline style hack on the text?
Edit
Per the answer that mentioned spacing I tried the following:
on <Button>:
<Button
m={1}
onClick={selected}
{...{
size: 'small',
'aria-label': 'menu',
'aria-haspopup': 'true',
}}
className={navBtn}
endIcon={<MenuIcon />}
>
Menu
</Button>
on <MenuIcon>:
<Button
onClick={selected}
{...{
size: 'small',
'aria-label': 'menu',
'aria-haspopup': 'true',
}}
className={navBtn}
endIcon={<MenuIcon m={1} />}
>
Menu
</Button>
styling:
navBtn: {
color: '#363537',
'&:hover': {
backgroundColor: '#FFFFFF',
boxShadow: 'none',
},
'&:focus': {
boxShadow: 'none',
},
},
and there is no effect on the margin to the component. My understanding from the docs for spacing to work I would need to build a theme.
for every component of the material-ui, they take a classes prop, by which you can target the inside classes directly. For endIcon, button receives a style object to endIcon key in classes prop.
App.js
import React from 'react'
// Material UI
import { Button } from '#material-ui/core'
import MenuIcon from '#material-ui/icons/Menu'
// Styles from style.js
import styles from './styles'
const NavIcon = ({ selected }) => {
const classes = styles()
return (
<Button
{...{
size: 'small',
'aria-label': 'menu',
'aria-haspopup': 'true',
}}
classes={{endIcon:classes.endIcon}}
endIcon={<MenuIcon />}
className={classes.navBtn}
>
<span style={{ marginRight: '-6px' }}>Menu</span>
</Button>
)
}
export default NavIcon
styles.js
import { makeStyles, createStyles } from '#material-ui/core/styles';
const useStyles = makeStyles(() =>
createStyles({
endIcon:{
marginLeft:'4px'
},
navBtn: {
color: '#363537',
'&:hover': {
backgroundColor: '#FFFFFF',
boxShadow: 'none',
},
'&:focus': {
boxShadow: 'none',
},
},
}),
);
export default useStyles
Add the required margin in endIcon class.
Documentation
From the Spacing docs
In order for it to work you have to wrap the element you want in a so called "Box"
import Box from '#material-ui/core/Box';
You can specify a prop called "m" to the Button, for example:
<Box m="5px"> <Button /> </Box>
This adds 5 pixels to the overall margin of the button, but if you want to apply only margin to the left you can do:
<Box ml="5px"> <Button /> </Box>

How can i change CSS of select component that inherited from inputBase, outlined and their pseudo-class

I am trying to customize CSS of a select component of material-ui this is inherited from class="MuiInputBase-root-97 MuiInput-root-84 MuiInput-underline-88 MuiInputBase-formControl-98 MuiInput-formControl-85" now i am stuck not able to change default design. Please help me, I don't have much experience with material-ui
I have tried to pass an object in classes props of select to change style applied by MuiInputBase-root-97, MuiInput-root-84, MuiInput-underline-88, MuiInputBase-formControl-98, MuiInput-formControl-85, and their pseudo class
const styles = theme => ({
root: {
'&$hover': {
color: 'red',
},
},
inputUnderline: {
minWidth: 220,
},
selectEmpty: {
marginTop: theme.spacing.unit * 2,
},
formControl: {
margin: theme.spacing.unit,
minWidth: 120,
},
});
<FormControl className={classes.formControl}>
<Select
value={this.state.age}
onChange={this.handelchange}
name="age"
displayEmpty
className={classes.selectEmpty}
classes={{
underline: classes.inputUnderline //change css of MuiInput-underline-88 and their pseudo class
root: classes.inputBaseRoot //want to change css of MuiInputBase-root-97 and their pseudo class
}}
>
<MenuItem value="" disabled>
Placeholder
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
<FormHelperText>Placeholder</FormHelperText>
</FormControl>
I want to remove border at the bottom on hover, focus, after, and before
I want a custom design in it overrides all CSS class at a select componentstrong text
In material-ui, you can override the style and customize it according to your requirement.
Please refer https://material-ui.com/customization/overrides/

How to style FormControlLabel font size

How do you set the in-line font size on a Material-UI FormControlLabel? The below attempt does not work.
const styles: any = createStyles({
formControlLabel: { fontSize: '0.6rem',
'& label': { fontSize: '0.6rem' } }
});
<FormControlLabel style={styles.formControlLabel}
control={<Checkbox value="Hello" color="primary" />}
label="World"
/>
You could define the label as a Typography component and apply the style there:
<FormControlLabel
control={<Checkbox value="Hello" color="primary" />}
label={<Typography style={styles.formControlLabel}>World</Typography>}
/>
UPDATE:
As per Saber's comment, newer versions should instead use:
<FormControlLabel
control={<Checkbox value="Hello" color="primary" />}
label={<Typography className={styles.formControlLabel}>World</Typography>}
/>
Use material box fontSize instead of giving external style.
<FormControlLabel
control={<Checkbox name="checkbox" />}
label={
<Box component="div" fontSize={15}>
Small
</Box>
}
/>
FormControlLabel exposes typography as prop. tested and works in Mui V5. https://mui.com/api/form-control-label/#props
<FormControlLabel
componentsProps={{ typography: { variant: 'h3' } }}
/>
Use overrides section in theme.ts
export default createMuiTheme({
overrides: {
MuiFormControlLabel: {
label: {
fontSize: 14,
},
},
});
In MUI v5 you could do it like this:
<FormControlLabel
label={
<Typography sx={{ fontSize: 16 }}>
Label Text
</Typography>
}
control={<Switch />}
/>
Here's another option to achieve the same thing, but without the extra p that using <Typography /> will give you (referencing MUI v4 as the post is from before v5, although I'm sure this solution will work there too).
By referring to the docs for the FormControlLabel you can see the styles for the label can be modified with the label rule (kinda like you've tried to do already), however another approach would be to style the label by using withStyles
const StyledFormControlLabel = withStyles(() => ({
label: {
fontSize: '0.6rem',
}
}))(FormControlLabel);
...
<StyledFormControlLabel
control={<Checkbox value="Hello" color="primary" />}
label="World"
/>