Dynamically drawing multiple borders with MUI - css

I am using React 17 and MUI 5.6. I have a component that needs to add new borders to the parent container based on user input. I found some non-MUI CSS tutorials for achieving what I want, but their borders are statically coded in CSS and not added on user demand.
Here's a working sandbox for one border. Would appreciate any help on how to support multiple borders.

This should help to solve your problem. Here is the working code, user can decide color with buttons but you can implement same solution also with dropdown options. https://codesandbox.io/embed/wonderful-worker-g8fzyi?fontsize=14&hidenavigation=1&theme=dark
import { Box } from "#mui/material";
import Button from "#mui/material/Button";
import { useState } from "react";
import "./styles.css";
export default function App() {
const [colors, setColors] = useState([]);
const [pixel, setPixel] = useState(6);
const addColor = async (color) => {
setPixel(pixel + 2);
let randomColor = `0 0 0 ${pixel}px ${color}`;
setColors([...colors, randomColor]);
};
return (
<div
style={{
width: "100vw",
height: "100vh",
display: "flex",
justifyContent: "center",
alignItems: "center",
flexDirection: "column"
}}
>
<Box
sx={{
width: "50%",
height: "20%",
border: 3,
boxShadow: colors.join(",")
}}
></Box>
<div style={{ marginTop: 100 }}>
<Button onClick={() => addColor("#FFFF00")}>Yellow</Button>
<Button onClick={() => addColor("#FF002B")}>Red</Button>
<Button onClick={() => addColor("#0000FF")}>Blue</Button>
<Button onClick={() => addColor("#2BFF00")}>Green</Button>
</div>
</div>
);
}

Related

Reduce the left padding of a dropdown button

I would like to make a row, where there is a title on the left and several buttons and a dropdown on the right.
Now, I would like to make the distance between Button 2 and the dropdown (e.g., Cat) smaller.
I guess we need to overwrite the left padding of the button inside the dropdown. I tried to put marginLeft: "-10px" and paddingLeft: "-10px" in the style of FluentProvider or Dropdown, but it did not work.
Could anyone help?
CodeSandbox: https://codesandbox.io/s/charming-ritchie-40tyj1?file=/example.tsx
import {
FluentProvider,
webLightTheme,
makeStyles,
shorthands
} from "#fluentui/react-components";
import {
Dropdown,
Option,
OptionGroup,
DropdownProps
} from "#fluentui/react-components/unstable";
import { CommandBarButton } from "#fluentui/react/lib/Button";
import * as React from "react";
import { initializeIcons } from "#fluentui/react/lib/Icons";
initializeIcons(/* optional base url */);
const useStyles = makeStyles({
dropdown: {
// removes default border around the dropdown
...shorthands.borderWidth(0),
// removes the blue bottom border when the dropdown is open
"::after": {
borderBottomWidth: 0
}
}
});
export const Grouped = (props: Partial<DropdownProps>) => {
const land = ["Cat", "Dog", "Ferret", "Hamster"];
const styles = useStyles();
return (
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div style={{ flexBasis: "auto" }}>
<span style={{ lineHeight: "2.7rem" }}>Title</span>
</div>
<div style={{ display: "flex" }}>
<CommandBarButton
styles={{ root: { height: 44 } }}
iconProps={{ iconName: "Back" }}
ariaLabel="Back"
text="Button 1"
disabled={false}
checked={false}
/>
<CommandBarButton
styles={{ root: { height: 44 } }}
iconProps={{ iconName: "Up" }}
text="Button 2"
disabled={false}
checked={false}
/>
<FluentProvider style={{ display: "flex" }} theme={webLightTheme}>
<Dropdown
className={styles.dropdown}
style={{
minWidth: "auto",
display: "flex"
}}
defaultSelectedOptions={["Cat"]}
{...props}
>
<OptionGroup label="Land">
{land.map((option) => (
<Option key={option} disabled={option === "Ferret"}>
{option}
</Option>
))}
</OptionGroup>
</Dropdown>
</FluentProvider>
</div>
</div>
);
};
There might be many approaches, perhaps try specify styles for Dropdown button in makeStyles and pass it to the button. The value in below example can be further adjusted to suit the use case.
Forked demo with modification: codesandbox
const useStyles = makeStyles({
dropdown: {
// removes default border around the dropdown
...shorthands.borderWidth(0),
// removes the blue bottom border when the dropdown is open
"::after": {
borderBottomWidth: 0
}
},
// 👇 styles for the dropdown button
button: {
paddingLeft: "0px"
}
});
Pass the styles to the button of Dropdown:
<Dropdown
className={styles.dropdown}
style={{
minWidth: "auto",
display: "flex",
}}
defaultSelectedOptions={["Cat"]}
// 👇 pass styles to the button
button={{ className: styles.button }}
{...props}
>
...
You cant assign negative values to the padding. Try the same idea but on Button2, but with negative margin-right: -10px You then might need to move the whole navbar 10px to the right, since it wont stay aligned as it is now. You can fix it by doing the same on navbar content.
You might also try overriding padding with padding-left: 0 !important

