2

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:

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.

DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127

2 Answers2

3

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.

Edit Invisible Backdrop

Documentation

Rajiv
  • 3,346
  • 2
  • 12
  • 27
  • Interesting approach but how can someone incorporate `navBtn` CSS from `makeStyles` with `createStyles` in one so it can be moved to a document like *styles.js*? I see that `navBtn` is changed from `className` to `classes`. – DᴀʀᴛʜVᴀᴅᴇʀ Jan 15 '21 at 18:43
  • create another class in styles.js object for the end icon and then pass that class to the endIcon – Rajiv Jan 15 '21 at 18:45
  • ya I see that but what I'm wondering is if I have two style objects from a file what is the best way to bring each on it and use two different styles from two different objects. – DᴀʀᴛʜVᴀᴅᴇʀ Jan 15 '21 at 18:48
  • 1
    now check the answer. Are you talking about something like this?? – Rajiv Jan 15 '21 at 18:53
  • can also be done in one prop: `classes={{ root: classes.navBtn, endIcon: classes.endIcon }}` – hotpink Jan 15 '21 at 19:00
0

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> 
DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
Marteam
  • 29
  • 4