I was previously using Material UI's Button component, which has the disable property. Basically that prop allows the button to be disabled based on a boolean. So if true, then it is disabled. However, now I want to switch to the Material UI Link component which is also a button, but it looks like a text. It does the same thing a button does, but looks like a link. However, it does not have the disable property or it seems because I dont see it as a possible property in the Material UI docs. Is there any work around for this?
*Note - This is not from the React Router Dom library. I am using the Link from Material UI Library for React. Just so there is no confusion.
<Link
hover
underline="hover"
variant="body2"
onClick={
this.buyAll
}>
Buy All Products
</Link>
Material-UI's Link renders as an <a> element by default. If you want it to render as a <button> (which would be appropriate when you are specifying onClick and not specifying href), then you need to specify component="button". Once you have done that, the disabled prop will work as expected with the caveat that Material-UI's Link doesn't have any styling for a "disabled" look; so if you want the link to look different when it is disabled, you will need to customize the styles for that state.
Below is a working example including some sample disabled styling:
import React from "react";
import { makeStyles, withStyles } from "#material-ui/core/styles";
import MuiLink from "#material-ui/core/Link";
import Typography from "#material-ui/core/Typography";
const useStyles = makeStyles((theme) => ({
root: {
"& > * + *": {
marginLeft: theme.spacing(2)
}
}
}));
const Link = withStyles({
root: {
"&[disabled]": {
color: "grey",
cursor: "default",
"&:hover": {
textDecoration: "none"
}
}
}
})(MuiLink);
export default function Links() {
const classes = useStyles();
return (
<Typography className={classes.root}>
<Link component="button" onClick={() => console.log("hello")}>
Link
</Link>
<Link
component="button"
disabled
onClick={() =>
console.log(
"I'm disabled so this doesn't appear in the console when this is clicked."
)
}
>
Disabled Link
</Link>
</Typography>
);
}
Thank #RyanCogswell. I tried to improve his answer by defining a custom theme, based on MUI's default theme and using pointer-events: none:
import { createTheme } from '#mui/material/styles'
const { palette } = createTheme() // MUI's default theme
const theme = createTheme({ // Our app's custom theme
MuiLink: {
styleOverrides: {
root: {
'&[disabled]': {
color: palette.action.disabled,
pointerEvents: 'none',
},
},
},
},
})
import { Link } from '#mui/material'
//...
<Link
disabled
to='https://stackoverflow.com/a/72479343/5318303'
>
Disabled link
</Link>
Related
I have a custom component for Buttons using NativeBase, and it seems work great initially; once I restart the project, the default style for the button I have set no longer works. To fix this, I have to manually set a variation, and then remove it, like so :
<Button variation="random" /> // Sets the variation to something random
<Button /> // delete the variation section of button, and now the default loads
I have it set up like so:
export const style = extendTheme({
components:{
Button: {
baseStyle: {
rounded: 'lg',
},
defaultProps: {
size: 'sm',
colorScheme: 'green',
_text: {
color: 'white',
fontSize: '30px',
...fonts.h1, //custom font
margin: -2,
}
},
}
}
Then, within App.js:
const style = style // from import
return (
<NativeBaseProvider theme={style}>
<NavigationContainer>
<StackNavigator>
...etc.
)
And finally, in another file:
<Button />
Why is this occurring? I assume it has something to do with NativeBaseProvider wrapping everything in App.js, instead of just wrapping each individual file using the custom components with it.
Thanks!
import { IconButton } from "#mui/material";
import React, { useState, useEffect } from "react";
import { Brightness4, Brightness7 } from "#mui/icons-material";
const ThemeChanger = () => {
const [themeState, setThemeState] = useState(false);
useEffect(() => {
const getTheme = localStorage.getItem("Theme");
if (getTheme === "dark") {
setThemeState(true);
} else {
}
}, []);
useEffect(() => {
if (themeState) {
localStorage.setItem("Theme", "dark");
document.body.classList.add("dark-mode");
} else {
localStorage.setItem("Theme", "light");
document.body.classList.remove("dark-mode");
}
}, [themeState]);
return (
<div>
<IconButton
className="icon-button"
style={{ marginTop: "16px" }}
onClick={() => {
setThemeState(!themeState);
document.body.classList.add("dark-light-toggle-transition");
}}
>
{themeState ? <Brightness4 /> : <Brightness7 />}
</IconButton>
</div>
);
};
export default ThemeChanger;
I am trying to make the former component to not fire the event of the transition that I have in "dark-mode" when I reload the page. The component is capable of toggling a dark mode.
I tried a bit of jQuery and the window.performance event but I could not make it work. I think the solution is not that hard but I am really loaded and my brain is not functioning anymore. Is there anyone who could help me?
P.S. I used a "preload" class with jQuery and set the class of the body into transition: none, however the problem is the useEffect as when the state is true it always adds the "dark-mode" class.
Thanks in advance!
EDIT: Actually I made it work. I just made a class called "dark-light-toggle-transition" which essentially is doing the work for me. I put it inside the jsx ThemeChanger component so it is only applied when I press the toggle button! If anyone needs more information, you can send me here!
pure-react-carousel gives me an unstyled html button (ButtonBack) and I want to style it using material-ui.
Placing buttons inside buttons is not permitted.
What works is to assign the className prop manually:
<ButtonBack className={"MuiButtonBase-root MuiButton-root MuiButton-contained"}>
<NavigateBeforeIcon />
</ButtonBack>
But it feels wrong, and also does not render as nice as an real Mui-Button.
Of course I could write my own css that mimics Muis but that feels wrong too.
Is there an easier/straight-forward way to this problem?
import { ButtonFirst } from 'pure-react-carousel';
import Button from '#material-ui/core/Button';
const CustomButtonFirst = React.forwardRef((props, ref) => <Button component={ButtonFirst} ref={ref} {...props} />);
// This line is needed because the "disabled" is internal state of "ButtonFirst".
export default withStore(CustomButtonFirst, state => ({ disabled: state.currentSlide === 0 }));
Taken from:
https://github.com/express-labs/pure-react-carousel/issues/175
I am building a webpage with React and Material-UI. I have a TextField element and I want to remove the arrow buttons - if I were using CSS I would use the following code:
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
But I want to style the page using CSS in JS where I use export default withStyles(styles)(FormPersonalDetails). How do I do this?
`
const styles = theme => ({
number: {
// styling code goes here//
}
});
render() function:
const { classes } = this.props;
return (
<TextField className={classes.number} />
)
There are a few syntax options. I have included two options below. The first one uses className on TextField and then targets the descendant input element. The second one applies the className directly to the input element via the TextField inputProps property.
The & is used in both to refer to the parent selector (i.e. the element that the class is being applied to).
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 = theme => ({
number: {
"& input::-webkit-outer-spin-button, & input::-webkit-inner-spin-button": {
"-webkit-appearance": "none",
margin: 0
}
},
input: {
"&::-webkit-outer-spin-button, &::-webkit-inner-spin-button": {
"-webkit-appearance": "none",
margin: 0
}
}
});
function App({ classes }) {
return (
<div className="App">
<TextField type="number" className={classes.number} />
<br />
<TextField type="number" inputProps={{ className: classes.input }} />
</div>
);
}
const StyledApp = withStyles(styles)(App);
const rootElement = document.getElementById("root");
ReactDOM.render(<StyledApp />, rootElement);
I'm developing a React project using the material-ui library. I'm currently trying to add a drawer which is working fine for me. However, I'm trying to change the background color of this drawer. I've heard that the way to do this is by changing the color of the drawer's paper. I've tried adding the following tag to my CSS object:
const styles = theme => ({
background:"BLUE"
Then I reference this object in my render function using the classNames library:
render(){
const { classes } = this.props;
return(
<div className={styles.root}>
<CssBaseline />
<Drawer
variant="permanent"
className={classNames(classes.drawer, {
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})}
classes = {{
paper: classNames({
background:classes.background,
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})
}}
However, when I run this on localhost, the paper is still a plain old white. Am I missing something about the classNames library or is a special case of the paper tag? Thanks in advance and let me know if I should supply more info than this.
You have a couple issues in the code shown in your question.
For your styles, you need something more like the following:
const styles = theme => ({
drawerPaper: { background: "blue" }
});
In this case, "drawerPaper" is the key for my class name and then the object to the right contains the CSS properties for that class. When passed into withStyles, this will generate CSS like the following:
<style>
.classname-generated-for-drawerPaper-key: {
background: blue;
}
</style>
You had a class name key of "background" with the string "BLUE" as the CSS properties which will end up with CSS like the following:
<style>
.classname-generated-for-background-key: {
0: B;
1: L;
2: U;
3: E;
}
</style>
which of course is not valid CSS and will have no effect on the paper.
The second issue is in how you specify the classes:
classes = {{
paper: classNames({
background:classes.background,
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})
}}
When you pass an object to classNames, the keys of the object are the class names and the associated value controls (based on whether it is falsey or truthy) whether the class name should be included. With the syntax you used, classes.background will always be truthy which means that the class "background" (rather than the generated class name in classes.background) will be included which will have no effect since a "background" class hasn't been defined.
Instead you should have:
classes = {{
paper: classNames(classes.drawerPaper, {
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})
}}
which will unconditionally include classes.drawerPaper.
Here is a modified version of one of the Drawer demos, but with the background color of the drawer changed to blue: https://codesandbox.io/s/wqlwyk7p4l
If you're using global theme = createTheme( the color of a background paper can be set as following
const theme = createTheme({
palette: {
{
primary: colors.blue,
background: {
default: colors.grey[50],
paper: colors.common.white,
},
// ...