Cannot change selected style of Mui tab - javascript

I am trying to create a custom Tab using Mui's Tab.
The style I want is:
The indicator applied by default is made transparent.
Designate the default background color and font color of the tab.
When a tab is selected, only the background color and font color of the selected tab are changed.
Problem
As follows, 1 and 2 were applied, but the color of the selected tab could not be changed. I am changing the css directly using Mui's styled function, but I don't know where is wrong.
const StyledMuiTab = styled(MuiTab)({
...
'&.Mui-selected': {
backgroundColor: 'red',
color: 'red',
},
});
Also onChange doesn't work.
Source
Tab
import React, { ReactElement, useState } from 'react';
import { Tabs as MuiTabs, Tab as MuiTab, styled } from '#mui/material';
interface Props {
color: string;
children: ReactElement | ReactElement[];
}
const StyledMuiTabs = styled(MuiTabs)<Props>(({ color }) => ({
borderBottom: `1px solid ${color}`,
overflow: 'hidden',
display: 'flex',
'& .MuiTabs-indicator': {
backgroundColor: 'transparent',
},
'& .MuiTab-root.Mui-selected': { // not working
backgroundColor: 'red',
color: 'red',
},
}));
const BasicTabs = ({ children, color }: Props) => {
const [tabIndex, setTabIndex] = useState<number>(0);
const handleChange = (_event: React.SyntheticEvent, newValue: number) => {
console.log(newValue); //not working
setTabIndex(newValue);
};
return (
<StyledMuiTabs
value={tabIndex}
color={color}
variant="scrollable"
scrollButtons={false}
onChange={handleChange}
>
{children}
</StyledMuiTabs>
);
};
interface TabProps {
text: string;
}
const StyledMuiTab = styled(MuiTab)({
textTransform: 'none',
fontFamily: 'Noto Sans KR',
fontStyle: 'normal',
fontWeight: '500',
fontSize: '14px',
lineHeight: '20px',
textAlign: 'center',
background: '#F5F6FA',
border: '1px solid #D4DAE4',
borderRadius: '6px 6px 0px 0px',
color: '#9CA3AF',
'&.Mui-selected': { // not working
backgroundColor: 'red',
color: 'red',
},
});
const Tab = ({ text }: TabProps) => <StyledMuiTab disableRipple label={text} />;
const Tabs = Object.assign(BasicTabs, {
Tab,
});
export default Tabs;
caller
<Tabs color="#0D58EE">
<Tabs.Tab text="one" />
<Tabs.Tab text="two" />
</Tabs>

Related

Material UI's Stepper StepLabel Icon issue with undefined

just having issues with trying to implememnt a custom Step Label Icon within the nodes of the Stepper Component provided by Material UI. I am trying to implement an icon within each circle, as seen here from Material UI's demo
however, am coming across an error
Please see my code below. Thanks!
import React from 'react';
import { Typography } from '#material-ui/core';
import { withStyles, styles } from '#material-ui/core/styles';
const styles = theme => ({
checklistHeader: {
fontWeight: 'bold',
marginTop: '80px',
color: 'white'
},
connectorIcon: {
color: theme.palette.text.secondary
},
active: {
backgroundColor: 'green'
}
});
const steps = ['Select campaign settings', 'Select campaign settings', 'Select campaign settings'];
const ColorlibStepIconRoot = styled('div')(({ theme, ownerState }) => ({
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.grey[700] : '#ccc',
zIndex: 1,
color: '#fff',
width: 50,
height: 50,
display: 'flex',
borderRadius: '50%',
justifyContent: 'center',
alignItems: 'center',
...(ownerState.active && {
backgroundImage:
'linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)',
boxShadow: '0 4px 10px 0 rgba(0,0,0,.25)',
}),
...(ownerState.completed && {
backgroundImage:
'linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)',
}),
}));
const ColorlibStepIcon = ({
icon, active, completed, className
}) => {
const icons = {
1: <Icon style={{ color: 'red' }}>create_outline</Icon>,
2: <Icon style={{ color: 'red' }}>star</Icon>,
3: <Icon style={{ color: 'red' }}>people</Icon>,
};
return (
<ColorlibStepIconRoot ownerState={{ completed, active }} className={className}>
{icons[String(icon)]}
</ColorlibStepIconRoot>
);
};
const Stepper = ({ classes }) => {
return (
<React.Fragment>
<Typography variant="h6" align="center" gutterBottom className={classes.checklistHeader}>Please complete the following criterion</Typography>
<Stepper alternativeLabel activeStep={2} style={{ background: 'none' }}>
{steps.map(label => (
<Step key={label}>
<StepLabel StepIconComponent={ColorlibStepIcon}>{label}</StepLabel>
</Step>
))}
</Stepper>
</React.Fragment>
);
};
Stepper.defaultProps = {
};
Stepper.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles, { withTheme: true })(Stepper);
It seems like the styled component is undefined. Is there any way that I can bypass this
The styled() function is only available in v5. You either need to upgrade to MUI v5 using this installation guide or use the older API in v4, (The equivalent is withStyles):
V5
import { styled } from '#mui/material/styles';
const StyledComponent = styled(Component)({
// your styles
});
V4
import { withStyles, styles } from '#material-ui/core/styles';
const StyledComponent = withStyles({
// your styles
})(Component);
You can see the v4 docs here and the v5 docs here.

