Material UI's CardHeader action styling - javascript

I have a CardHeader which has a dropdown within it, I use the to select various options for the table, however currently it looks awful and im not entirely sure how to style it in a more appropriate way, I am using material UI's framework to do this.
formControl: {
flexBasis: 'auto',
position: 'relative'
},
<CardHeader className={classes.cardHeader} classes={{ title: classes.cardHeader }}
avatar={
<Home />
}
action={
<FormControl className={classes.formControl}>
<InputLabel htmlFor="Available Contracts" style={{ marginRight: 20, color: 'white' }}>Contract Type</InputLabel>
<Select
value={contractType.contractObject}
onChange={handleChange}
inputProps={{
name: 'contractObject',
id: 'contractObject',
}}
>
<MenuItem value={10}>Local Contract</MenuItem>
<MenuItem value={20}>Framework Contract</MenuItem>
</Select>
</FormControl>
}
/>
A screen shot below of the table
As you can see the Contract Type is currently on the right, I would like this on the left next to the Home icon if possible, any ideas?

The 'Card' component has further sub components - 'CardHeader', 'CardContent'.
To style the CardHeader for instances, the API indicates that you can do the following:
import React from 'react';
import { makeStyles } from '#material-ui/styles';
import {
Card, CardContent, CardHeader, Divider
} from '#material-ui/core';
const useStyles = makeStyles(theme => ({
action: {
margin: 0
}
}))
const CustomerInfoCards = ({ customer }) => {
const classes = useStyles();
return (
<Card>
<CardHeader
action={
<p>{customer._id}</p>
}
classes={{ action: classes.action }}
className={classes.action}
subheader={customer.email}
title={customer.name}
/>
<Divider />
<CardContent>
<h2>Some text</h2>
</CardContent>
</Card>
)
}
export default CustomerInfoCards
Main thing here is classes={{ action: classes.action }} - which removes the default margin top and right of 8px for the action prop.
Take a look at the API link above to know the various CSS exposed by material-ui and have fun styling!

In your styling for formControl add a new property flex and have its value as flex: "0 1 auto",
formControl: {
flexBasis: 'auto',
position: 'relative',
flexgrow: '1',
flex: '0 1 auto',
}
Hope this helps. flex usually adjust the component to relative right of the earlier component.
Read more: CSS flex on W3Schools

Related

Material UI - Widget component issue