Override delete icon margin styles in MUI Chip component

I'm using V4 MUI Chip component with size : 'small' and variant: 'outlined' with a deleteIcon specified.
https://v4.mui.com/components/chips/
I'd like to override the margin-right property of the deleteIcon but I'm having trouble getting the right specificity, because MUI is applying more specific styles.
The following styles are applied to the delete icon by MUI:
.MuiChip-outlined-253 .MuiChip-deleteIconSmall-267 {
margin-right: 3px;
}
.MuiChip-outlined-253 .MuiChip-deleteIcon-266 {
margin-right: 5px;
}
How do I apply a style to override the margin-right of the deleteIcon and set it to e.g. '10px'?
You can use the class .MuiChip-deleteIcon based on the Chip api documentation (https://v4.mui.com/api/chip/)
Here is a working codesandbox to play with (has for the both default and outlined variants).
Here is the code to implement the change you want.
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Chip from "#material-ui/core/Chip";
import FaceIcon from "#material-ui/icons/Face";
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
justifyContent: "center",
flexWrap: "wrap",
"& > *": {
margin: theme.spacing(0.5)
},
//Here is where you customise the css for the delete icon
"& .MuiChip-deleteIcon": {
marginRight: "20px", // Change those values to yours
},
//For customising the outlined the css for the delete icon
"& .MuiChip-outlined": {
"& .MuiChip-deleteIcon": {
marginRight: "10px", // Change those values to yours
}
}
}
}));
export default function Chips() {
const classes = useStyles();
const handleDelete = () => {
console.info("You clicked the delete icon.");
};
const handleClick = () => {
console.info("You clicked the Chip.");
};
return (
<div className={classes.root}>
<Chip label="Deletable primary" onDelete={handleDelete} color="primary" />
<Chip
icon={<FaceIcon />}
label="Deletable secondary"
onDelete={handleDelete}
color="secondary"
/>
<Chip
icon={<FaceIcon />}
label="Deletable secondary"
onDelete={handleDelete}
color="secondary"
variant="outlined"
/>
</div>
);
}
Another way would be to do something similar in the theme.

Can't Make MouseEnter and MouseLeave Animation on React

