What is the best way to adjust the placement of an Icon component when it is nested within a Tab component?

Incorporating MaterialUI's tabs into my React project has been quite a task.

Here's the JSX code for the tabs:

<AppBar color="default" position="static">
       <Tabs indicatorColor="primary" textColor="primary" value={tabIndex} onChange={this.handleChange}>
         {instances.map(instance =>    
            <StyledTab                        
                    style={{ textTransform: 'initial' }}
                    onClick={() => { this.changeActiveInstance(instance.id) }}
                    label={this.getTabAddress(instance)}
                    icon={<ClearIcon ></ClearIcon>}
                  >    
            </StyledTab>
         )}                   
 </Tabs>

This is my method of injecting the CSS:

const StyledTab = withStyles({
  root: {
    textTransform: 'initial' 
  },  
})(Tab);

The output can be seen here: https://i.sstatic.net/yhwVU.png

I'm struggling to reposition the "ClearIcon" on the tabs. I've experimented with styling, but haven't had any luck.

Any guidance on how I can achieve this would be much appreciated.

Answer №1

When you want to customize a Material-UI component, the first step is to check out the CSS section of the API documentation. The key classes you might want to modify in this scenario are wrapper, labelContainer, and label.

To get a full grasp of how these classes are utilized and how they are styled by default (and hence what you might want to change), it's beneficial to examine the source code.

Highlighted below are the pertinent style excerpts from Tab.js:

 /* Styling applied to the wrapper element for `icon` and `label`. */
  wrapper: {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    width: '100%',
    flexDirection: 'column',
  },
  /* Styling applied to the label container element if `label` is given. */
  labelContainer: {
    width: '100%', // Solves an issue in IE 11
    boxSizing: 'border-box',
    padding: '6px 12px',
    [theme.breakpoints.up('md')]: {
      padding: '6px 24px',
    },
  },

Also provided is the code snippet that demonstrates the usage of these styles:

    if (labelProp !== undefined) {
      label = (
        <span className={classes.labelContainer}>
          <span
            className={classNames(classes.label, {
              [classes.labelWrapped]: this.state.labelWrapped,
            })}
            ref={ref => {
              this.labelRef = ref;
            }}
          >
            {labelProp}
          </span>
        </span>
      );
    }
        <span className={classes.wrapper}>
          {icon}
          {label}
        </span>

Below are a few examples of potential ways to customize this setup.

import React from "react";
import PropTypes from "prop-types";
import Paper from "@material-ui/core/Paper";
import { withStyles } from "@material-ui/core/styles";
import Tabs from "@material-ui/core/Tabs";
import Tab from "@material-ui/core/Tab";
import PhoneIcon from "@material-ui/icons/Phone";
import FavoriteIcon from "@material-ui/icons/Favorite";
import PersonPinIcon from "@material-ui/icons/PersonPin";

const styles = {
  root: {
    flexGrow: 1,
    maxWidth: 700
  },
  firstIcon: {
    paddingLeft: 70
  },
  labelContainer: {
    width: "auto",
    padding: 0
  },
  iconLabelWrapper: {
    flexDirection: "row"
  },
  iconLabelWrapper2: {
    flexDirection: "row-reverse"
  }
};

class IconLabelTabs extends React.Component {
  state = {
    value: 0
  };

  handleChange = (event, value) => {
    this.setState({ value });
  };

  render() {
    const { classes } = this.props;

    return (
      <Paper square className={classes.root}>
        <Tabs
          value={this.state.value}
          onChange={this.handleChange}
          variant="fullWidth"
          indicatorColor="secondary"
          textColor="secondary"
        >
          <Tab
            icon={<PhoneIcon className={classes.firstIcon} />}
            label="Class On Icon"
          />
          <Tab
            classes={{
              wrapper: classes.iconLabelWrapper,
              labelContainer: classes.labelContainer
            }}
            icon={<FavoriteIcon />}
            label="Row"
          />
          <Tab
            classes={{
              wrapper: classes.iconLabelWrapper2,
              labelContainer: classes.labelContainer
            }}
            icon={<PersonPinIcon />}
            label="Row-Reverse"
          />

          <Tab icon={<PersonPinIcon />} label="Default" />
        </Tabs>
      </Paper>
    );
  }
}

IconLabelTabs.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(IconLabelTabs);

Click here for further details

Answer №2

There is a built-in feature that allows you to customize the position of the icon in a tab using Material UI. Check out the official documentation for more information.

iconPosition: 'bottom' | 'end' | 'start' | 'top'

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When attempting to utilize Link in a Mapbox GL JS popup, an error is thrown: Invariant failed - It is advised not to use <Link> outside a <Router>

Currently, I am developing a React (16) Single Page Application that incorporates a Mapbox GL JS map with markers. The issue I am facing involves attempting to display a Link within each marker popup, causing the following error message to appear: Error: I ...

