I need to make a stylized version of material-ui select component.
What i have now is:
import { Select } from '#material-ui/core';
import type { SelectProps } from '#material-ui/core';
import styled from 'styled-components';
const menuProps = {
getContentAnchorEl: null,
anchorOrigin: {
vertical: "bottom",
horizontal: "left",
},
PopoverClasses: {
// pass only classnames
}
}
const StyledSelect = styled(Select)<SelectProps>`
... some styles
`;
const Select: React.FC<SelectProps> = (props) => {
return <StyledSelect MenuProps={menuProps} {...props}/>
};
I need to pass styles(NOT CLASSES) to popover part of Select to make a margin between popover and input.
I tried everything and found only way to pass classes to them.
But I can't use global classes o module classes because of project restrictions, only pass them in js.
Any ideas?
If you use the disablePortal: true menu prop, it will cause the Popover to be a descendant of the Select's root element in the DOM. This allows you to target it like the following:
const Select = styled(MuiSelect)`
.MuiPopover-paper {
margin-top: 3px;
}
`;
Here's a full working example:
import React from "react";
import InputLabel from "#material-ui/core/InputLabel";
import MenuItem from "#material-ui/core/MenuItem";
import MuiFormControl from "#material-ui/core/FormControl";
import MuiSelect from "#material-ui/core/Select";
import styled from "styled-components";
import { StylesProvider } from "#material-ui/core/styles";
const FormControl = styled(MuiFormControl)`
margin: 8px;
min-width: 120px;
`;
const Select = styled(MuiSelect)`
.MuiPopover-paper {
margin-top: 3px;
}
`;
export default function SimpleSelect() {
const [age, setAge] = React.useState("");
const handleChange = event => {
setAge(event.target.value);
};
const menuProps = {
getContentAnchorEl: null,
anchorOrigin: {
vertical: "bottom",
horizontal: "left"
},
disablePortal: true
};
return (
<StylesProvider injectFirst>
<div>
<FormControl>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
onChange={handleChange}
MenuProps={menuProps}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</div>
</StylesProvider>
);
}
Related
There are multiple components in child component and can I apply styling to a specific component that is in child component from parent component?
App/index.jsx
import React from "react";
import { Container, StyledMenu } from "./styles";
const App = ({ className }) => {
return (
<Container className={className}>
<h1>this is a demo</h1>
<StyledMenu />
</Container>
);
};
export default App;
App/styles.js
import styled from "styled-components";
import Demo from "../Demo";
export const Container = styled.div`
background-color: pink;
padding: 20px;
`;
Container.displayName = "Container";
export const StyledMenu = styled(Demo)`
& .MuiPaper-root {
width: 300px;
}
`;
StyledMenu.displayName = "StyledMenu";
Demo/index.jsx
import * as React from "react";
import Button from "#mui/material/Button";
// import Menu from "#mui/material/Menu";
import MenuItem from "#mui/material/MenuItem";
import { MenuDisplay } from "./styles";
export default function BasicMenu({ className }) {
const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div className={className}>
<Button
id="basic-button"
aria-controls={open ? "basic-menu" : undefined}
aria-haspopup="true"
aria-expanded={open ? "true" : undefined}
onClick={handleClick}
>
Dashboard
</Button>
<MenuDisplay
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
MenuListProps={{
"aria-labelledby": "basic-button"
}}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</MenuDisplay>
</div>
);
}
Demo/styles.js
import styled from "styled-components";
import Menu from "#mui/material/Menu";
export const MenuDisplay = styled(Menu)`
background-color: green;
`;
MenuDisplay.displayName = "MenuDisplay";
I like to apply width: 300px for the Menu component (where it is a dropdown menu) in Demo/index.jsx from App/style.js.
Is that possible?
Here is codesandbox for demo
Here is Menu component from mui doc
Attempts
I imported MenuDisplay (that's in Demo/styles.js) inside App/styles.js
import styled from "styled-components";
import Demo from "../Demo";
import { MenuDisplay } from "../Demo/styles";
export const Container = styled.div`
background-color: pink;
padding: 20px;
`;
Container.displayName = "Container";
export const StyledMenu = styled(Demo)`
${MenuDisplay} & {
& .MuiPaper-root {
width: 300px;
}
}
`;
StyledMenu.displayName = "StyledMenu";
This didn't work
To apply css to your child component, define width in the Demo/styles.js
export const MenuDisplay = styled(Menu)width: 300px;;
For more detail see the replay https://dashboard.testwise.io/replays/bRJwLQfxEcG of your issue.
I'm trying to apply background-color when MenuItem component has the selected={true}
also I'd like to apply a style when MenuItem component hovered.
How can I do that?
import * as React from "react";
import Paper from "#mui/material/Paper";
import MenuList from "#mui/material/MenuList";
import Stack from "#mui/material/Stack";
import { MenuItem } from "./styles";
export default function MenuListComposition() {
return (
<Stack direction="row" spacing={2}>
<Paper>
<MenuList>
<MenuItem selected={true}>Profile</MenuItem>
<MenuItem>My account</MenuItem>
<MenuItem>Logout</MenuItem>
</MenuList>
</Paper>
</Stack>
);
}
styles.js
import styled from "styled-components";
import { default as MuiMenuItem } from "#mui/material/MenuItem";
export const MenuItem = styled(MuiMenuItem)`
.MuiMenuItem-root {
color: blue;
padding: 10px 0;
& .Mui-selected {
background-color: red;
}
&:hover {
background-color: green;
}
}
`;
Solution with styled-components
If you need to use styled-components instead of styled from Mui, you can do it.
export const MenuItem = styled(MuiMenuItem)`
color: blue;
padding: 20px;
&.Mui-selected {
background-color: red;
}
&:hover {
background-color: green;
}
`;
You can fix the problem by importing styled from material and adapt the format, like this:
import { MenuItem as MuiMenuItem, styled } from "#mui/material";
export const MenuItem = styled(MuiMenuItem)({
"&.MuiMenuItem-root": {
color: "blue",
padding: "10px",
"&.Mui-selected": {
backgroundColor: "red"
},
"&:hover": {
backgroundColor: "green"
}
}
});
and then I assume that what you want is to change the color only of the selected MenuItem and you can create the array of objects like in the code so you do not repeat to much code.
import React, { useState } from "react";
import Paper from "#mui/material/Paper";
import MenuList from "#mui/material/MenuList";
import Stack from "#mui/material/Stack";
import { MenuItem } from "./styles";
const ITEMS = [
{ index: 1, title: "Profile" },
{ index: 2, title: "My Account" },
{ index: 3, title: "Logout" }
];
export default function MenuListComposition() {
const [selectedIndex, setSelectedIndex] = useState(1);
const handleListItemClick = (event, index) => {
setSelectedIndex(index);
};
return (
<Stack direction="row" spacing={2}>
<Paper>
<MenuList variant="menu">
{ITEMS.map(({ index, title }) => (
<MenuItem
key={index}
onClick={(event) => handleListItemClick(event, index)}
selected={selectedIndex === index}
>
{title}
</MenuItem>
))}
</MenuList>
</Paper>
</Stack>
);
}
You need to make some configuration changes, because MUI uses 'emotion' as a default style engine, otherwise they would conflict with each other.
https://mui.com/material-ui/guides/styled-engine/#how-to-switch-to-styled-components
here is a working example you need to compare dependencies that are recommended for usage with react
I would like to make select dropdown using by InputBase component. The select box shows correctly, but dropdown options doesn't show when I click the field. I had tried other inputComponent like input, it's work fine.
I want the label above on the field and I know that I can use native select to make this. However, I want to share same styles between these components.
Does anyone know how to use input base to make select component?
The code provided below:
import React from "react";
import "./styles.css";
import {
FormControl,
InputLabel,
InputBase,
MenuItem
} from "#material-ui/core";
import { withStyles, fade } from "#material-ui/core/styles";
export default function App() {
const BootstrapInput = withStyles((theme) => ({
root: {
"label + &": {
marginTop: "20px"
}
},
input: {
position: "relative",
backgroundColor: theme.palette.common.white,
border: "1px solid #ccc",
fontSize: 14,
width: "380px",
height: "12px",
padding: "10px 12px",
transition: theme.transitions.create(["border-color", "box-shadow"]),
"&:focus": {
boxShadow: `${fade(theme.palette.primary.main, 0.25)} 0 0 0 0.2rem`,
borderColor: theme.palette.primary.main
}
}
}))(InputBase);
return (
<div className="App">
<FormControl>
<InputLabel shrink htmlFor="personalTitle">
Age
</InputLabel>
<BootstrapInput inputComponent="select" name="personalTitle">
<MenuItem>20</MenuItem>
<MenuItem>30</MenuItem>
<MenuItem>40</MenuItem>
</BootstrapInput>
</FormControl>
</div>
);
}
CodeSandbox link:
https://codesandbox.io/s/select-on-inputbase-0ufes?file=/src/App.js:0-1209
You Can use material-ui select component to manage select box easily. You can check more details using below link
https://material-ui.com/components/selects/
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import InputLabel from '#material-ui/core/InputLabel';
import MenuItem from '#material-ui/core/MenuItem';
import FormHelperText from '#material-ui/core/FormHelperText';
import FormControl from '#material-ui/core/FormControl';
import Select from '#material-ui/core/Select';
const useStyles = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
export default function SimpleSelect() {
const classes = useStyles();
const [age, setAge] = React.useState('');
const handleChange = (event) => {
setAge(event.target.value);
};
return (
<div>
<FormControl className={classes.formControl}>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
onChange={handleChange}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</div>
)
}
I am trying to align a Placeholder to be centered within the Text-Field. Is there a way to do this? applying text-align: center to the input is not centering the placeholder.
You can use the &::placeholder pseudoselector on input classname like below
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const useStyles = makeStyles(theme => ({
input: {
"&::placeholder": {
color: "red",
textAlign: "center"
}
}
}));
export default function Inputs() {
const classes = useStyles();
return (
<TextField
placeholder="Placeholder"
InputProps={{ classes: { input: classes.input } }}
/>
);
}
A working sandbox project link
How can I change the color of the label which is showing in grey color? Depending on the theme of the page I have to change the color of the label or even if I remove the override color it should work.
Example remove the default one:
.MuiFormLabel-root {
/* color: rgba(0, 0, 0, 0.54); //default in the browser
}
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
root: {
"& .MuiFormLabel-root": {
color: "white"
}
}
}));
export default function SelectBox(props) {
const classes = useStyles();
return (
<FormControl
style={{ width: '100%' }}>
<InputLabel shrink className={classes.root}>
{props.label}
</InputLabel>
</FormControl>
)
}
You can pass the classes object and overirde the root which corresponds to .MuiInputLabel-root
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import { FormControl } from "#material-ui/core";
import { InputLabel } from "#material-ui/core";
const useStyles = makeStyles(theme => ({
root: {
color: "red"
}
}));
export default function SelectBox(props) {
const classes = useStyles();
return (
<FormControl style={{ width: "100%" }}>
<InputLabel shrink classes={{ root: classes.root }}>
{props.label}
</InputLabel>
</FormControl>
);
}
To have result like this -
Working sandbox here - https://codesandbox.io/s/update-input-label-color-kzew2?file=/demo.js:0-513