Quick note: this is not a duplicate of How to change outline color of Material UI React input component?
With material-ui (React) I am unable to delete the outline on hover or focus. The reason I am using this input is to request add a little red border when a warning occurs. I can change the focused and hover styles. This is tested in the following image:
Where this CSS is applied when the input is focused:
outlinedInputFocused: {
borderStyle: 'none',
borderColor: 'red',
outlineWidth: 0,
outline: 'none',
backgroundColor: 'green'
},
Component
<OutlinedInput
disableUnderline={true}
notched={true}
id="adornment-weight"
classes={{root: classes.outlinedInput, focused: classes.outlinedInputFocused}}
value={this.state.budgetValue}
onChange={evt => this.updateBudgetValue(evt)}
onKeyPress={evt => this.handleKeyPress(evt)}
endAdornment={<InputAdornment sposition="end">BTC</InputAdornment>}
/>
As you can see the color of the image is green, but there is still an outline. Even though the outlineWidth is 0 and outline is set to none in the CSS. How can I change / disable this outline?
The key to understanding how to override these styles is to look at how they are defined in the Material-UI source code. The question you referenced also shows some of the syntax needed.
Below is an abbreviated version (I left out the styles that are not related to the outline) of the styles from OutlinedInput.js:
export const styles = theme => {
const borderColor =
theme.palette.type === 'light' ? 'rgba(0, 0, 0, 0.23)' : 'rgba(255, 255, 255, 0.23)';
return {
/* Styles applied to the root element. */
root: {
position: 'relative',
'& $notchedOutline': {
borderColor,
},
'&:hover:not($disabled):not($focused):not($error) $notchedOutline': {
borderColor: theme.palette.text.primary,
// Reset on touch devices, it doesn't add specificity
'#media (hover: none)': {
borderColor,
},
},
'&$focused $notchedOutline': {
borderColor: theme.palette.primary.main,
borderWidth: 2,
},
'&$error $notchedOutline': {
borderColor: theme.palette.error.main,
},
'&$disabled $notchedOutline': {
borderColor: theme.palette.action.disabled,
},
},
/* Styles applied to the root element if the component is focused. */
focused: {},
/* Styles applied to the root element if `disabled={true}`. */
disabled: {},
/* Styles applied to the root element if `error={true}`. */
error: {},
/* Styles applied to the `NotchedOutline` element. */
notchedOutline: {}
};
};
The "outline" of OutlinedInput is controlled via the border on the NotchedOutline component nested within it. In order to impact that nested element, you need to define a "notchedOutline" class (even if empty) that you can then use to target that element for the different states (e.g. focused, hover) of the parent.
Here's an example that fully removes the border:
import React from "react";
import ReactDOM from "react-dom";
import OutlinedInput from "#material-ui/core/OutlinedInput";
import InputAdornment from "#material-ui/core/InputAdornment";
import { withStyles } from "#material-ui/core/styles";
const styles = theme => ({
root: {
"& $notchedOutline": {
borderWidth: 0
},
"&:hover $notchedOutline": {
borderWidth: 0
},
"&$focused $notchedOutline": {
borderWidth: 0
}
},
focused: {},
notchedOutline: {}
});
function App(props) {
const { classes } = props;
return (
<div className="App">
<OutlinedInput
disableUnderline={true}
notched={true}
id="adornment-weight"
classes={classes}
value={1}
endAdornment={<InputAdornment sposition="end">BTC</InputAdornment>}
/>
</div>
);
}
const StyledApp = withStyles(styles)(App);
const rootElement = document.getElementById("root");
ReactDOM.render(<StyledApp />, rootElement);
You can use inline style like this:
<MyComponent style={{outline: 'none'}} />
2.4.7 Focus Visible: Any keyboard operable user interface has a mode of operation where the keyboard focus indicator is visible. (Level AA)
https://www.w3.org/TR/2008/REC-WCAG20-20081211/#navigation-mechanisms-focus-visible
https://www.w3.org/WAI/WCAG21/quickref/?versions=2.0#qr-navigation-mechanisms-focus-visible
OutlinedInput is desined in such a way that you can't turn off its outline you have to use TextField with variant 'outlined' as default and 'none' on focus.
You can see the example of Outlined Input Adornments using TextField here
Related
I have a ToggleButton component that has custom styling. I want to make that Toggle Button component look differently only when it's used as a child (inside) a ToggleButtonGroup. Here is how I'd call the ToggleButtonGroup component:
<ToggleButtonGroup onChange={()=>{}} ariaLabel='platform'>
<ToggleButton label='Japan' value='1' selected={true}/>
<ToggleButton label='China' value='2' selected={false}/>
<ToggleButton label='Brazil' value='3' selected={false}/>
</ToggleButtonGroup>
Here is the code for my ToggleButtonGroup component:
const StyledToggleGroup = styled(ToggleOptionsGroup)(
({ theme: { palette, spacing } }) => ({
height: spacing(10),
borderRadius: '6px',
boxShadow: 'none',
'&:hover': {
boxShadow: 'none',
},
'&.MuiToggleButtonGroup-root':{
gap: '0px'
},
'&.MuiToggleButton-standard':{
backgroundColor:'red',
},
'&.MuiToggleButtonGroup-grouped.Mui-selected': {
backgroundColor:'green',
}
})
);
const ToggleButtonGroup:React.FC<ToggleButtonGroupProps> = ({children, onChange, ariaLabel}) =>{
return(
<StyledToggleGroup
exclusive
onChange={onChange}
aria-label={ariaLabel}>
{children}
</StyledToggleGroup>
)
}
However, the last two classes:
'&.MuiToggleButton-standard':{
backgroundColor:'red',
},
'&.MuiToggleButtonGroup-grouped.Mui-selected': {
backgroundColor:'green',
}
don't really change anything.
How can I change the styling of my ToggleButton component only when it's passed as a child to the ToggleButtonGroup component?
It seems that class names are correct according to MUI document, the posted code should just need to specify these as children of StyledToggleGroup with a descendant combinator after & for the styles to work:
Tested in a simple demo here: stackblitz
"& .MuiToggleButton-standard": {
backgroundColor: "hotpink",
},
"& .MuiToggleButtonGroup-grouped.Mui-selected": {
backgroundColor: "lightblue",
},
I'm working on a basic calculator app with dynamic themes to be applied. How do I add a dynamic style react border-bottom with a set color on the keyStyle constant to be applied on my buttons?
I can't pass the value of currentTheme.numKeyShadow in the borderBottom css style as it's already a string.
How do i go about this?
This is a snippet my code:
import { useStateContext } from '../context/contextProvider'
const NumKeys = () => {
const { currentTheme, SetCurrentTheme } = useStateContext()
const keysStyle = {
borderRadius: "8px",
borderBottom:"4px solid",
borderBottomColor: currentTheme.numkeyShadow,
backgroundColor: currentTheme.keysBackground
}
return (
<section>
<div className='numKeys'>
<button style={keysStyle}>1</button>
</div>
</section>
)
}
export default NumKeys
This is my part of my data source:
export default [
{
"id": 0,
"background": "#3a4764",
"keysBackground": "#232c43",
"screenBackground": "#182034",
"KeysBackground": "#637097",
"KeysShadow": "#404e72",
"equaKeyBackground": "#d03f2f",
"equalKeyShadow": "#93261a",
"numKeyBackground": "#eae3dc",
"numKeyShadow": "#b4a597",
"num": "444b5a",
"equal": "#ffff"
}
]
You don't need a context or custom hook here. The CSS for the theme is a constant, and hence, you can declare, import and export like a simple JavaScript file.
NumKeys.js (React component)
import theme from "./Theme";
const NumKeys = () => {
const keysStyle = {
borderRadius: "8px",
borderBottom: "4px solid",
borderBottomColor: theme.numKeyShadow,
backgroundColor: theme.keysBackground,
};
return (
<section>
<div className="numKeys">
<button style={keysStyle}>1</button>
</div>
</section>
);
};
export default NumKeys;
Theme.js
const theme = {
id: 0,
background: "#3a4764",
keysBackground: "#232c43",
screenBackground: "#182034",
KeysBackground: "#637097",
KeysShadow: "#404e72",
equaKeyBackground: "#d03f2f",
equalKeyShadow: "#93261a",
numKeyBackground: "#eae3dc",
numKeyShadow: "#b4a597",
num: "444b5a",
equal: "#ffff",
};
export default theme;
This would add the style in your React component.
Live version - https://codesandbox.io/s/theme-0t9773
Trying to add styles to a Material-UI chip (outlined variant) upon hovering, but not getting the expected results.
The border color is white, but the background color doesn't change at all.
So I'm questioning whether backgroundColor is even the right property anymore, but what else can it be?
const CustomChip = withStyles(theme => ({
root: {
"&:hover": {
borderColor: "white",
backgroundColor: "green"
}
}
}))(Chip);
Below are the default background-color styles for the outlined variant of Chip:
/* Styles applied to the root element if `variant="outlined"`. */
outlined: {
backgroundColor: 'transparent',
'$clickable&:hover, $clickable&:focus, $deletable&:focus': {
backgroundColor: fade(theme.palette.text.primary, theme.palette.action.hoverOpacity),
},
In the styles above, $clickable& will be resolved to .MuiChip-clickable.MuiChip-outlined. The important aspect being that this rule is specified using two class names in addition to the pseudo-class (:hover or :focus). This means that these default styles will have greater specificity than the style rule you used for your override (which only uses one class name plus the pseudo-class). In order for your override to be successful, it needs to have specificity equal to or greater than the default styles.
One simple way to do this is to double the &. This causes the generated class name (which the ampersand refers to) to be specified twice in the rule -- increasing its specificity to match the default styles.
Here's a working example:
import React from "react";
import { makeStyles, withStyles } from "#material-ui/core/styles";
import Avatar from "#material-ui/core/Avatar";
import Chip from "#material-ui/core/Chip";
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
justifyContent: "center",
flexWrap: "wrap",
"& > *": {
margin: theme.spacing(0.5)
}
}
}));
const StyledChip = withStyles({
root: {
"&&:hover": {
backgroundColor: "purple"
},
"&&:focus": {
backgroundColor: "green"
}
}
})(Chip);
export default function SmallChips() {
const classes = useStyles();
const handleClick = () => {
console.info("You clicked the Chip.");
};
return (
<div className={classes.root}>
<StyledChip variant="outlined" size="small" label="Basic" />
<StyledChip
size="small"
variant="outlined"
avatar={<Avatar>M</Avatar>}
label="Clickable"
onClick={handleClick}
/>
</div>
);
}
I have ReactJS project and I want to change colour of button during clicking. I know that it is a Ripple API but it's very incomprehensible to use it. Could someone advise me how can I do that?
I've tried to create two elements - parent and child - and changed background of child to transparent while clicking. Unfortunately I have also 'classes' object responsible for changing class if button is active and it is just not working.
My code below:
import React, { Component } from 'react';
import { withStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import PropTypes from 'prop-types';
import styles from './MydButton.style';
class MyButton extends Component {
constructor(props) {
super(props);
this.state = {
isClicked: false
};
}
handleClick = () => {
this.setState({ isClicked: !this.state.isClicked });
}
render() {
const {
classes,
children,
color,
disabled,
className,
onClick,
type,
border,
...props
} = this.props;
const myClass = this.state.isClicked ? 'auxClass' : 'buttonDefaultRoot';
return (
<div className={classes.parentRoot} >
<Button
classes={{
root: disabled
? classes.buttonDisabledRoot
: classes.buttonRoot,
label: disabled
? classes.buttonLabelDisabled
: classes.buttonLabel,
}}
{...props}
onClick={this.handleClick}
className={myClass}
disabled={disabled}
type={type === undefined ? 'button' : type}
>
{children}
</Button>
</div>
)
}
};
MyButton.propTypes = {
children: PropTypes.string.isRequired,
disabled: PropTypes.bool,
classes: PropTypes.object.isRequired,
};
MyButton.defaultProps = {
disabled: false,
};
export default withStyles(styles)(MyButton);
and styles:
const buttonRoot = {
border: 0,
height: 48,
width: '100%',
}
export default theme => ({
buttonDefaultRoot: {
...buttonRoot,
transition: 'all 1s ease-in-out',
backgroundImage: 'linear-gradient(to right, #F59C81, #E65DA2, #E65DA2, #B13A97, #881E8E)',
boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.16)',
backgroundSize: '300% 100%',
marginTop: 0,
'&:hover': {
backgroundPosition: '100% 0%',
transition: 'all 1s ease-in-out',
}
},
parentRoot: {
...buttonRoot,
backgroundColor: 'red',
backgroundSize: '300% 100%',
marginTop: 36,
},
auxClass: {
backgroundImage: 'none',
},
Material UI Core for ReactJS
The documentation is very good. I have updated my answer to accomodate the specific needs of this question. I have also included two general solutions for anyone who stumbles upon this question.
Tailored Solution:
Changes background color of button from classes.buttonDefaultRoot (a color defined by owner of question) to the gradient defined by the owner of this question.
First step, have a variable stored in state. You can call it whatever you want, but I'm calling bgButton. Set this to this.props.classes.buttonDefaultRoot like so:
state = {
bgButton: this.props.classes.buttonDefaultRoot,
}
Next, you want to define your function that will handle the click. Again, call it what you want. I will call it handleClick.
handleClick = () => {
const { classes } = this.props; //this grabs your css style theme
this.setState({ bgButton: classes.parentRoot.auxClass }); //accessing styles
};
A couple of things are happening here. First, I am destructuring props. So, I am creating a new const variable called classes that has the same value as this.props.classes. The classes contains a set of objects that defines your css styles for your buttons, margins, etc. You can access those styles just like you would if you were trying to get the value of a prop in an obj.
In this case you can access your button style by doing, classes.buttonDefaultRoot. That takes care of your handle click function.
Last step: render the button. In your render method you want to grab your bgButton from state like so:
render() {
const { bgButton } = this.state;
Then you want to assign your className of your button to bgButton and add the onClick functionality like this (this follows the Material UI Core documentation):
<Button variant="contained" color="primary" className={classNames(bgButton)} onClick={this.handleClick}>Button Name</Button>
Putting it all together you get this:
import React, { Component } from "react";
import Button from "#material-ui/core/Button";
import PropTypes from "prop-types";
import classNames from "classnames";
import { withStyles } from "#material-ui/core/styles";
export default theme => ({ ... }) //not going to copy all of this
class MyButton extends Component {
state = {
bgButton: null
};
handleClick = () => {
const { classes } = this.props;
this.setState({ bgButton: classes.parentRoot.auxClass });
};
render() {
const { bgButton } = this.state;
return (
<div className={classes.container}>
<Button
variant="contained"
color="primary"
className={classNames(bgButton)}
onClick={this.handleClick}
>
Custom CSS
</Button>
</div>
);
}
}
MyButton.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(MyButton);
General Solution
This solution is for those who want to use the predefined colors, i.e. default, primary, secondary, inherit. This implementation does not need the PropTypes or className imports. This will change the color from the predefined blue to the predefined pink. That's it.
state = {
bgButton: "primary",
}
handleClick = () => {
this.setState({ bgButton: "secondary" });
}
render() {
const { bgButton } = this.state;
return(
...
<Button
onClick = {this.handleClick}
variant = "contained" //checked Material UI documentation
color={bgButton}
> ..etc.
General Solution 2
To accommodate your custom styles to the button, you would have to import PropTypes and classNames and take a similar approach as the tailored solution above. The only difference here will be my syntax and class name. I am closely following the documentation here so you can easily follow along and readjust where necessary.
import React, { Component } from "react";
import Button from "#material-ui/core/Button";
import PropTypes from "prop-types";
import classNames from "classnames";
import { withStyles } from "#material-ui/core/styles";
import purple from "#material-ui/core/colors/purple";
const styles = theme => ({
container: {
display: "flex",
flexWrap: "wrap"
},
margin: {
margin: theme.spacing.unit
},
cssRoot: {
color: theme.palette.getContrastText(purple[500]),
backgroundColor: purple[500],
"&:hover": {
backgroundColor: purple[700]
}
},
bootstrapRoot: {
boxShadow: "none",
textTransform: "none",
fontSize: 16,
padding: "6px 12px",
border: "1px solid",
backgroundColor: "#007bff",
borderColor: "#007bff",
fontFamily: [
"-apple-system",
"BlinkMacSystemFont",
'"Segoe UI"',
"Roboto",
'"Helvetica Neue"',
"Arial",
"sans-serif",
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"'
].join(","),
"&:hover": {
backgroundColor: "#0069d9",
borderColor: "#0062cc"
},
"&:active": {
boxShadow: "none",
backgroundColor: "#0062cc",
borderColor: "#005cbf"
},
"&:focus": {
boxShadow: "0 0 0 0.2rem rgba(0,123,255,.5)"
}
}
});
class MyButton extends Component {
state = {
bgButton: null
};
handleClick = () => {
const { classes } = this.props;
this.setState({ bgButton: classes.cssRoot });
};
render() {
const { classes } = this.props; //this gives you access to all styles defined above, so in your className prop for your HTML tags you can put classes.container, classes.margin, classes.cssRoot, or classes.bootstrapRoot in this example.
const { bgButton } = this.state;
return (
<div className={classes.container}>
<Button
variant="contained"
color="primary"
className={classNames(bgButton)}
onClick={this.handleClick}
>
Custom CSS
</Button>
</div>
);
}
}
MyButton.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(MyButton);
A tip. You no longer need a constructor or to bind methods.
Hope this helps.
I'm pretty new to css and i'm a little confused here. I'm using material ui with react and redux. I want somehow to edit some properties of a specific component. For example suppose we use TextField with disabled property. As i can see the disabled property contains these properties(i saw that from the material ui node modules in textfield).
var styles = {
root: {
borderTop: 'none',
borderLeft: 'none',
borderRight: 'none',
borderBottomStyle: 'solid',
borderBottomWidth: 1,
borderColor: borderColor,
bottom: 8,
boxSizing: 'content-box',
margin: 0,
position: 'absolute',
width: '100%'
},
disabled: {
borderBottomStyle: 'dotted',
borderBottomWidth: 2,
borderColor: disabledTextColor
},
But i dont want when it's disable for the borderBottomLine to be dotted. I want to change it to hidden. How to do such an action without affecting the frameworks code?
You can override some default styles of material-ui components. Look at this section of docs. Pay attention to this example:
import React from 'react';
import {cyan500} from 'material-ui/styles/colors';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import AppBar from 'material-ui/AppBar';
// This replaces the textColor value on the palette
// and then update the keys for each component that depends on it.
// More on Colors: http://www.material-ui.com/#/customization/colors
const muiTheme = getMuiTheme({
textField: {
backgroundColor: 'yellow',
},
datePicker: {
color: 'yellow',
},
});
// MuiThemeProvider takes the theme as a property and passed it down the hierarchy.
const Main = () => (
<MuiThemeProvider muiTheme={muiTheme}>
<AppBar title="My AppBar" />
</MuiThemeProvider>
);
export default Main;
Here, we override background-color for TextField component and color for DatePicker. You should import getMuiTheme function, pass to its object with properties which you want to override. Unfortunately, for disabled TextField you can override only text color. You can check all properties which you can override from source of default theme - https://github.com/callemall/material-ui/blob/master/src/styles/getMuiTheme.js
const muiTheme = getMuiTheme({
textField: {
backgroundColor: 'yellow',
},
datePicker: {
color: 'yellow',
},
});
After that, you should pass muiTheme to the eponymous property
of MuiThemeProvider component. This component should wrap root-component of your application.
const Main = () => (
<MuiThemeProvider muiTheme={muiTheme}>
<AppBar title="My AppBar" />
</MuiThemeProvider>
);
Here's sample code. Use style in your preferred jsx tag and edit it normally like CSS, but the properties & values must be inside quotation marks("").
import React from "react";
import AppBar from "#mui/material/AppBar";
import Toolbar from "#mui/material/Toolbar";
const index = () => {
return (
<AppBar style={{ backgroundColor: "black", height: "65px" }}>
<Toolbar></Toolbar>
</AppBar>
);
};
export default index;