"Fixing index.html with the power of Bootstrap 4: A step-by

*I am facing an issue where the default bootstrap navbar style appears before my custom styles get applied every time I reload the page. Any assistance would be greatly appreciated* - Whenever I reload the page, the default bootstrap navbar style appears ...

Jquery Position behaving unexpectedly during initial invocation

My goal is to have the autocomplete menu open above the input box if there is not enough space below it. The code functions properly, except for the initial render. It consistently displays at the bottom in the following scenarios: 1. When starting a searc ...

Random variable without repetition in SASS

I have a unique project where I am tasked with incorporating a list of 5 specific colors into 10 different div elements. The challenge is that each color must be used twice and in a completely random order without any repetition of colors. Although utilizi ...

What might be causing my action function to be triggered during the rendering process?

While working on creating a basic card view in material UI, I encountered an issue where the functions for adding and deleting items seem to be triggered multiple times upon rendering. I am aware that a common reason for this could be using action={myFunc ...

Styling for main banner image on large desktop screens and mobile devices

I need help with website design and CSS solutions. Currently, I have a WordPress website with a onepager theme. At the top of the page, there is an image that almost fills the screen along with a title. My concern is how this image behaves with different b ...

Using a React frontend and a Node JS backend for hosting

Is it possible to host a React JS application with a Node JS back end? Should the build command be executed on the back end? ...

Are there any better methods for transforming a class component into a hook component?

After some attempts, I'm working on getting this code to function properly using useState: https://codesandbox.io/s/rdg-cell-editing-forked-nc7wy?file=/src/index.js:0-1146 Despite my efforts, I encountered an error message that reads as follows: × ...

The Dialog component is overlapping the ColumnMenu in the Material UI DataGrid

A DataGrid is housed within a Dialog, causing the column menu to be obscured by the Dialog itself. To see a demonstration of this issue, please refer to the following demo on SandBox My attempted solutions: I noticed that Dialog creates an html tag The ...

The alternative text for the oversized image exceeds the boundaries

After setting the width and height for an image, along with testing overflow:hidden, I've encountered an issue where the alt text for a broken image overflows the bounds of the image and the image size is lost. How can I contain the alt text within th ...

What is the best way to relocate a child component to a different parent in React?

I have a list of child components with checkboxes, and when a checkbox is clicked, I want to move that child component inside another div. Below is an illustration of how my app should look. I need to select student names and shift them up under the "Pres ...

Unable to transmit form information in 'Multipart/formdata' format

Having trouble sending form data with 'multipart/formdata' Content type in a react-native expo app. When we attempt to send formData object in a post request within our react-native app, we are not able to access req.body or req.files from the no ...

Is there a material button available for use in Java programming?

Is it possible to integrate Material UI into a Java application? I am currently developing a calculator using Swing and AWT in Eclipse, and I'm interested in incorporating Material Design elements such as the material button. Has anyone successfully ...

What is preventing the two spans from being centered within the div?

I'm having trouble centering the two spans within the div. How can I fix this issue? The code below is not working, but when I move the div outside of the two spans and change the display property to inline-block, it works. Why is this happening? b ...

My application was successfully deployed on Heroku, but unfortunately, it is not retrieving data from the database as expected

Despite successfully deploying my app on Heroku, I encountered an issue with loading data. After scouring through various articles and tutorials, I couldn't find a solution to connecting my local PostgreSQL data with Heroku addons. While my app funct ...

The component is expected to return a JSX.Element, however it is failing to return any value

The issue lies with this component: const NavigationItems = (props: {name: string, href: string}[]): JSX.Element => { props.map((item, index) => { return <a href={item.href} key={index}>{item.name}</a> }) }; export default Naviga ...

Photos appearing outside the border

My current border has a vertical flow like this: https://i.sstatic.net/CdUm6.png (source: gyazo.com) However, I want the content to flow horizontally from left to right instead of top to bottom. When I apply float: left; to the controlling div, it resu ...

Running a 2D JavaScript game script on a React page - A step-by-step guide!

I am facing a challenge with my website that features a game coded entirely in javascript. Despite my efforts to switch the site from an HTML layout to a more modern React design, I can't seem to get the game to display correctly. In the original HTM ...

Make the child div images disappear gradually and at the same time, make an overlapping parent div image appear using Javascript

Check out my attempt at solving this challenge on jsfiddle: http://jsfiddle.net/oca3L32h/ In the scenario, there are 3 divs within a main div. Each of these divs contains an image and they overlap each other. By using radio buttons, the visibility of the ...

Photo not completing the table

Hey there, I'm currently working on creating a table to showcase some products but I am struggling with ensuring that the images display at the correct size. Any assistance on this matter would be greatly appreciated. #tbldesktops { width: 100%; ...