I'm new at react. I'm using media cards to present some picture and small text and have been trying to give small sliding animation to my text and background layer. However I failed. Codes are below:
import React, { useState, Component } from 'react';
import { makeStyles } from '#material-ui/core/styles';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardContent from '#material-ui/core/CardContent';
import CardMedia from '#material-ui/core/CardMedia';
import Typography from '#material-ui/core/Typography';
import Grid from '#material-ui/core/Grid';
import Paper from '#material-ui/core/Paper';
export default function SectionCard(props) {
const [areaHeight, setAreaHeight] = useState(100);
const [imgSize, setImgSize] = useState(1);
const [lineColor, setLineColor] = useState('dodgerblue');
const [textPosition, setTextPosition] = useState(0);
const useStyles = makeStyles((theme) => ({
root: {
maxWidth: 345,
},
media: {
height: 400,
scale: imgSize,
},
greyCover: {
backgroundColor: 'rgba(0, 0, 0, 0.5)',
height: areaHeight,
width: '100%',
bottom: 0,
position: 'absolute',
},
line: {
backgroundColor: lineColor,
height: 5,
width: '100%',
borderRadius: 0,
},
textPosition: {
paddingTop: textPosition,
fontFamily: 'Quicksand !important',
color: 'white !important',
},
body: {
fontFamily: 'Quicksand !important',
},
}));
const classes = useStyles();
return (
<Grid item xs={12} sm={4} onMouseEnter={() => (setAreaHeight('100%'), setLineColor('red'), setImgSize(1.2), setTextPosition('150px!important'))} onMouseLeave={() => (setAreaHeight(100), setLineColor('dodgerblue'), setImgSize(1), setTextPosition('0px !important'))}>
<CardActionArea>
<CardMedia
className={classes.media}
image={props.img}
/>
<CardContent className={classes.greyCover} style={{ fontFamily: 'Quicksand', }}>
<div className={classes.textPosition}>
<Typography gutterBottom variant="h5" component="h2" align="center">
{props.title}
</Typography>
<Typography component="p" align="center">
{props.text}
</Typography>
</div>
</CardContent>
</CardActionArea>
<Paper className={classes.line} />
</Grid>
);
}
Codes are probably messy. Sorry for that. onMouseEnter and onMouseLeave are working fine. I just want to see that greyCover class and text moves slowly to height 100% and text to mid of the frame.
I didn't want to use another packages yet I don't know how to use too to be honest.
What I'm doing wrong?

Material-UI style buttons on the right

