The input text in a Material-UI Multiline TextField is overlapping each other (not the label).
See sample and code in CodeSandBox: https://codesandbox.io/s/keen-wu-yquk6
I suspect it may have something to do with the fact that I increased the Font-Sized to 30, but the line-height (or something else) remained configured for the default size font.
Samples screenshots:
import React from "react";
import styled from "styled-components";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const useStyles = makeStyles(theme => ({
container: {
display: "flex",
flexWrap: "wrap"
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
width: 350
}
}));
const StyledTextField = styled(TextField)`
.MuiInput-underline::before {
border-bottom-color: white;
}
.MuiInput-underline:hover:not(.Mui-disabled)::before {
border-bottom-color: white;
}
.MuiInput-underline::after {
border-bottom-color: #fdcd39;
}
`;
const StyledTextArea1 = ({ Label, fieldType, handleChange }) => {
const classes = useStyles();
return (
<StyledTextField
id="standard-basic"
className={classes.textField}
label="Test Label"
multiline
fullWidth
rows="5"
variant="outlined"
margin="normal"
// onChange={handleChange(fieldType)}
InputLabelProps={{
style: {
color: "black",
fontSize: 30,
borderBottom: "white",
fontFamily: "Akrobat"
}
}}
inputProps={{
style: {
fontSize: 30,
color: "#fdcd39",
fontFamily: "Akrobat",
fontWeight: 800
}
}}
/>
);
};
export { StyledTextArea1 };
Any assistance greatly appreciated.
Setting the font styles via inputProps defines those styles on the textarea element whereas Material-UI controls the font size on a div (with the MuiInputBase-root CSS class) that wraps the textarea. If you move where you control the font styles to target .MuiInputBase-root, it works as desired.
import React from "react";
import styled from "styled-components";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const useStyles = makeStyles(theme => ({
container: {
display: "flex",
flexWrap: "wrap"
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
width: 350
}
}));
const StyledTextField = styled(TextField)`
.MuiInputBase-root {
font-size: 30px;
color: #fdcd39;
font-family: Akrobat;
font-weight: 800;
}
.MuiInput-underline::before {
border-bottom-color: white;
}
.MuiInput-underline:hover:not(.Mui-disabled)::before {
border-bottom-color: white;
}
.MuiInput-underline::after {
border-bottom-color: #fdcd39;
}
`;
const StyledTextArea1 = ({ Label, fieldType, handleChange }) => {
const classes = useStyles();
return (
<StyledTextField
id="standard-basic"
className={classes.textField}
label="Test Label"
defaultValue="Default Value"
multiline
fullWidth
rows="5"
variant="outlined"
margin="normal"
// onChange={handleChange(fieldType)}
InputLabelProps={{
style: {
color: "black",
fontSize: 30,
borderBottom: "white",
fontFamily: "Akrobat"
}
}}
/>
);
};
export { StyledTextArea1 };
In my sandbox, I also added <StylesProvider injectFirst> around everything in index.js to ensure that the styled-components CSS classes are injected after the Material-UI CSS classes in the <head> so that your style overrides via styled-components will win in cases where specificity is the same.
Related
I have the following component:
import * as React from "react";
import { createTheme, ThemeProvider } from '#mui/material/styles'
import { Box } from '#mui/system';
import { InputBase, TextField, Typography } from "#mui/material";
import ReactQuill from 'react-quill';
import { NoEncryption } from "#mui/icons-material";
type Props = {
issueId: string
}
export default function DialogBox({ issueId }: Props) {
const myTheme = createTheme({
// Set up your custom MUI theme here
})
const [newMsg, setNewMsg] = React.useState("");
const [startNewMsg, setStartNewMsg] = React.useState(false)
const handleNewMsgInput = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
}
const handleKeyPress = (event: React.KeyboardEvent<HTMLDivElement>) => {
if (event.key === "Escape") {
// setStartNewMsg(false);
setNewMsg((prev) => "");
}
}
return (
<Box flexDirection="column" sx={{ display: "flex", alignItems: "center", backgroundColor: "lightblue", height: "100%", gap: "2rem" }} onKeyPress={(e) => {
handleKeyPress(e)
}}>
<Typography
sx={{
width: "fit-content",
height: "fit-content",
fontFamily: "Amatic SC",
background: "lightblue",
fontSize: "3rem"
}}>
Message board
</Typography>
{startNewMsg ?
<Box sx={{ width: "fit-content", height: "fit-content" }}>
<ReactQuill style={{ backgroundColor: "white", height: "10rem", maxWidth: "30rem", maxHeight: "10rem" }} theme="snow" />
</Box>
:
<TextField id="filled-basic" label="write new message" sx={{ "& fieldset": { border: 'none' }, backgroundColor: "white", borderRadius: "5px" }} variant="filled" fullWidth={true} onClick={(e) => setStartNewMsg((prev) => true)} onChange={(e) => handleNewMsgInput(e)} />}
</Box >
)
}
Which's causing me the following issue of text appearing out of my white textbox:
I notice on inspection the following property which's responsible for the problem:
My question is, what would be the best way to manipulating the values of that element? How should I retrieve them?
Regards!
Use ch units (the size of the text characters) and adjust the size based on the input.
Example:
const Test = () => {
const [text, setText] = useState('');
return (
<div>
<input
value={text}
onChange= {(e) => setText(e.target.value)}
style= {{height: `${text.length}ch`, width: `${text.length}ch`}}
/>
</div>
);
};
^ that is an input box that will grow based on the size of the text.
You don't want:
height: 100%;
as this will only allow the height to be as big as its parent container.
Currently trying to figure out how to render the styles(without having to do inline styles) from the styles object for the stepper component. However, it is giving me an error when I try to do something similar to what Material UI's demo gave me. I took bits and pieces from it basically and tried to implement it in my code. Here is what Material UI's demo looks like which I want to replicate as well.
And here is the code they have
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%)',
}),
}));
function ColorlibStepIcon(props) {
const { active, completed, className } = props;
const icons = {
1: <SettingsIcon />,
2: <GroupAddIcon />,
3: <VideoLabelIcon />,
};
return (
<ColorlibStepIconRoot ownerState={{ completed, active }} className={className}>
{icons[String(props.icon)]}
</ColorlibStepIconRoot>
);
}
I figured I could scrap the HOC component(color step icon root) and just do without root. Also, they are importing styled from
import { styled } from '#mui/material/styles';
Which when I try to do, its undefined. So I tried to use it in the styles object the way Ive been always doing with withStyles.
But am getting this error:
Here is my code:
import React from 'react';
import { Typography } from '#material-ui/core';
import { withStyles } from '#material-ui/core/styles';
import Stepper from '#material-ui/core/Stepper';
import Step from '#material-ui/core/Step';
import StepLabel from '#material-ui/core/StepLabel';
import Icon from '#material-ui/core/Icon';
import PropTypes from 'prop-types';
const styles = theme => ({
stepLabelRoot: {
fontWeight: 'bold',
color: '#fff',
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
},
checklistHeader: {
fontWeight: 'bold',
marginTop: '80px',
color: 'white'
},
connectorIcon: {
color: theme.palette.text.secondary
},
active: {
backgroundColor: 'green'
},
stepper: {
background: 'none',
fontWeight: 'bold',
height: '500px'
},
checklistImage: {
width: '42px',
height: '42px'
}
});
const steps = ['Are you there?', 'Adopt', 'Buy'];
const Checklist = ({ classes }) => {
const ColorlibStepIcon = ({
icon, completed, className, classes, theme
}) => {
const icons = {
1: <img className={classes.checkListImage} src="https://i.pinimg.com/474x/be/54/bd/be54bd5e8e9c23e3ce570ff2acae592d.jpg" alt="check" />,
2: <img className={classes.checkListImage} src="https://i.pinimg.com/474x/be/54/bd/be54bd5e8e9c23e3ce570ff2acae592d.jpg" alt="check" />,
3: <img className={classes.checkListImage} src="https://i.pinimg.com/474x/be/54/bd/be54bd5e8e9c23e3ce570ff2acae592d.jpg" />,
};
return (
<div ownerState={{ completed }} className={className}>
{icons[String(icon)]}
</div>
);
};
return (
<React.Fragment>
<Typography variant="h6" align="center" gutterBottom className={classes.checklistHeader}>Check the following</Typography>
<Stepper alternativeLabel activeStep={2} className={classes.stepper}>
{steps.map(label => (
<Step key={label}>
<StepLabel classes={{ root: classes.stepLabelRoot }} StepIconComponent={ColorlibStepIcon}>
<div className={classes.stepLabelRoot}>
{label}
</div>
<span>
Lorem Ipsum
</span>
</StepLabel>
</Step>
))}
</Stepper>
</React.Fragment>
);
};
Checklist.defaultProps = {
};
Checklist.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles, { withTheme: true })(Checklist);
You have 2 bugs in your code. In your icon component:
<img className={classes.checkListImage}
The rule name you defined above is called checklistImage not checkListImage, so change it to:
<img className={classes.checklistImage}
Secondly, the classes from the Checklist component is shadowed by the classes inside ColorlibStepIcon:
const ColorlibStepIcon = ({
icon,
completed,
className,
theme,
/*classes <-- this classes is undefined which shadows the real classes
passing from above, so remove it */
}) => {
I am creating a Radio button in React using emotion styled-components. Due to the fact we export out components into an online component repo (Bit.dev), I can not use targeted styled-components selectors and have to use classNames. I have built a switch the same way and using a class selector I can change the CSS of another component when the switch (input) is checked. However, when my toggle is changed to "checked" the class selector doesn't work:
Here is my code:
import React from "react";
import PropTypes from "prop-types";
import { Container, Input, Label, Outline, Fill } from "./styles";
const RadioButton = ({ id, ...props }) => {
return (
<Container>
<Input id={id} type="radio" {...props} />
<Label htmlFor={id}>
<Outline className="outline">
<Fill className="fill" />
</Outline>
</Label>
</Container>
);
};
RadioButton.propTypes = {
id: PropTypes.string.isRequired,
};
export default RadioButton;
And styles:
import styled from "#emotion/styled";
export const Container = styled.div(() => ({}));
export const Label = styled.label(() => ({
cursor: "pointer",
}));
export const Outline = styled.span(({ theme }) => ({
border: `3px solid ${theme.colors.Blue}`,
width: "24px",
height: "24px",
borderRadius: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
}));
export const Fill = styled.span(({ theme }) => ({
width: "14px",
height: "14px",
margin: "auto",
borderRadius: "50%",
background: "red",
}));
export const Input = styled.input(({ theme }) => ({
opacity: 0,
position: "absolute",
"&: checked + .fill": {
background: theme.colors.Blue,
},
}));
As you can see when the Input is changed to "checked" the background of the fill span should change but it doesn't.
Emotion Styled Components:
https://emotion.sh/docs/styled
I think the issue is come from this selector
&: checked + .fill: {
background: theme.colors.Blue,
},
Because Input and .fill are not in same level.
I've made a simple demo for it, please check
https://codepen.io/doichithhe/pen/bGEQwLJ
Video reproducing the error/missing css
I know there are already dated versions of this question on stack overflow, like React + Material-UI - Warning: Prop className did not match.
However, when I attempt to google and research people's solutions, there is just no clear answer. Any answers I could find don't match my stack.
My stack:
Node JS
Next JS
Material UI
And from what I could glean from answers to questions like next.js & material-ui - getting them to work is that there is some measure of incompatibility when it comes to Next JS and Material UI.
Code-wise, here is my Appbar component. Initially I was not exporting my useStyles object, but I ended up doing it in a pitiful attempt to follow along with Material UI's express guide to "server rendering". There has to be a fix that doesn't involve changing like every file I have.
import React from 'react';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import IconButton from '#material-ui/core/IconButton';
import Typography from '#material-ui/core/Typography';
import InputBase from '#material-ui/core/InputBase';
import { fade } from '#material-ui/core/styles/colorManipulator';
import { makeStyles } from '#material-ui/core/styles';
import MenuIcon from '#material-ui/icons/Menu';
import SearchIcon from '#material-ui/icons/Search';
import {connectSearchBox} from 'react-instantsearch-dom';
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
display: 'none',
[theme.breakpoints.up('sm')]: {
display: 'block',
},
},
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: fade(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: fade(theme.palette.common.white, 0.25),
},
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing(1),
width: 'auto',
},
},
searchIcon: {
width: theme.spacing(7),
height: '100%',
position: 'absolute',
pointerEvents: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
inputRoot: {
color: 'inherit',
},
inputInput: {
padding: theme.spacing(1, 1, 1, 7),
transition: theme.transitions.create('width'),
width: '100%',
[theme.breakpoints.up('sm')]: {
width: 300,
'&:focus': {
width: 400,
},
},
}
}));
function SearchBox({currentRefinement, refine}){
const classes = useStyles();
return(
<InputBase
type="search"
value={currentRefinement}
onChange={event => refine(event.currentTarget.value)}
placeholder="Search by state, park name, keywords..."
classes = {{
root: classes.inputRoot,
input: classes.inputInput,
}}
/>
)
}
const CustomSearchBox = connectSearchBox(SearchBox);
function SearchAppBar() {
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static" color="primary">
<Toolbar>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="Open drawer"
>
<MenuIcon />
</IconButton>
<Typography className={classes.title} variant="h6" noWrap>
Title
</Typography>
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<CustomSearchBox/>
</div>
</Toolbar>
</AppBar>
</div>
);
}
export {SearchAppBar, useStyles};
I was just digging around random parts of the internet looking for answers to this error, accidentally npm install'ed styled-components as part of this answer on a Github issue (because they have a very similar object to the counterpart in Material UI called ServerStyleSheet (vs Material UI's ServerStyleSheets), so obviously that didn't work.
BUT......... I ended up just using the ServerStyleSheet fix to try to make it agreeable with Material UI's ServerStyleSheets object, and ended up with this new _document.js.
I'm still dumbfounded I was able to refactor an entirely different fix to make this work but I tested it and it fixes the problem entirely, now reloads are fine.
import Document, { Html, Head, Main, NextScript } from 'next/document';
import {ServerStyleSheets} from "#material-ui/styles";
class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
try{
ctx.renderPage = () => originalRenderPage({
enhanceApp: App => props => sheet.collect(<App {...props}/>)
});
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
}
} finally {
ctx.renderPage(sheet)
}
}
render() {
return (
<Html>
<Head>
<link rel="shortcut icon" type="image/png" href="../static/favicon.ico"/>
<style>{`body { margin: 0 } /* custom! */`}</style>
<meta name="viewport"content="width=device-width, initial-scale=1.0" />
</Head>
<body className="custom_class">
<Main />
<NextScript />
</body>
</Html>
)}
}
export default MyDocument;
If you wanna see how crazy it was that it worked, here is the fix for the same error in styled-components:
export default MyDocument;
import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
static async getInitialProps (ctx) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props => sheet.collectStyles(<App {...props} />)
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
}
} finally {
sheet.seal()
}
}
}
I hope this helped someone with the mess that is Material-UI + Next.js
For my part, adding { name: "MuiExample_Component" } in the makeStyle hook works for some reason. I found this solution while digging on internet. I would appreciate if someone could tell me if it's a good solution or not, but here is the code :
const useStyles = makeStyles({
card: {
backgroundColor: "#f7f7f7",
width: "33%",
},
title: {
color: "#0ab5db",
fontWeight: "bold",
},
description: {
fontSize: "1em"
}
}, { name: "MuiExample_Component" });
I have a Material UI TextField component that needs some color customization for :
error
focused
I am using #material-ui/core 3.8.1 and it's <TextField /> component.
I want to avoid having to use <MuiThemeProvider>
This is how I have tried based on the recommendation here for the Material-UI <Input /> component and the answer here
Reproduction: https://codesandbox.io/s/q9yj0y74z6
As already stated in the comments, you need to override the classes property.
The &$ syntax refers to a class in the same stylesheet.
You are nearly there with your example but you need to pass in an error class.
const styles = muiTheme => ({
label: {
"&$focusedLabel": {
color: "cyan"
},
"&$erroredLabel": {
color: "orange"
}
},
focusedLabel: {},
erroredLabel: {},
underline: {
"&$error:after": {
borderBottomColor: "orange"
},
"&:after": {
borderBottom: `2px solid cyan`
}
},
error: {}
});
<TextFieldMui
InputLabelProps={{
classes: {
root: classes.label,
focused: classes.focusedLabel,
error: classes.erroredLabel
},
}}
InputProps={{
classes: {
root: classes.underline,
error: classes.error
}
}}
{...props}
/>
https://codesandbox.io/s/9z70kz5vnr
for Disable label and for input text color change example.
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const useStyles = makeStyles((theme) => ({
container: {
display: "flex",
flexWrap: "wrap"
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1)
},
label: {
"&$disabled": {
color: "black"
}
},
inputRoot: {
"&$disabled": {
color: "red"
}
},
disabled: {}
}));
export default function OutlinedTextFields() {
const classes = useStyles();
return (
<form className={classes.container} noValidate autoComplete="off">
<TextField
disabled
id="outlined-disabled"
label="Disabled"
defaultValue="Hello World"
InputProps={{
classes: {
root: classes.inputRoot,
disabled: classes.disabled
}
}}
InputLabelProps={{
classes: {
root: classes.label,
disabled: classes.disabled
}
}}
margin="normal"
variant="outlined"
/>
</form>
);
}