Change disabled Material UI checkbox color or background color

The disabled unchecked checkbox look a bit too subtle and I would like to have them have a grey background and for the cursor to be of type not-allowed.
Unfortunately I cannot figure out how to apply these styles on the checkbox using the makeStyles. This is what my current code looks like:
const useStyles = makeStyles((theme) => ({
disabledCheckbox: {
cursor: 'not-allowed',
color: 'grey',
backgroundColor: 'grey',
},
}));
// ...
const App = () => {
const classes = useStyles();
return (
<div>
Disabled:
<Checkbox
disabled={true}
name="Disabled checkbox"
classes={{ disabled: classes.disabledCheckbox }}
/>
</div>
);
};
Unfortunately this does nothing, and the disabled checkbox looks the same. Here is a demo app to compare a disabled and enabled one.
What am I doing wrong? How can I change the background color of an unselected MUI disabled checkbox:
Using the disabled class by itself does not provide sufficient specificity to override the default styles in IconButton. Also, you don't want to override the background-color for the entire checkbox or it will fill in the entire area that gets the hover effect for the checkbox; instead you just want to target the icon within the checkbox (and even that is slightly more than ideal -- more about that later).
Below is a way of defining the styles with enough specificity to target just the icon. Overriding the cursor requires some additional work because by default Material-UI disables pointer events on disabled buttons (Checkbox leverages SwitchBase which uses IconButton which uses ButtonBase) and the cursor CSS has no effect when pointer events are disabled. The CSS below turns pointer events back on, but then it is necessary to turn off the hover effect which was previously prevented via pointerEvents: 'none'.
const useStyles = makeStyles((theme) => ({
backgroundColorOnWholeIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root': {
backgroundColor: '#eee',
},
},
},
}));
Unfortunately, this still doesn't produce quite what you likely want. The box of the checkbox icon does not extend to the edge of the 24px-by-24px box that the icon resides in, so when you set a background color it bleeds out of the box:
In order to fill the inner box of the checkbox without changing the color of the couple pixels outside that box, you need to create a custom icon.
The code below creates a custom icon that is identical to the default unchecked icon except that it adds a second path duplicating the inner box of the checkbox without any fill so that it can be targeted via CSS.
import React from 'react';
import createSvgIcon from '#material-ui/icons/utils/createSvgIcon';
export default createSvgIcon(
<>
<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 fill="none" class="innerBox" d="M19 5v14H5V5h14" />
</>,
'CustomUnchecked'
);
Then you can target this inner box as follows:
const useStyles = makeStyles((theme) => ({
backgroundColorOnInnerBoxOfCustomIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root .innerBox': {
fill: '#eee',
},
},
}
}));
In order for this to work, you need to specify the custom icon on the checkbox. It is also possible to do all of this via the theme if you want all of your disabled checkboxes to look like this.
Below is a working example demonstrating doing this via both makeStyles and via the theme.
import { Checkbox } from '#material-ui/core';
import {
makeStyles,
createMuiTheme,
ThemeProvider,
} from '#material-ui/core/styles';
import CustomUncheckedIcon from './CustomUnchecked';
import React from 'react';
const useStyles = makeStyles((theme) => ({
backgroundColorOnInnerBoxOfCustomIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root .innerBox': {
fill: '#eee',
},
},
},
backgroundColorOnWholeIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root': {
backgroundColor: '#eee',
},
},
},
}));
const defaultTheme = createMuiTheme();
const theme = createMuiTheme({
props: {
MuiCheckbox: {
icon: <CustomUncheckedIcon />,
},
},
overrides: {
MuiCheckbox: {
root: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
// This syntax is necessary (instead of just ".MuiSvgIcon-root") because of the nested theme causing the global class names to be suffixed)
'& [class*=MuiSvgIcon-root] .innerBox': {
fill: '#eee',
},
},
},
},
},
});
const App = () => {
const classes = useStyles();
return (
<ThemeProvider theme={defaultTheme}>
<div style={{ marginBottom: '16px' }}>
Styled via makeStyles
<br />
Disabled without custom icon:
<Checkbox
className={classes.backgroundColorOnWholeIcon}
disabled={true}
name="Disabled checkbox"
/>
<br />
Disabled:
<Checkbox
className={classes.backgroundColorOnInnerBoxOfCustomIcon}
disabled={true}
icon={<CustomUncheckedIcon />}
name="Disabled checkbox"
/>
Enabled:
<Checkbox
icon={<CustomUncheckedIcon />}
className={classes.backgroundColorOnInnerBoxOfCustomIcon}
name="Enabled checkbox"
/>
</div>
<ThemeProvider theme={theme}>
<div>
Styled via theme
<br />
Disabled:
<Checkbox disabled={true} name="Disabled checkbox" />
Enabled:
<Checkbox name="Enabled checkbox" />
</div>
</ThemeProvider>
</ThemeProvider>
);
};
export default App;
There is option to pass checked icon and unchecked Icon , by style you need to select Icon first then you can use 'input:disabled ~ &': to change style of disabled checkbox , You can use styling like below
const useStyles = makeStyles({
root: {
'&:hover': {
backgroundColor: 'transparent',
},
},
icon: {
borderRadius: 3,
width: 16,
height: 16,
boxShadow: 'inset 0 0 0 1px rgba(16,22,26,.2), inset 0 -1px 0 rgba(16,22,26,.1)',
backgroundColor: '#f5f8fa',
backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.8),hsla(0,0%,100%,0))',
'$root.Mui-focusVisible &': {
outline: '2px auto rgba(19,124,189,.6)',
outlineOffset: 2,
},
'input:hover ~ &': {
backgroundColor: '#ebf1f5',
},
'input:disabled ~ &': {
boxShadow: 'black',
background: 'rgba(0,0,0,0.5)',
},
},
checkedIcon: {
backgroundColor: '#137cbd',
backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))',
'&:before': {
display: 'block',
width: 16,
height: 16,
backgroundImage:
"url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" +
" fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " +
"1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")",
content: '""',
},
'input:hover ~ &': {
backgroundColor: '#106ba3',
},
},
});
Refer to sandbox below

