Adhoc styling in Material-UI 5 - material-ui

Trying to upgrade from MUI 4 to 5. In MUI 4, I used to be able to introduce adhoc classes using makeStyles:
const useStyles = makeStyles((theme: Theme) => ({
root: {
cursor: 'pointer',
},
}));
export const FakeLink = ({ children }) => {
const classes = useStyles();
return (
<span className={classes.root}>
{children}
</span>
);
};
Now trying to put the same cursor: 'pointer' on an ImageListItem. How do I do this?
<ImageListItem>
<img ... />
</ImageListItem>
I thought I could do it using sx, but it doesn't implement the cursor property. What am I missing?

The cursor property should be supposed by the sx and styled API. Maybe you are facing a TypeScript issue?

Related

Unable to pass props to makeStyles when using material UI with next.js

I am using Next.js with material UI.
I have created a Icon and when clicked it calls the setOpenFn() and sets the open variable to be true. This variable is then passed as props to the useStyles(). Now I display the search bar if open is true. But I get the below error
webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:67 Warning: Prop `className` did not match. Server: "makeStyles-search-3 makeStyles-search-8" Client: "makeStyles-search-3 makeStyles-search-9"
When the search Icon is clicked display: flex property is also not working.
I tried to create .babelrc file and added this
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}
but still nothing works.
const useStyles = makeStyles((theme) => ({
search: {
[theme.breakpoints.down('sm')]: {
display: (props) => (props.open ? 'flex' : 'none'),
width: '70%',
},
}
}))
const Navbar = () => {
const [open, setOpen] = useState(false);
const setOpenFn = () => {
setOpen(true);
};
const classes = useStyles({ open });
return(
<Search
className={classes.searchButton}
onClick={() => {
setOpenFn();
}}
/>
)
}
I am assuming you are using mui version 5+
According to this migration guide! you need to wrap your JSX with the following component.
<StyledEngineProvider injectFirst>
</StyledEngineProvider>

IonToggle firing twice in React-based Ionic project

In the following block of code, the IonToggle is firing twice for some unknown reason. I had it already replaced with a normal button and it works fine. If I keep the IonToggle and remove the line setUpdating(true) it also works fine.
Is it some known bug, or is there something wrong with this code.
import { AppContext } from './../AppContextProvider';
const LightController: React.FC<InterfaceLamp> = ({ id, color, brightness, turnedOn }) => {
const { state, dispatch } = useContext(AppContext);
const [isUpdating, setUpdating] = useState(false);
const isMount = useIsMount();
const handleUpdateToggle = async (isToggled: boolean) => {
lightService.toggleLight(state.api, id, isToggled, state.auth.username,
state.auth.password).then((res) => {
if (!res.error) {
[...]
dispatch({
key: 'devices',
data: devices,
})
}
setUpdating(false);
})
}
const handleToggle = (isToggled: boolean) => {
setUpdating(true);
handleUpdateToggle(isToggled);
}
return (
<div className="c-light">
<Loader isLoading={isUpdating} message={"Updating devices"} onClose={() => { }} />
<div className="c-light__controls">
<div className="c-light__toggle">
<IonItem lines={"none"}>
<button onClick={(e)=>handleToggle(!turnedOn)}>toggle</button>
<IonToggle checked={turnedOn} onIonChange={(e) => handleToggle(e.detail.checked)}/>
</IonItem>
</div>
</div>
</div>
);
};
export default LightController;
value="true"
why are you setting the value here? dont think it is necessary
As of Ionic React v5.5.0, IonToggle and IonCheckbox have still got the same issue.
The simplest workaround is to add an onClick event listener to the IonItem component that usually wraps the IonToggle component. (Alternately, use any other wrapper component with onClick.) This approach makes it possible to keep the native-looking IonToggle.

Styling react-select v2 with material-ui - Replace Input component

