In our current react app, we are using material ui v4, we have following customized style:
const useStyles = makeStyles((theme) =>
createStyles({
dob: {
color: theme.palette.grey[300],
},
location: {
color: theme.palette.grey[300],
},
})
)
And in our component, we have
<Box>
...
<Typography className={classes.dob} variant="caption">
{formatDateTime(
person.dateOfBirth,
"M/D/YYYY HH:mm:ss A"
)}
</Typography>
<Typography className={classes.location} variant="caption">
{props.person.location}
</Typography>
...
</Box>
Now we are upgrading to v5. In the migration guide, it recommended to use sx, but I got an error with theme
<Typography sx={{theme.palette.grey[300]}} variant="caption">
{props.person.location}
</Typography>
Does any know how do I fix this? In addition, I wonder if I could use styled() to create a custom style on a material ui components, such as Box, Appbar, etc. The examples provided in the guide only for generic html elements, such as div, span. For example:
const MyTypograhy = styled('Typography')(({ theme }) => ({
color: theme.palette.primary.main,
}))
sx could act like inline style, so you must provide the data type, and if you want to use theme, you must pass as a function with theme is the first parameter
<Typography sx={{ color: theme => theme.palette.grey[300] }} variant="caption">
{props.person.location}
</Typography>
And yes you could create custom component based on existing MUI component
const CustomBox = styled(Box)((theme) => ({
padding: "2rem",
background: "black"
}));
Codesandbox Demo
References
The sx prop
Style library interoperability
Related
I am using MUI's Text Field component and found there's literally no way to copy the label contents. Is there a way to copy the label somehow?
See the demo here: https://codesandbox.io/s/4ou0l7?file=/demo.tsx
Thanks
It is because material UI is disabling the label selection using CSS.
You can enable it back in a few ways. You can enable it for a certain field or across all of them using the material UI theme override ability.
In order to enable label selection only to one field, you have pass an additional prop to your TextField: InputLabelProps={{ sx: { userSelect: "text" } }}
And here I have provided you with the second way to do that for all the text fields:
import * as React from "react";
import Box from "#mui/material/Box";
import TextField from "#mui/material/TextField";
import { createTheme, ThemeProvider } from "#mui/material/styles";
const theme = createTheme({
components: {
MuiInputLabel: {
styleOverrides: {
root: {
userSelect: "text"
}
}
}
}
});
const StateTextFields = () => {
const [name, setName] = React.useState("Cat in the Hat");
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
};
return (
<Box
component="form"
sx={{
"& > :not(style)": { m: 1, width: "25ch" }
}}
noValidate
autoComplete="off"
>
<TextField
id="outlined-name"
label="Name"
value={name}
onChange={handleChange}
/>
<TextField
id="outlined-uncontrolled"
label="Uncontrolled"
defaultValue="foo"
/>
</Box>
);
};
export default () => (
<ThemeProvider theme={theme}>
<StateTextFields />
</ThemeProvider>
);
Of course, you can extract this ThemeProvider into a separate file and wrap with it the whole project, not only this file. It is combined just for the example.
I found a way that this can be done using the helperText and my solution is more of a hack. I am using the helperText and positioning it where the label was used to be, giving it a background and bringing it to front using z-index.
Also you can either choose to use the label or replace it with the placeholder depending if you are happy with the animation.
Here is a codesandbox based on your code in case you need it.
<TextField
id="outlined-name"
label="Name"
// placeholder="Name"
value={name}
onChange={handleChange}
helperText="Name"
sx={{
"& .MuiFormHelperText-root": {
top: "-11px",
position: "absolute",
zIndex: "1",
background: "white",
padding: "0 4px",
}
}}
/>
I am following the example here [1] to create a custom theme using Material-UI. On Line 10 in App.js [2] it references color="textSecondary", can someone explain where the value textSecondary comes from?
I was able to get the example to work using:
style={{ color: theme.palette.secondary.light }}
but I'd prefer to be able to use the shorter syntax reference.
Full App.js code below:
import React from 'react';
import Container from '#material-ui/core/Container';
import Typography from '#material-ui/core/Typography';
import Box from '#material-ui/core/Box';
import ProTip from './ProTip';
import Link from '#material-ui/core/Link';
import theme from './theme';
function MadeWithLove() {
return (
<Typography variant="body2" style={{ color: theme.palette.secondary.light }} align="center">
{'Built with love by the '}
<Link color="inherit" href="https://material-ui.com/">
Material-UI
</Link>
{' team.'}
</Typography>
);
}
export default function App() {
return (
<Container maxWidth="sm">
<Box my={4}>
<Typography variant="h4" component="h1" gutterBottom>
Create React App v4-beta example
</Typography>
<ProTip />
<MadeWithLove />
</Box>
</Container>
);
}
My theme.js file is:
import { createMuiTheme } from '#material-ui/core/styles';
const theme = createMuiTheme({
palette: {
primary: {
light: '#6fbf73',
main: '#4caf50',
dark: '#357a38',
contrastText: '#fff',
},
secondary: {
light: '#5464c0',
main: '#2a3eb1',
dark: '#1d2b7b',
contrastText: '#000',
},
},
});
export default theme;
[1] https://github.com/mui-org/material-ui/tree/master/examples/create-react-app
[2] https://github.com/mui-org/material-ui/blob/master/examples/create-react-app/src/App.js#L10
If you have a look at the documentation for Typography component, you can provide several options for the color prop:
name: color
type: enum: 'initial', 'inherit', 'primary', 'secondary', 'textPrimary', 'textSecondary', 'error'
default: 'initial'
description: The color of the component. It supports those theme colors that make sense for this component.
textSecondary is defined here: https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Typography/Typography.js#L92 as
theme.palette.text.secondary
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.
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>
)
}
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};
}
`