overwriting react-native stylesheets styles

I have a custom react component that looks like this:
import { StyleSheet } from 'react-native';
import { Input, Item } from 'native-base';
import Icon from 'react-native-vector-icons/FontAwesome';
import { moderateScale, verticalScale } from 'react-native-size-matters';
import { styles as commonStyles } from '~/styles/RegistrationStyles';
type FieldInputProps = {
handleChange: (e: string) => undefined;
handleBlur: (e: string) => undefined;
value: string;
fieldType: string;
placeholderText?: string;
hidePasswordIcon?: string;
hidePassword?: boolean;
togglePassword?: () => void;
icon: string;
};
export const FieldInput: React.FunctionComponent<FieldInputProps> = ({
handleChange,
handleBlur,
fieldType,
placeholderText,
value,
hidePassword,
hidePasswordIcon,
togglePassword,
icon,
}) => {
return (
<Item rounded style={styles.personalListItem}>
<Icon name={icon} size={moderateScale(20)} color="green" />
<Input
autoFocus={true}
autoCapitalize="none"
style={{ fontSize: moderateScale(15) }}
placeholder={placeholderText}
keyboardType="default"
onChangeText={handleChange(fieldType)}
onBlur={handleBlur(fieldType)}
value={value}
secureTextEntry={hidePassword}
/>
{togglePassword ? (
<Icon
name={hidePasswordIcon}
onPress={togglePassword}
style={commonStyles.iconStyle}
size={moderateScale(20)}
color="green"
/>
) : null}
</Item>
);
};
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor: '#2E3331',
flex: 1,
},
personalListItem: {
width: moderateScale(320),
backgroundColor: 'white',
borderBottomColor: 'grey',
borderRadius: moderateScale(10),
height: verticalScale(50),
paddingRight: moderateScale(20),
paddingLeft: moderateScale(10),
marginVertical: moderateScale(20),
},
text: {
fontFamily: 'Roboto',
fontSize: moderateScale(20),
fontWeight: '600',
marginVertical: moderateScale(10),
color: '#17D041',
},
subtext: {
color: '#17D041',
fontSize: moderateScale(14),
},
subtextBold: {
textDecorationLine: 'underline',
color: '#17D041',
fontWeight: '600',
fontSize: moderateScale(14),
},
button: {
height: moderateScale(50),
width: moderateScale(350),
borderRadius: moderateScale(10),
justifyContent: 'center',
marginBottom: moderateScale(5),
},
buttonText: {
fontSize: moderateScale(15),
},
});
Usually when I use this component, I want to keep using this style. However, in one particular case, I want to overwrite the styles. For example, change the width or the background color of the input field etc. However, if I try to overwrite the styles, there are no changes.
<FieldInput style={styles.fieldInput}
handleChange={handleChange}
handleBlur={handleBlur}
value={values.phoneNumber}
fieldType="phoneNumber"
icon="phone"
placeholderText="49152901820"
/>
fieldInput: {
width: moderateScale(320),
backgroundColor: 'red',
},
You're not using style prop in your component. Please fix it as shown below.
export const FieldInput: React.FunctionComponent<FieldInputProps> = ({
handleChange,
handleBlur,
fieldType,
placeholderText,
value,
hidePassword,
hidePasswordIcon,
togglePassword,
icon,
style,
rounded,
}) => {
return (
<Item rounded={rounded} style={[styles.personalListItem, style]}>
/* remaining code code */
</Item>
);
};
Here you are passing the styles as a parameter, lets say you want to use it for the outer wrap, you can do it like below
<Item rounded style={[styles.personalListItem,this.props.style]}>
If a style prop is received then it will overwrite the one in personalListItem, else it will use the styles in personalListItem.
You will have to add the style to the props, also you can add separate style props for inner components and use them the same way.
If you want to have only the style that is passed you can do this
<Item rounded style={this.props.style||styles.personalListItem}>
Which will use the personalListItem if a style prop is not passed