I'm having an issue with replacing the Input component for react-select v2 with the Input component from Material UI.
I've made an attempt so far in the codesandbox below, but unable to invoke the filtering upon typing into the Input?
https://codesandbox.io/s/jjjwoj3yz9
Also, any feedback on the Option replacement implementation would be appreciated. Am I going about it the right way with grabbing the text of the clicked option and search for the Option object from my options list to pass to the selectOption function?
Much appreciated,
Eric
V1
refer the documentation from here : https://material-ui.com/demos/autocomplete/
it provides clear documentation about how to use react-select with material-ui
here is a working example for your question: https://codesandbox.io/s/p9jpl9l827
as you can see material-ui Input component can take react-select as inputComponent.
V2
It's almost same as the previous approach :
implement the Input component:
<div className={classes.root}>
<Input
fullWidth
inputComponent={SelectWrapped}
value={this.state.value}
onChange={this.handleChange}
placeholder="Search your color"
id="react-select-single"
inputProps={{
options: colourOptions
}}
/>
</div>
and then SelectWrapped component implementation should be:
function SelectWrapped(props) {
const { classes, ...other } = props;
return (
<Select
components={{
Option: Option,
DropdownIndicator: ArrowDropDownIcon
}}
styles={customStyles}
isClearable={true}
{...other}
/>
);
}
and I overrides the component Option and DropdownIndicator to make it more material and added customStyles also:
const customStyles = {
control: () => ({
display: "flex",
alignItems: "center",
border: 0,
height: "auto",
background: "transparent",
"&:hover": {
boxShadow: "none"
}
}),
menu: () => ({
backgroundColor: "white",
boxShadow: "1px 2px 6px #888888", // should be changed as material-ui
position: "absolute",
left: 0,
top: `calc(100% + 1px)`,
width: "100%",
zIndex: 2,
maxHeight: ITEM_HEIGHT * 4.5
}),
menuList: () => ({
maxHeight: ITEM_HEIGHT * 4.5,
overflowY: "auto"
})
};
and Option:
class Option extends React.Component {
handleClick = event => {
this.props.selectOption(this.props.data, event);
};
render() {
const { children, isFocused, isSelected, onFocus } = this.props;
console.log(this.props);
return (
<MenuItem
onFocus={onFocus}
selected={isFocused}
onClick={this.handleClick}
component="div"
style={{
fontWeight: isSelected ? 500 : 400
}}
>
{children}
</MenuItem>
);
}
}
please find the example from here: https://codesandbox.io/s/7k82j5j1qx
refer the documentation from react select and you can add more changes if you wish.
hope these will help you.

Apply CSS to Typography Material UI

Im trying to apply css to a Typography element but it does nothing; I have tried the same css on another div element and it works but it simply does not apply to Typography.
This is my Typography element:
<Typography
variant="title"
classname={classes.detailTitle}
>
Details:
</Typography>
And this is my css:
detailTitle: {
textDecoration: 'underline'
}
Any clues?
You have a slight typo in your Typography html, it needs to say className where you have classname. This is react specific, for more info take a look here https://reactjs.org/docs/dom-elements.html
You can use Material UI component's classes property to set its style.
Check this page https://material-ui.com/api/typography/#css
Example:
const useStyles = makeStyles((theme) => ({
h3: {
fontSize: '48px',
fontWeight: '600'
},
})
)
const TextComp = (props) => {
const classes = useStyles()
return (
<Typography
variant='h3' component='h3'
classes={{ h3: internalClasses.h3 }}
>
{header}
</Typography>
)
}

MaterialUI together with styled-components, SSR

I'm building a new project with SSR using Next.js, MaterialUI and styled-components. From what I know, MaterialUI uses JSS as a tool for SSR (according to the example in its repository). I wonder if anyone knows how I can make it work with styled-components. I opened issues in MaterialUI and styled-components repositories, both authors answered me that they don't know how to make it work together. But probably anyone did it already? Or at least can tell me where to dig to solve this problem. Thanks in advance!
You can use styled-components with material ui, but you'll end up needing to use !important a lot. Like this:
import Button from "material-ui/Button"
const MyButton = styled(Button)`
background: red !important;
`
In the project I'm working on with the same combo, I've just resorted to using the JSS style material-ui wants you to use with the whole withStyles HOC..
You may check their docs here https://material-ui.com/guides/interoperability/#styled-components, you may check the deeper elements section if you want to override specific classes https://material-ui.com/guides/interoperability/#deeper-elements
below is my example where for the switch component
const StyledSwitch = styled(({ ...other }) => (
<div>
<Switch
{...other}
classes={{ colorSecondary: 'colorSecondary', checked: 'checked', bar: 'bar' }}
/>
</div>
))`
& .colorSecondary.checked + .bar {
background-color: ${props => props.theme.lighter.toString()};
}
& .colorSecondary.checked {
color: ${props => props.theme.default.toString()};
}
`;
export default StyledSwitch;
usage
<StyledSwitch theme={lightTheme.secondary} />
this is using a theme but you can specify any color you want
Looks like we have 3 ways (could be easier, but not everything is flowers) to override Material UI styles with Styled Components. Here is my Gist.
I do it like this:
In head component of app:
const styleNode = document.createComment('insertion-point-jss')
document.head.insertBefore(styleNode, document.head.firstChild)
const generateClassName = createGenerateClassName()
const jss = create({
...jssPreset(),
insertionPoint: 'insertion-point-jss'
})
<JssProvider jss={jss} generateClassName={generateClassName}>
<Main />
</JssProvider>
and then just style:
import styled from 'styled-components'
import Select from '#material-ui/core/Select'
import Input from '#material-ui/core/Input'
import React from 'react'
export const InputM = styled(({ ...other }) => (
<Input {...other} classes={{ input: 'input' }} />
))`
color: ${p => p.theme.textColor};
& .icon {
font-family: ${p => p.theme.fontFamily};
font-size: ${p => p.theme.fontSize}px;
color: ${p => p.theme.textColor};
}
`