Set border for Tab indicator in Material UI - css

I made a simple NavBar and I overwrote the tab indicator in the following way:
indicator: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
},
<Tabs classes={{indicator: classes.indicator}} onChange={handleClickTab} value={value}>
{...}
</Tabs>
My main problem is, that I want the indicator to be a square like a border ( instead of an underline ) where I can set paddings and other related things. How can I achieve this?

firstly, i know theres a correct answer on the top but if you want another way this is another way to dot... this is not a good approach but this is what i did:
css:
//And This is for the color of the text ↓
.MuiTab-textColorPrimary.Mui-selected {
color: var(--darkGreen) !important;
}
//this is for changing the span or bottom border ↓
.PrivateTabIndicator-colorPrimary-4 {
background-color: var(--darkGreen) !important;
}
All i did was get their classnames and override/overwrite them by using the !important method on css
If it did helped you, which it did to me... Then Im Glad I helped! :)
Cheers!

In Material-UI, TabIndicator is a span, not border-bottom of some elements, so you need to remove it completely and add your own border, which removes the transition effect when switching between tabs. Also you want your border color to be gradient, so that requires a bit of work.
const useStyles = makeStyles({
indicator: {
background: "none" // remove MUI indicator
},
tabs: {
"& button": {
padding: 5 // the size of the border
},
"& button[aria-selected='true']": {
position: "relative",
"&:before": {
content: '""',
position: "absolute",
left: 0,
top: 0,
right: 0,
bottom: 0,
background: "linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)", // border color
zIndex: 0
},
"& > *": { zIndex: 0 },
"& > .MuiTab-wrapper": {
background: "#fff",
height: "100%"
}
}
}
});
However, if you only want a single color for your border it becomes much easier to implement:
const useStyles = makeStyles({
indicator: {
background: "none"
},
tabs: {
"& button[aria-selected='true']": {
border: "3px solid red"
}
}
});
Usage
const classes = useStyles();
return (
<Tabs
className={classes.tabs}
classes={{ indicator: classes.indicator }}
{...props}
>
<Tab label="Item One" />
<Tab label="Item Two" />
<Tab label="Item Three" />
</Tabs>
);
Live Demo

You can use this class directly on your CSS and modify the Tab Border by default
.css-1aquho2-MuiTabs-indicator {
background-color: white!important;
}
Hope it helps

Related

MaterialUI withStyles, trying drilling down to a disabled switches css override

I'm developing with react and MaterialUI on the front end and I have a bunch of customized inputs. Everything is working pretty well except for this one. No matter what combination of selectors I use I can't seem to point to the right one to change this black color.
Also, it'd be nice to have a clear way to identify just by looking at the element selector, to drill down into the right component. Is there anyway to do this (teach a man to fish kind of thing).Here is the image of the element when I inspect it and the color I'm trying to get at.
here is the style object:
toggleToUse = {
switchBase: {},
thumb: {
color: colorUsedByInputs,
opacity: 0.6,
marginLeft: '10.2px'
},
track: {
background: 'grey',
opacity: '1 !important',
borderRadius: 20,
position: 'relative',
'&:before, &:after': {
display: 'inline-block',
position: 'absolute',
top: '50%',
width: '50%',
transform: 'translateY(-50%)',
color: '#fff',
textAlign: 'center'
}
},
checked: {
'&$switchBase': {
color: '#185a9d',
transform: 'translateX(32px)',
'&:hover': {
backgroundColor: 'rgba(24,90,257,0.08)'
}
},
'& $thumb': {
backgroundColor: '#fff'
},
'& + $track': {
background: 'linear-gradient(to right, rgba(43, 56, 97, 0.7), #2b3861)',
'&:before': {
opacity: 1
},
'&:after': {
opacity: 0
}
}
}
};
Here is the image of the element when I inspect it and the color I'm trying to get at.
<Switch classes={{ track: classes.track }} />
track: {
'.Mui-disabled + &&': {
backgroundColor: 'hotpink',
},
},
This will work for a default MUI Switch. If needed, you can increase the specificity by adding additional & to the selector. If all fails, please provide a codesandbox and precisely state what color you want in which scenario.

Change background-color of an unchecked Material-UI checkbox