I'm using the autocomplete component, and finally, I finished the feature as I wanted but since this component is rendered in other pages as a widget I'm getting some weird issues with the styling since the page that renders my component is overriding/adding styles they have globally.
This is how it looks in my local:
And this is how it looks when I deploy it and I check it on one of the pages:
I've been working on this the whole day without success, but I found that the styles that are braking my component are these ones:
I'm using these styles to hide the outlined style of the textfield
const useStyles = makeStyles(theme => ({
root: {
"& .MuiOutlinedInput-root .MuiOutlinedInput-notchedOutline": {
border: 'none !important',
outline: 'none'
},
"& .MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline": {
border: 'none !important',
outline: 'none'
}
}
}));
And this is how my autocomplete components look like
<Autocomplete
id="listings-filter"
multiple
disableCloseOnSelect={true}
freeSolo
clearOnBlur={false}
limitTags={5}
disableCloseOnSelect={true}
blurOnSelect={false}
options={options}
groupBy={(option) => option.key }
onInputChange={handleInputChange}
onChange={handleOptionSelection}
disableCloseOnSelect
getOptionLabel={(option) => option.value}
renderOption={(option, { selected }) => (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option.value}
</React.Fragment>
)}
style={{ width: "100%" }}
renderInput={(params) => (
<TextField
id='autocomplete-input'
{...params}
margin={'dense'}
className={autocompleteClasses.root}
InputLabelProps={{
shrink: true
}}
variant='outlined'
label="Search listings by address, MLS or property name"
placeholder='Type the address, MLS or property name'
/>
)}
/>
I tried to add inputProps to the textfield and give the styles there but this didn't work at all, also tried adding the styles on the makeStyles part but I'm confused about how to get into the exact class I need with MUI style overrides, and since this looks that is related with generic input component and not with a material UI component, made me confuse even more.
I don't know if this is possible with react or I have to build a CSS file to be able to avoid this behavior. Really appreciate any help!
EDIT:
Also tried using the inputProps of the TextField component leaning on another stackoverflow question but that make the autocomplete component to crash when the input is clicked with the following error -> Uncaught TypeError: Cannot read property 'focus' of null
const useStyles = makeStyles(theme => ({
root: {
"& .MuiOutlinedInput-root .MuiOutlinedInput-notchedOutline": {
border: 'none !important',
outline: 'none'
},
"& .MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline": {
border: 'none !important',
outline: 'none'
}
},
input: {
border: '10 !important',
borderColor: 'red',
boxShadow: 'unset !important',
color: 'red'
}
}));
renderInput={(params) => (
<TextField
id='autocomplete-input'
{...params}
margin={'dense'}
className={autocompleteClasses.root}
InputLabelProps={{
...params.InputLabelProps,
shrink: true
}}
inputProps={{
...params.InputProps,
classes:{
root: autocompleteClasses.input,
}
}}
variant='outlined'
label="Search listings by address, MLS or property name"
placeholder='Type the address, MLS or property name'
/>
)}
I solved the issue by creating a scss file:
.autocomplete-component > div > div > input {
border: 0px !important;
border-color: white !important;
box-shadow: unset !important;
-webkit-box-shadow: unset !important
}
and used as a className on the autocomplete component:
import './listingStyles.scss'
<Autocomplete
id="listings-filter"
className={'autocomplete-component'}
multiple
disableCloseOnSelect={true}
freeSolo
clearOnBlur={false}
limitTags={5}
disableCloseOnSelect={true}
blurOnSelect={false}
options={options}
groupBy={(option) => option.key }
onInputChange={handleInputChange}
onChange={handleOptionSelection}
disableCloseOnSelect
... />
Hope this is useful for anyone!

why Href attribute can't redirect to the respective js file?

why my button is not redirecting to the respective .js file?
Basically i am using Button with href tage where href="signup.js" and signup.js file is present in my project.
Can we use href tag to link a ".js" file properly and redirect properly...
Button has been imported from react-bootstrap so what changes should be madeso user click on Button and go to signup.js file?
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import { Button } from 'react-bootstrap';
import Typography from '../components/Typography';
import ProductHeroLayout from './ProductHeroLayout';
const backgroundImage =
'https://thumbs.dreamstime.com/z/female-boss-online-conference-meeting-woman-crossed-hands-office-desk-front-laptop-student-teaches-exam-139215819.jpg';
const styles = (theme) => ({
background: {
backgroundImage: `url(${backgroundImage})`,
backgroundColor: '#7fc7d9', // Average color of the background image.
backgroundPosition: 'center',
},
button: {
minWidth: 200,
},
h5: {
marginBottom: theme.spacing(4),
marginTop: theme.spacing(4),
[theme.breakpoints.up('sm')]: {
marginTop: theme.spacing(10),
},
},
more: {
marginTop: theme.spacing(2),
},
});
function ProductHero(props) {
const { classes } = props;
return (
<ProductHeroLayout backgroundClassName={classes.background}>
{/* Increase the network loading priority of the background image. */}
<img style={{ display: 'none' }} src={backgroundImage} alt="increase priority" />
<Typography color="inherit" align="center" variant="h2" marked="center">
Upgrade your knowledge
</Typography>
<Typography color="inherit" align="center" variant="h5" className={classes.h5}>
Test Your Skills.
</Typography>
<Button
color="secondary"
variant="contained"
size="large"
className={classes.button}
component="a"
href="SignUp.js"
>
User Registeration
</Button>
<Typography variant="body2" color="inherit" className={classes.more}>
Be Digital
</Typography>
</ProductHeroLayout>
);
}
ProductHero.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ProductHero);

How to embed checkbox with label in Card Media?