Unable to change border color when focused and not focused of Material UI Input

I'm not sure why I can't get this to work. I'm selecting the MuiInputBase-root element, telling it to select the field and set the border color to blue, and on focus set the border color to red. What am I doing wrong here?
Codesandbox
import React from "react";
import "./styles.css";
import { makeStyles } from "#material-ui/core/styles";
import FormControl from "#material-ui/core/FormControl";
import OutlinedInput from "#material-ui/core/OutlinedInput";
import InputLabel from "#material-ui/core/InputLabel";
const useStyles = makeStyles(theme => ({
root: {
width: "20rem"
},
label: {
background: "white",
paddingRight: theme.spacing(0.5),
"&.Mui-focused": {
color: theme.palette.secondary.main
}
},
closeIcon: {
color: theme.palette.grey[400],
"&.hidden": {
display: "none"
}
},
searchIcon: {
color: theme.palette.primary.main
}
}));
const useOutlinedInputStyles = makeStyles({
root: {
"& .MuiInputBase-root": {
"& fieldset": {
borderColor: "blue"
},
"&.Mui-focused fieldset": {
borderColor: "red"
}
}
}
});
export default function App() {
const classes = useStyles();
const outlinedInputStyles = useOutlinedInputStyles();
return (
<div className="App">
<FormControl className={classes.root} variant="outlined">
<InputLabel className={classes.label} htmlFor="search-input">
placeholder
</InputLabel>
<OutlinedInput
classes={outlinedInputStyles}
id="search-input"
labelWidth={70}
/>
</FormControl>
</div>
);
}
The issue is that the .MuiInputBase-root is not a child of the root element (the .MuiOutlinedInput-root element), it's actually exactly the same element, so that layer is unnecessary. Also, type selectors (e.g. fieldset) have lower specificity than class selectors, so &.Mui-focused fieldset does not have sufficient specificity to override the default focused styles. Instead of fieldset you can use the class selector .MuiOutlinedInput-notchedOutline.
So instead of:
root: {
"& .MuiInputBase-root": {
"& fieldset": {
borderColor: "blue"
},
"&.Mui-focused fieldset": {
borderColor: "red"
}
}
}
You should have:
root: {
"& .MuiOutlinedInput-notchedOutline": {
borderColor: "blue"
},
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
borderColor: "red"
}
}
Related answer: Change border color on Material-UI TextField

