Customize Tab indicator styling in Material-UI

Currently, I am attempting to customize the MUI tab by changing the indicator from a line to a background color. Through my research, I discovered that using TabIndicatorProps and setting a style of display:none eliminates the indicator completely. However, when I try

backgroundColor:"color"
, the line color changes but I'm struggling to make it span the entire background instead of just a line.

I experimented with some potential solutions, such as adding height:100% to the TabIndicatorProps, which resulted in creating the background but obscured the text within the tab. Likewise, applying opacity: .8 gave me the desired effect, but the text became too dark and I was unable to adjust it for active tabs.

Expected Tab Image Current Tab Image

<Box sx={{ width: '100%', bgcolor: 'background.paper' }}>
            <Tabs TabIndicatorProps={{
                style: {
                    backgroundColor: '#D2603D',
                    borderRadius: '5px',
                },
            }} value={value} onChange={handleChange}>
                <Tab textColor='blue' onClick={handleClick} sx={{
                    backgroundColor: '#F4F5F9',
                    borderRadius: '5px',

                }} label="Daily" />
                < Tab sx={{
                    backgroundColor: '#F4F5F9',

                }} label="Weekly" />
                <Tab sx={{
                    backgroundColor: '#F4F5F9',
                    borderRadius: '5px'
                }} label="Monthly" />
            </Tabs>
        </Box >

Answer №1

It doesn't seem feasible to achieve this in a straightforward manner. Options include resorting to less elegant solutions or completely revamping the functionality.

The tab labels are represented by <button> elements, while the tab indicator is a <span> positioned above these buttons. If you want the labels to appear above the indicator, you will need to either rearrange the hierarchy of HTML elements or introduce a secondary label above the indicator.

Unfortunately, it's not possible for the tab indicator to slide behind the button text but in front of the button background.

Here are some suboptimal ("dirty") workarounds:

  1. You can rearrange the stacking order of the HTML elements.

This can be achieved using the z-index property. You have to assign specific z-index values to the buttons and ensure that the button backgrounds remain transparent.

Take caution if there are other elements with existing z-index values or if they need to stay behind the buttons; in such cases, their z-index values might also need adjustment.

<Tab label="Daily" style={{ zIndex: 1 }} />
<Tab label="Weekly" style={{ zIndex: 1 }} />
<Tab label="Monthly" style={{ zIndex: 1 }} />
  1. You could append the current label as a child of the tab indicator, matching its style with the original label. Additionally, you would need to pass the current label so that it moves with the indicator or remains empty during sliding.
const IndicatorLabel = ({ label }) => {
  return <span className={'indicator-label'}>
    { label }
  </span>;
};

// ...

<Tabs
  TabIndicatorProps={{
    // ...
    children: <IndicatorLabel label={ currentLabel } />
  }}
>

// ...
  1. You could dynamically set the background color of the <button>, bypassing the use of the indicator altogether. However, this approach sacrifices the sliding effect.

  2. Alternatively, you could create your own custom tab indicator from scratch instead of relying on the MUI tab indicator.

Answer №2

Even though this may seem outdated, it could still be useful for anyone who is searching for a solution.

In MUI5, you can customize Tabs with styles using the code snippet below:

import { Tabs as MuiTabs } from '@mui/material';
import { styled } from '@mui/material';

const Tabs = styled(MuiTabs)(({ theme }) => ({
    '& .MuiTab-root': {
        margin: "8px 5px 8px 5px",
        borderRadius: "6px",
        lineHeight: 0,
        minHeight: "unset",
        padding: "16px",
        color: "grey",
        fontWeight: 700,
    },
    '& .MuiTab-root.Mui-selected': {
        backgroundColor: "#ff7100",
        fontWeight: 700,
        color: "white"
    }
}));

export default Tabs

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

Exploring the hidden contents within the zip file

I have been exploring methods for reading 'zip' files. Two libraries that I have used are zip.js and JSzip. I have successfully viewed the contents of the zip file. However, here lies the challenge: My goal is to identify specific file types ...

Listen for the load event during an AJAX request without using jQuery's add

I have four HTML files and four corresponding JavaScript files. Each JavaScript file is externally loaded by its respective HTML file. Specifically, index.html loads javascript.js, 1.html loads javascript1.js, 2.html loads javascript2.js, and 3.html loads ...

The JavaScript function is not being activated by clicking on Selenium in Chrome

Take a look at the HTML snippet below: <table class="table-main "> <thead> <tbody> <!----> <tr class="" ng-if="mapCtrl.isAdded" style=""> <td/> <td> <td> <t ...