I tried to code this thing. But the CardMedia will not go together with the checkbox. so responsive is a failure.
<Card>
<CardMedia
component='img'
alt=''
height='160'
image=''
title='Image'
style={{ backgroundColor: '#DEDBDB',
position: 'relative' }}
/>
{/*<input type='checkbox' id='select'*/}
{/* style={{ position: 'absolute', marginLeft: '20%', marginTop: '-2%'}}*/}
{/*/>*/}
{/*<label htmlFor='select'*/}
{/* style={{ position: 'absolute', marginLeft: '21%', marginTop: '-2.15%'}}*/}
{/*>選択</label>*/}
<Box mt={-6} ml={45}>
<span><Checkbox inputProps={{ 'aria-label': 'uncontrolled-checkbox' }} /></span>
</Box>
</Card>
I tried also the FormControlLabel for this so that the label and checkbox will be together and style it with position: absolute and some margins so that the result will be like this.
But the problem is that it is not responsive and if using box label disappear.
Thanks.
Ciao, your problem is connected to the zIndex of the label in FormControlLabel. Infact, if you inspect the page you can see the label present on DOM but invisible (maybe because on CardMedia the image is always on top, but this is my personal opinion).
To solve this problem, you can override the style of the label associated to the FormControlLabel. This is a codesandbox example.
At first I defined a CustomCheckbox:
const CustomCheckbox = withStyles((theme) => ({
root: {
// checkbox style example
// color: "#000000"
// '&$checked': {
// color: "#000000",
// },
},
checked: {}
}))((props) => <Checkbox color="default" {...props} />);
Then, I used it into Card:
<Box mt={-6} ml={45}>
<span>
<FormControlLabel
control={
<CustomCheckbox
checked={cheboxChecked}
onChange={handleChange}
name="toggleFavorite"
/>
}
label="Checkbox label" // label value
classes={{
label: styles.formcontrollabel // label class overriding
}}
/>
</span>
</Box>
And finally in makeStyles I made the override:
const useStyles = makeStyles(() => ({
formcontrollabel: {
"&.MuiFormControlLabel-label": {
zIndex: 1
}
}
}));
The result is:
The label is responsive also (in this case "label" word goes on new line if you reduce screen width) as long as possible (if you continue to reduce screen width, label will be cutted). But this is normal (because you defined Box like <Box mt={-6} ml={45}>). If you don't like this behaviour, you could use a Hidden component to hidden checkbox and label if screen goes under a certain breakpoint like:
<Hidden smDown> // if screen width goes under smDown breakpoint, the Hidden content will be hided
...
</Hidden>

React Material UI CardHeader title overflow with dots