color change for the loading bar component of material ui

I am trying to learn material ui.
I am trying to change the css of the loading bar.
I referred to the documentation and used colorPrimary classes
but its not changing.
can you tell me how to fix it so taht in future I will fix it myself
providing my code snippet below.
all my code is in ReceipeReviewCardList.js
https://codesandbox.io/s/2zonj08v5r
const styles = {
root: {
flexGrow: 1
},
colorPrimary: {
color: "green"
}
};
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<LinearProgress
className={classes.colorPrimary}
variant="determinate"
value={this.state.completed}
you can use example as was in the reply of the issue in material ui github project: https://github.com/mui-org/material-ui/issues/12858#issuecomment-421150158
import React, { Component } from 'react';
import { withStyles } from '#material-ui/core/styles';
import { LinearProgress } from '#material-ui/core';
class ColoredLinearProgress extends Component {
render() {
const { classes } = this.props;
return <LinearProgress {...this.props} classes={{colorPrimary: classes.colorPrimary, barColorPrimary: classes.barColorPrimary}}/>;
}
}
const styles = props => ({
colorPrimary: {
backgroundColor: '#00695C',
},
barColorPrimary: {
backgroundColor: '#B2DFDB',
}
});
export default withStyles(styles)(ColoredLinearProgress);
It works perfect.
You can override the background colors with makeStyles.
On makeStyles file:
export const useStyles = makeStyles(() => ({
root: {
"& .MuiLinearProgress-colorPrimary": {
backgroundColor: "red",
},
"& .MuiLinearProgress-barColorPrimary": {
backgroundColor: "green",
},
},
})
Import and use:
import { useStyles } from "./myFile.style";
...
const classes = useStyles();
...
<div className={classes.root}>
<LinearProgress />
</div>
It is because you set the CSS is not correctly,
const styles = {
root: {
flexGrow: 1
},
colorPrimary: {
background: 'green'
}
};
not:
const styles = {
root: {
flexGrow: 1
},
colorPrimary: {
color: "green",
}
};
Hope it help!
If you want to overwrite with sx:
sx={{
'& .MuiLinearProgress-bar1Determinate': {
backgroundColor: 'red',
}
}}
the color of the main bar is set as the BACKGROUNDCOLOR, NOT the COLOR
For Material UI v5 (#mui)
<LinearProgress sx={{
backgroundColor: 'white',
'& .MuiLinearProgress-bar': {
backgroundColor: 'green'
}
}}
variant="determinate"
value={10}/>
I did do it by this way, creating your own theme
import {createMuiTheme, MuiThemeProvider } from '#material-ui/core/styles';
const theme = createMuiTheme({
palette: {
secondary: {
main: '#42baf5'
}
}
})
<MuiThemeProvider theme={theme}>
<LinearProgress color="secondary"/>
</MuiThemeProvider>
An easy workaround i stumbled upon which doesn't seem too much of a hack:
<LinearProgress
className="VolumeBar"
variant="determinate"
value={volume}
/>
.VolumeBar > * { background-color:green; }
.VolumeBar{background-color:gray ;}
The first rule makes the progress appear green(completed part).
The second rule takes care of the uncompleted part .
const BorderLinearProgress = withStyles((theme: Theme) =>
createStyles({
root: {
width: '95%',
height: 10,
borderRadius: 5,
marginTop: 8,
marginBottom: 20
},
colorPrimary: {
backgroundColor: Liquidity.colors.main.pink,
},
bar: {
borderRadius: 5,
backgroundColor: Liquidity.colors.main.yellow,
},
}),
)(LinearProgress);
This worked for me (Material ui version 4):
progressbar: {
background: 'yellow',
'& .MuiLinearProgress-bar': {
backgroundColor: theme.palette.success.main,
},
},
And then
<LinearProgress
className={classes.progressbar}
variant="determinate"
value={30}
/>
That have worked for me !
First set a className to the LinearProgress component
<LinearProgress
className="custom-class"
variant="determinate"
value={MyValue}
/>
then style it from your attached css file as shown in the following :
.custom-class > * { background-color:green !important; }
.custom-class{background-color:gray !important;}
using the !important tag is premordial to override the original color.
style: progress: { color: 'red' },
Component:
<LinearProgress color="inherit" className={classes.progress} />

Categories

Resources