I am working with React-Redux and Material-UI for styling. I have a < Checkbox /> that is on a toolbar. The toolbar's background-color is blue (#295ED9).
I've managed to change the color of the checkbox, when it is checked. I have also changed the color of the outline of the checkbox to white, when it is unchecked.
Problem: I cannot change the background-color / fill-color of the checkbox when it is unchecked. It is always the same color as the toolbar it is on (blue - #295ED9).
I have tried changing the background-color, color, and fill attributes of the < svg > and the < path > to white.
The best result I can get is when I change the < svg > fill attribute to white. Unfortunately, this does not make the checkbox fill with a white background when unchecked.
JSX
<div className="hasBalance">
<FormControlLabel
control={<Checkbox color="primary"/>}
label="Has Balance"
/>
</div>
SCSS
.hasBalance {
grid-area: balance;
.MuiSvgIcon-root {
fill: white;
}
}
Elements in Chrome Inspect Tool
<div class="hasBalance">
<label class="MuiFormControlLabel-root">
<span class="MuiButtonBase-root MuiIconButton-root PrivateSwitchBase-root-143 MuiCheckbox-root MuiCheckbox-colorPrimary MuiIconButton-colorPrimary" aria-disabled="false">
<span class="MuiIconButton-label">
<input class="PrivateSwitchBase-input-146" type="checkbox" data-indeterminate="false" value="">
<svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true" role="presentation">
<path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path>
</svg>
</span>
<span class="MuiTouchRipple-root"></span>
</span>
<span class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1">Has Balance</span>
</label>
</div>
The goal is to change the background-color / fill-color of the unchecked Material-UI checkbox to white. Thank you.
Below is an approach that seems to work. This uses the ":after" pseudo-element to place a white background behind the SVG.
import React from "react";
import ReactDOM from "react-dom";
import { withStyles } from "#material-ui/core/styles";
import Checkbox from "#material-ui/core/Checkbox";
const WhiteBackgroundCheckbox = withStyles(theme => ({
root: {
color: "red",
"& .MuiIconButton-label": {
position: "relative",
zIndex: 0
},
"&:not($checked) .MuiIconButton-label:after": {
content: '""',
left: 4,
top: 4,
height: 15,
width: 15,
position: "absolute",
backgroundColor: "white",
zIndex: -1
}
},
checked: {}
}))(Checkbox);
function App() {
return (
<div style={{ backgroundColor: "blue" }}>
<WhiteBackgroundCheckbox />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Related question: Change the tick color in MuiCheckbox material UI
MUIv5
Accepted answer doesn't work in MUIv5. MuiIconButton-label doesn't exist in Checkbox anymore and it changed the structure of the component.
For anyone struggling with v5, here's my kinda-hacky solution :
import { Components } from '#mui/material'
const MuiCheckbox: Components['MuiCheckbox'] = {
styleOverrides: {
root: {
'& .MuiSvgIcon-root': {
zIndex: 1,
},
'& .PrivateSwitchBase-input': {
width: 'auto',
height: 'auto',
top: 'auto',
left: 'auto',
opacity: '1',
visibility: 'hidden', // optional
'&::before': {
content: '""',
position: 'absolute',
background: 'white',
height: "100%",
width: "100%",
visibility: "visible" // optional
},
}
},
},
}
It relies on the fact that the <input> element assumes just the right dimensions and position if we reset its size and positioning attributes. That way the solution is resistant to various paddings and size props applied to the root element of the component. AFAIK it shouldn't break anything, but my experience with MUI is not that long.
Note that I have this solution defined as a global styleOverride in my theme's config and I want this custom background to affect checked tick too - mix and match with Ryan's answer for your scenario.
Visibility attributes are optional, they just make sure the input element stays hidden (I set opacity 1 on it, default is 0). Just make sure you remove both if you don't want them.

Set TextField height material-ui

index.js
import React from 'react'
import TextField from '#material-ui/core/TextField'
import style from './style'
import withStyles from 'hoc/withStyles'
import { connect } from 'react-redux'
class SearchField extends React.Component {
constructor (props) {
super(props)
this.onChange = this.onChange.bind(this)
}
onChange (event) {
const { dispatcher } = this.props
this.props.dispatch(dispatcher(event.target.value))
event.preventDefault()
}
render () {
const { classes, placeholder } = this.props
return (
<TextField
label={placeholder}
placeholder={placeholder}
InputProps={{ classes: { input: classes.resize } }}
className={classes.textField}
margin="normal"
autoFocus={true}
variant="outlined"
onChange={this.onChange}
/>
)
}
}
export default withStyles(style)(connect()(SearchField))
style.js
export default function () {
return {
container: {
display: 'flex',
flexWrap: 'wrap'
},
textField: {
width: 'auto'
},
resize: {
fontSize: 11
}
}
}
https://material-ui.com/api/text-field/
How can I change TextField height? I can't find it in the documentation. When I try to change it directly in CSS it works incorrectly (it looks like this - selected height on the screen 26px).
What should I do?
You can try out adding the size="small" which is mentioned in the Textfield API
<TextField variant="outlined" size="small" / >
The other answer is useful but didn't work for me because if a label is used in an outlined component (as it is in the question) it leaves the label uncentered. If this is your usecase, read on.
The way the <label> component is styled is somewhat idiosyncratic, using position: absolute and transform. I believe it's done this way to make the animation work when you focus the field.
The following worked for me, with the latest material-ui v4 (it should work fine with v3 too).
// height of the TextField
const height = 44
// magic number which must be set appropriately for height
const labelOffset = -6
// get this from your form library, for instance in
// react-final-form it's fieldProps.meta.active
// or provide it yourself - see notes below
const focused = ???
---
<TextField
label="Example"
variant="outlined"
/* styles the wrapper */
style={{ height }}
/* styles the label component */
InputLabelProps={{
style: {
height,
...(!focused && { top: `${labelOffset}px` }),
},
}}
/* styles the input component */
inputProps={{
style: {
height,
padding: '0 14px',
},
}}
/>
Notes
I just used inline styles rather than the withStyles HOC, as this approach just seems simpler to me
The focused variable is required for this solution - you get this with final-form, formik and probably other form libraries. If you're just using a raw TextField, or another form library that doesn't support this, you'll have to hook this up yourself.
The solution relies on a magic number labelOffset to center the label which is coupled to the static height you choose. If you want to edit height, you'll also have to edit labelOffset appropriately.
This solution does not support changing the label font size. You can change the input font size, only if you're fine with there being a mismatch between that and the label. The issue is that the size of the 'notch' that houses the label in the outlined border is calculated in javascript according to a magic number ratio that only works when the label font size is the default. If you set the label font size smaller, the notch will also be too small when the label shows in the border. There's no easy way to override this, short of repeating the entire calculation yourself and setting the width of the notch (the component is fieldset > legend) yourself via CSS. For me this wasn't worth it, as I'm fine with using the default font sizes with a height of 44px.
The component takes a multiline prop which is a boolean. Set this to true, and then set the component's rows prop to a number.
<TextField
multiline={true}
rows={3}
name="Description"
label="Description"
placeholder="Description"
autoComplete="off"
variant="outlined"
value={description}
onChange={e => setDescription(e.target.value)}
/>
You didn't show how you tried to specify the height, but the approach you used for font-size is the right approach.
Here's an example showing two text fields with different heights:
import React from "react";
import ReactDOM from "react-dom";
import TextField from "#material-ui/core/TextField";
import { withStyles } from "#material-ui/core/styles";
const styles = {
input1: {
height: 50
},
input2: {
height: 200,
fontSize: "3em"
}
};
function App(props) {
return (
<div className="App">
<TextField
variant="outlined"
InputProps={{ classes: { input: props.classes.input1 } }}
/>
<TextField
variant="outlined"
InputProps={{ classes: { input: props.classes.input2 } }}
/>
</div>
);
}
const StyledApp = withStyles(styles)(App);
const rootElement = document.getElementById("root");
ReactDOM.render(<StyledApp />, rootElement);
And here is a code sandbox with the same code so you can see it running.
First of all, my heart goes out to any poor soul in this thread who has found themselves fighting against the awkward design of the MUI components. Second, if you're using themes AND the "filled" variant of TextField, this solution might work for you. Using the Chrome Dev Tools, I found success adjusting the height of the divs with the classes "MuiFormControl-root" and "MuiInputBase-root". This is what my code looks like (results may vary):
const theme = createMuiTheme({
overrides: {
MuiFormControl: {
root: {
height: '56px',
},
},
MuiInputBase: {
root: {
height: '56px',
},
},
},
})
<TextField
id="outlined-multiline-static"
label="Multiline"
multiline
fullWidth
defaultValue="Default Value"
inputProps={{
style: {
height: "600px",
},
}}
/>
To make it narrower, set a height, and add a "dense" margin prop on the TextField to keep the label aligned correctly:
<TextField margin="dense" style={{ height: 38 }} />
With material-ui v4+, you have to adjust the input padding and the label position to get what you whant.
<TextField label="Label" variant="outlined" />
Suppose we want the above TextField to be 48px height (it's default size is 56px), we just have to do (56px - 48px) / 2 = 4px and in our css file:
.MuiTextField-root input {
/* 14.5px = 18.5px - 4px (note: 18.5px is the input's default padding top and bottom) */
padding-top: 14.5px;
padding-bottom: 14.5px;
}
.MuiTextField-root label {
top: -4px;
}
.MuiTextField-root label[data-shrink='true'] {
top: 0;
}
For styled-components users, all the above block of code can be defined as Sass mixins that can be re-used throughout the code base
import { css } from 'styled-components'
const muiTextFieldHeight = (height: number) => {
const offset = (56 - height) / 2
return css`
input {
padding-top: calc(18.5px - ${offset}px);
padding-bottom: calc(18.5px - ${offset}px);
}
label {
top: -${offset}px;
}
label[data-shrink='true'] {
top: 0;
}
`
}
Then somewhere in your stylesheet
.MuiTextField-root {
${muiTextFieldHeight(40)} /* set TextField height to 40px */
}
This works with material-ui v3,
<div className="container">
<TextField
label="Full name"
margin="dense"
variant="outlined"
autoFocus
/>
</div>
.css
.container input {
height: 36px;
padding: 0px 14px;
}
.container label {
height: 36px;
top: -6px;
}
.container label[data-shrink="true"] {
top: 0;
}
https://codesandbox.io/s/elated-kilby-9s3ge
With React and "#mui/material": "^5.2.2",
import * as React from 'react';
import TextField from '#mui/material/TextField';
export default function BasicTextFields() {
return (
<TextField
label="Outlined"
variant="outlined"
InputLabelProps={{
style: {
fontSize: 14,
backgroundColor: '#FFF',
paddingLeft: 4,
paddingRight: 4,
color: '#383838',
},
}}
inputProps={{
style: {
fontSize: 14,
height: 40,
width: 272,
padding: '0 14px',
fontWeight: 'bold'
},
}}
/>
);
}
CSS
.MuiTextField-root{
border: 1px solid $BORDER_COLOR_2;
border-radius: 6px;
height: 40px;
box-shadow: 0px 2px 3px $BOX_SHADOW_1;
color: $TEXT_COLOR_3;
font-size: 14px;
font-weight: bold;
}
.MuiTextField-root label {
top: -6px;
}
.MuiTextField-root label[data-shrink='true'] {
top: 0;
}
Changing the height is simple, can be achieved using
InputProps={{style: { fontSize: '1.8rem', height: 70 },
But that isn't enough, because the label(placeholder in this case) will not be centered.
Label can be centered using:
sx={{'.MuiFormLabel-root[data-shrink=false]': { top: <put desired value here>} }}

Change default border color of outline textfield

I want to change the default border color of an outlined textfield from gray to a darker blue.
<TextField
variant={"outlined"}
placeholder={t('landing_page.code.placeholder')}
onChange={this.onCodeChanged}
value={code}
fullWidth={true}
className={classes.codeInput}
error={code ? code.length < 10 : false}
/>
This is the codeInputclass:
codeInput: {
marginTop: theme.spacing.unit,
},
I have tried overriding the color via theme, but it does not work:
overrides: {
MuiOutlinedInput: {
root: {
borderColor: "#2b303e"
},
notchedOutline: {
borderRadius: "0",
borderWidth: "2px",
borderColor: "#2b303e"
},
},
}
It is still gray as you can see in the image.
I have identified the following css rules as the problem. With disabling this, everything looks fine. I just don't know how to do this
.MuiOutlinedInput-root-148 .MuiOutlinedInput-notchedOutline-155 {
border-color: rgba(0, 0, 0, 0.23);
}
Create a new css class for example:
// app.css
.blueBorder {
}
Add in the border you want and add !important; to overwrite.
// app.css
.blueBorder{
border-radius: 0px!important;
border: 2px solid #2b303e!important;
}
Assign it to your component:
// js / react component
<TextField
variant={"outlined"}
placeholder={t('landing_page.code.placeholder')}
onChange={this.onCodeChanged}
value={code}
fullWidth={true}
className={`blueBorder ${classes.codeInput}`}
/>
Update to show error class
// app.css
.blueBorder{
border-radius: 0px!important;
border: 2px solid #2b303e!important;
}
// Red border to denote error
.blueBorder-error {
border-radius: 0px!important;
border: 2px solid red!important;
}
Use the error class in the components className
condition ? true : false
// js / component
<TextField
variant={"outlined"}
placeholder={t('landing_page.code.placeholder')}
onChange={this.onCodeChanged}
value={code}
fullWidth={true}
className={code.length < 10 ? `blueBorder-error ${classes.codeInput}` : `blueBorder ${classes.codeInput}}
/>

Unable to modify some internal styles of Material UI's <Dialog> component

I'm trying to apply some reasonably simple styles to my <Dialog> component. In this case, I am trying to round the corners with a border radius. Here are some simple inline styles that I'd like to use to override the default <Dialog> styles:
let overrideStyles = {
padding: 0,
margin: 0,
borderRadiusTopLeft: '4px',
borderRadiusTopRight: '4px',
};
<Dialog> provides a wide variety of possibilities for overriding internal styles. These include bodyStyle, contentStyle, style, titleStyle, overlayStyle, and actionsContainerStyle. I decided to try to apply these styles to each one.
<Dialog
bodyStyle={overrideStyles}
contentStyle={overrideStyles}
style={overrideStyles}
titleStyle={overrideStyles}
overlayStyle={overrideStyles}
actionsContainerStyle={overrideStyles}
modal={overrideStyles}
>
<TestPanel/>
</Dialog>
When I render my TestPanel, it ends up looking like this:
Notice the corners, where my border radius has not been applied... I opened up the inspector and noticed the following div:
If I apply the border radius styling to the highlighted div, the dialog will have its corners rounded as expected. Which leads me to my question...
How do I override the styles of Material UI's <Dialog> component to apply rounded corners as my CSS is attempting?
I solved it with paperProps property.
<Dialog PaperProps={{
style: { borderRadius: 2 } }}
> .... </Dialog>
This perfeclty worked for me
You can override styles like below.
const styles = {
root: { }
paper: { borderRadius: 15 }
}
// ...
<Dialog classes={{
root: classes.root,
paper: classes.paper
}}>
</Dialog>
Unfortunately, Material UI isn't supremely style-friendly. In this case, there's no prop you can override to change the border-radius, so we've got to apply our own class:
let headerStyles = {
color: 'white',
textAlign: 'center',
fontSize: 24,
backgroundColor: '#3B8DBC',
padding: 20,
borderTopLeftRadius: 4,
borderTopRightRadius: 4
};
let bodyStyles = {
backgroundColor: 'white',
padding: 10,
height: 200
};
<Dialog className='test'>
<div style={headerStyles}>Testing</div>
<div style={bodyStyles}>5:43pm</div>
</Dialog>
Then style that class, and, yes, the border-radius has to be set on both of the below CSS classes as well as the TestPanel header:
/* Some rules use !important because Material UI sets them by default */
.test > div > div {
background-color: #3B8DBC; /* Same background-color as TestPanel */
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.test > div > div > div {
/* Not overriding the color and border radius here too result in your changes
not being visible. */
background-color: inherit !important;
border-top-left-radius: 4px !important;
border-top-right-radius: 4px !important;
}
.test > div > div > div > div {
/* This div is the topmost padding between the modal content and the edge
of the modal */
padding: 0 !important;
}
This ends up looking like what you want:
screenshot here
Hope this helps!
You can override <Dialog /> styles globally in your application when creating your theme object. The paper key of MuiDialog will let you target the border-radius.
const theme = createMuiTheme({
overrides: {
MuiDialog: {
paper: {
borderTopLeftRadius: '4px',
borderTopRightRadius: '4px'
}
}
}
})
Dialog - CSS api
Material UI Theming
The first answer is not working for me. I tried this and it work perfect for me:
sx={{
"& .MuiDialog-container": {
"& .MuiPaper-root": {
width: "100%",
maxWidth: "740px",
borderRadius: "8px"
}
},
}}

Resources