How can I properly add dots the the title in my Cardheader if it exceeds the parents width (Card width). So far I have done this:
card: {
width: 275,
display: "flex"
},
overflowWithDots: {
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
width: '100px'
}
<Card className={classes.card}>
<CardHeader
title={
<Typography gutterBottom variant="h6" component="h4" className={classes.overflowWithDots}>
{movie.title}
</Typography>
}
/>
This works in a way, but I have to tell the class to have a width of 100px until it adds the dots. I need to add the dots if it exceeds the parents width.
Problem
As I understand it you are limiting the size of the Card, in this case, you are not being able to place the ellipsis due to the way the CardHeader is rendered in the html.
The CardHeader component is rendered with a "root" element and a "content" element. See below:
Typography has a built-in prop to adding dots noWrap. For the noWrap property to work correctly, we have the following approaches.
Solution 1
CardHeader's default behavior is to use flex. If you don't need it use flex:
...
cardHeader: {
display: "block",
overflow: "hidden"
}
...
<CardHeader
className={classes.cardHeader}
title={
<Typography noWrap gutterBottom variant="h6" component="h4">
A world wide web - the revolution
</Typography>
}
/>
...
Solution 2
If you need to keep CardHeader with flex behavior, in this case, the overflow needs to be applied to the root and content. To reach the elements use the CardHeader classes property passing the generated class to the content prop.
...
cardHeaderRoot: {
overflow: "hidden"
},
cardHeaderContent: {
overflow: "hidden"
}
...
<CardHeader
classes={{
root: classes.cardHeaderRoot,
content: classes.cardHeaderContent
}}
title={
<Typography noWrap gutterBottom variant="h6" component="h4">
A world wide web - the revolution
</Typography>
}
/>
...
Here's an example in the sandbox.
Atention
Be aware that by modifying the default behavior of how components are rendered, some side effects may occur in your entire component tree.
Anyway
If you still have any problems let us know.
Although this solution works, if you are using mui v5, this is how you can do it using the sx prop described here. You can set the .MuiCardHeader-content style and titleTypographyProps prop to style the title. I added an action button and subheader as an extra example.
import React from "react";
import { Card, CardHeader, IconButton } from "#mui/material";
import { MoreVert as MoreVertIcon } from "#mui/icons-material";
const SimpleCard = () => (
<Card sx={{ width: "275px", display: "flex" }}>
<CardHeader
sx={{
display: "flex",
overflow: "hidden",
"& .MuiCardHeader-content": {
overflow: "hidden"
}
}}
title={"A very long title coooooooooooooool"}
titleTypographyProps={{ noWrap: true }}
subheader={"ps long subheader cooooooooooooool"}
subheaderTypographyProps={{ noWrap: true }}
action={
<IconButton>
<MoreVertIcon />
</IconButton>
}
/>
</Card>
);
export default SimpleCard;
Here's the sandbox to mess around with.
Typography has a built-in prop to adding dots. You can simply add noWrap prop to Typography. It will add dots in header text and according to the parent component width.
<Card className={classes.card}>
<CardHeader
title={
<Typography gutterBottom noWrap variant="h6" component="h4">
{movie.title}
</Typography>
}
/>
/>

Is there a way to control where a nested Material UI select in a popper gets mounted in the DOM?

I am trying to place a select menu in a Popper. The issue I'm running into is that the nested select menu wants to mount the popup that comes out of it on the body as a neighbor and not a child of popper. This causes the clickaway event to fire. Here's the code to reproduce it:
import React, { useState } from "react";
import "./styles.css";
import Popper from "#material-ui/core/Popper";
import TextField from "#material-ui/core/TextField";
import MenuItem from "#material-ui/core/MenuItem";
import ClickAwayListener from "#material-ui/core/ClickAwayListener";
export default function App() {
const [popperAnc, setPopperAnc] = useState(null);
const popperOpen = Boolean(popperAnc);
return (
<div className="App">
<div
onClick={e => {
setPopperAnc(e.currentTarget);
}}
>
Popper anchor
</div>
<div style={{ position: "absolute" }}>
<Popper open={popperOpen} anchorEl={popperAnc}>
<ClickAwayListener
onClickAway={e => {
setPopperAnc(null);
}}
>
<TextField select label="Menu">
<MenuItem value="select1">Select me!</MenuItem>
</TextField>
</ClickAwayListener>
</Popper>
</div>
</div>
);
}
https://codesandbox.io/s/strange-bassi-liwdc?file=/src/App.js:0-1013
If you need to use Select - just use it (don't use TextField, it doesn't make any sense).
You need to make sure that the second popper is not rendered as a portal (you need to set disabledPortal on the MenuProps of the Select element.
You need to tell the new menu where to position itself and what will be it's size.
<div style={{ position: "absolute" }}>
<Popper open={popperOpen} anchorEl={popperAnc}>
<ClickAwayListener
onClickAway={e => {
console.log("click away");
setPopperAnc(null);
}}
>
<div>
<div>Wow</div>
<Select
label="Menu"
MenuProps={{
disablePortal: true,
anchorEl: this,
style: { marginTop: "20px", width: "150px", height: "200px" }
}}
>
<MenuItem value="select1">Select me!</MenuItem>
</Select>
</div>
</ClickAwayListener>
</Popper>
</div>
Here is a working example: https://codesandbox.io/s/mui-nested-popper-4uu5l?file=/src/App.js

Categories

Resources