How do you align buttons on the right using Material-UI's makeStyles function?
I have tried using CSS's margin-right: 0 tag, but there is an error using '-' with makeStyles.
I renamed it as 'marginRight' and it still does not work. Also mr: 0 is not valid either. (Using Material-UI's spacing).
The code is trying to make the UI similar to stackOverflow's title layout.
import React from 'react';
import { makeStyles } from "#material-ui/core/styles";
import { Box, Button } from "#material-ui/core";
const style = makeStyles({
titleItemRight: {
color: 'white',
backgroundColor: 'blue',
top: '50%',
height: 30,
align: 'right',
position: 'relative',
transform: 'translateY(-50%)',
}
});
const App = () => {
const classes = style();
return (
<div>
<Box className={classes.titleBar}>
<Button variant='text' className={classes.titleItemRight}>Sign In</Button>
</Box>
</div>
);
};
Change,
align: 'right'
To,
float: 'right'
So the code would look like,
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import { Box, Button } from "#material-ui/core";
const style = makeStyles({
titleItemRight: {
color: "white",
backgroundColor: "blue",
top: "50%",
height: 30,
float: "right",
position: "relative",
transform: "translateY(-50%)"
}
});
const App = () => {
const classes = style();
return (
<div>
<Box className={classes.titleBar}>
<Button variant="text" className={classes.titleItemRight}>
Sign In
</Button>
</Box>
</div>
);
};
Working Codesandbox
I'd suggest using a flexbox for this or just using the AppBar provided already by material ui
https://material-ui.com/components/app-bar/#app-bar
if you'd still like to use Box, just edit the titleBar styles this way and add a spacer element to seperate elements to far right or far left
const style = makeStyles({
titleBar: {
display: 'flex',
width:'100%',
flexFlow: 'row',
},
spacer: {
flex: '1 1 auto'
}
});
and then your component
<Box className={classes.titleBar}>
<LogoHere/>
<div className={classes.spacer}/>
<Button variant="text">
Sign In
</Button>
</Box>

How to change the position of an Icon component, within a Tab component?

I'm using MaterialUI's tabs in my React project.
This is the JSX for the tabs:
<AppBar color="default" position="static">
<Tabs indicatorColor="primary" textColor="primary" value={tabIndex} onChange={this.handleChange}>
{instances.map(instance =>
<StyledTab
style={{ textTransform: 'initial' }}
onClick={() => { this.changeActiveInstance(instance.id) }}
label={this.getTabAddress(instance)}
icon={<ClearIcon ></ClearIcon>}
>
</StyledTab>
)}
</Tabs>
This is how i inject the css:
const StyledTab = withStyles({
root: {
textTransform: 'initial'
},
})(Tab);
The result is this:
I would like to position the "ClearIcon" elsewhere. I tried playing with the style injection a bit, with no success.
Can somebody point me to the right direction?
When trying to customize any Material-UI component, the starting point is the CSS portion of the API documentation. The most relevant classes that you may want to override in this case are wrapper, labelContainer, and label.
The best way to fully understand how these are used and how they are styled by default (and therefore what you may want to override) is to look at the source code.
Here are the most relevant portions of the styles from Tab.js:
/* Styles applied to the `icon` and `label`'s wrapper element. */
wrapper: {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
flexDirection: 'column',
},
/* Styles applied to the label container element if `label` is provided. */
labelContainer: {
width: '100%', // Fix an IE 11 issue
boxSizing: 'border-box',
padding: '6px 12px',
[theme.breakpoints.up('md')]: {
padding: '6px 24px',
},
},
And here is the relevant code for understanding how these are used:
if (labelProp !== undefined) {
label = (
<span className={classes.labelContainer}>
<span
className={classNames(classes.label, {
[classes.labelWrapped]: this.state.labelWrapped,
})}
ref={ref => {
this.labelRef = ref;
}}
>
{labelProp}
</span>
</span>
);
}
<span className={classes.wrapper}>
{icon}
{label}
</span>
Below are some examples of possible ways to customize this.
import React from "react";
import PropTypes from "prop-types";
import Paper from "#material-ui/core/Paper";
import { withStyles } from "#material-ui/core/styles";
import Tabs from "#material-ui/core/Tabs";
import Tab from "#material-ui/core/Tab";
import PhoneIcon from "#material-ui/icons/Phone";
import FavoriteIcon from "#material-ui/icons/Favorite";
import PersonPinIcon from "#material-ui/icons/PersonPin";
const styles = {
root: {
flexGrow: 1,
maxWidth: 700
},
firstIcon: {
paddingLeft: 70
},
labelContainer: {
width: "auto",
padding: 0
},
iconLabelWrapper: {
flexDirection: "row"
},
iconLabelWrapper2: {
flexDirection: "row-reverse"
}
};
class IconLabelTabs extends React.Component {
state = {
value: 0
};
handleChange = (event, value) => {
this.setState({ value });
};
render() {
const { classes } = this.props;
return (
<Paper square className={classes.root}>
<Tabs
value={this.state.value}
onChange={this.handleChange}
variant="fullWidth"
indicatorColor="secondary"
textColor="secondary"
>
<Tab
icon={<PhoneIcon className={classes.firstIcon} />}
label="Class On Icon"
/>
<Tab
classes={{
wrapper: classes.iconLabelWrapper,
labelContainer: classes.labelContainer
}}
icon={<FavoriteIcon />}
label="Row"
/>
<Tab
classes={{
wrapper: classes.iconLabelWrapper2,
labelContainer: classes.labelContainer
}}
icon={<PersonPinIcon />}
label="Row-Reverse"
/>
<Tab icon={<PersonPinIcon />} label="Default" />
</Tabs>
</Paper>
);
}
}
IconLabelTabs.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(IconLabelTabs);
We have a inbuilt property to set the icon position of tab in material ui. Document link
iconPosition:'bottom' | 'end' | 'start' | 'top'

Resources