Initial argument for the event listener

If I have event handlers registered inline in my markup (even though it's deprecated) like span id="..." onclick="foo(p1,p2,p3)" how do I access the "event" object in the event handler function foo? Is changing the above to span ...

Multiple callbacks triggered by jQuery CSS transitions

I am experiencing an issue with my menu animation. I am curious as to why the slideDown transition is occurring twice. You can view the JSFiddle here. <ul class=top-menu"> <li>Item 1</li> <li>Item 2</li> <ul cl ...

Conceal additional recipients in the "to" address field when sending emails with Node.js using Nodemailer

I am currently working on a project called EmailSender using node.js, and I have found that the nodemailer package is incredibly helpful. However, when sending emails to multiple contacts, all recipients are able to see each other's email addresses i ...

Seeking Up/Down Arrows HTML numerical input feature specifically designed for iOS devices

I am having an issue with a number input box on iOS. I am utilizing jquery, kendo mobile, and HTML5 for this particular task. While the number input displays up and down arrows in the Icenium simulator, they are not showing on the iPad. I am seeking a sol ...

Navbar optimization by eliminating unnecessary whitespace at the end

I'm working on a navigation bar that has four links. I need to get rid of the extra space to the left of "Projects" and to the right of "Contact." It seems like this spacing is part of the unordered list structure, rather than padding or margin. Chec ...

Having trouble getting the form to submit with jQuery's submitHandler

I am in the process of converting a contact form to AJAX so that I can utilize the success function. Currently, I am encountering an issue where the code is halting at the submitHandler section due to it being undefined. Can anyone identify why my submitHa ...

Gaining access to the isolated scope of a sibling through the same Angular directive led to a valuable discovery

I am currently working on an angularjs directive that creates a multi-select dropdown with a complex template. The directives have isolated scopes and there is a variable called open in the dropdown that toggles its visibility based on clicks. Currently, t ...

I am currently working on updating row values within the MUI datagrid using the processRowUpdate property. However, I have encountered an issue where I am only able to retrieve the most recently updated cell value

Here, the **Skills** array consists of objects with values that are being updated. const handleProcessRowUpdate = (newRow, oldRow) => { console.log("update called", newRow, oldRow); let skills = assignedskillList; let result = skills.map((it ...

In my Vue project, I am required to extract only the numerical value from a select option text and disregard the rest of the text

Currently, I am in the process of learning Vue and have taken on the task of creating a basic tax calculator. The challenge is to display the result in real-time without requiring a "show total value" button. Everything seems to be functioning well except ...

Locate and substitute `?php` and `?` in a given string

I am facing a challenge with inserting a large string of valid HTML code into the DOM, as the string also includes PHP code. When Chrome renders the code, it automatically comments out the PHP sections. The PHP code is encapsulated in <?php ... ?>, s ...

JavaScript Promise Chains- Issues with Functionality?

Could someone provide an explanation for why calling secondMethod in the Promise chain yields results, while calling secondMethod() does not? function firstFunction() { return new Promise(function(resolve, reject){ setTimeout(function() { ...

How to update the state in react-native using asynchronous functions and the async/

As I attempt to instantly update a boolean state variable in react native, I am encountering issues with the await keyword not working. Due to the asynchronous nature of state setter functions, I am unsure how to proceed using async / await. The use of a ...

Leverage variable references in custom themes with React and Material-UI

In Material-UI (React), is it possible to reference a variable defined within a custom theme in the same theme file? For instance, can we set the background color of the MuiBottomNavigation component to the primary color (main) specified in the theme? im ...

What is the best way to select and link a specific section of a string using Javascript?

I have a JavaScript string that looks like the following: const pageContent = "He stood up and asked the teacher, "Can you elaborate the last point please?"; My goal is to map out the words in the string and display them in a way that makes ...

Trigger JavaScript function once all Ajax requests have completed

Seeking assistance with troubleshooting JavaScript code that is not functioning as expected. The Application sends file names to the server via Ajax calls for processing, but I need to update the database once all imports are complete. The problem arises ...

The React component is failing to display updated data from the Redux store

I've been working with React and Redux, trying to update my counter value in the React view. I can successfully log the latest state of my Redux store, but the changes are not reflecting in my React view. const counter = (state = 0, action) => { ...

The constructor error in ng-serve signalizes an issue in

Currently, I am developing an AngularJS application. However, when attempting to start the dev server, I encountered an issue with my ng serve command: https://i.stack.imgur.com/QujSe.png ...