Manager line-height per font-size with styled system - css

Styled components has a compose utility to combine multiple Styled System functions in a single component. I want to compose the lineHeight and fontSize together based on the default array.
Instead of doing:
<Heading type="h1"
fontSize={[ 1, 2, 3 ]}
lineHeight={[1 , 2, 3 ]}
color={theme.colors.heading.tinted}
>
I want to achieve only a font prop that has the fontSize and lineHeight combined.
<Heading type="h1"
font={[ 1, 2, 3 ]}
color={theme.colors.heading.tinted}
>
Heading.jsx
const Element = styled('div')(
space,
color,
compose(
fontSize,
lineHeight
)
);
theme.js
const theme = {
fontSizes: [11, 13, 16, 23, 29, 37, 47, 76, 97],
lineHeights: ['12px', '12px', '12px', '32px', '32px', '40px', '48px', '56px', '72px', '80px', '104px']
}

I have created a codesandbox example with your requirements:
Whole file is here:
https://codesandbox.io/s/styled-component-basic-j3zpx
<Title font={[50, 45]}>
This is a heading includes first array index for font size and second array for line height.
</Title>
styled css:
export const Title = styled.h1`
color: red;
margin: 0;
border: 1px solid black;
${props =>
props.font &&
css`
font-size: ${props => (props.font[0] ? `${props.font[0]}px` : "20px")};
line-height: ${props => (props.font[1] ? `${props.font[1]}px` : "30px")};
`}
`;

Related

How to place icon at the end in linear progress bar MUI?

I'm using MUI v5 to build linear progress bar.I have a scenario where if value in progress bar is 100%,I need to show tick icon at the end.The width of the bar with/without tick icon should be same,meaning icon shouldn't be placed after the bar.It should be at the end of bar.I tried with stylings and able to place tick icon at the end.But I'm unable to show the icon clearly as the bar overlaps with tick icon.
<div style={{ display: "flex", flexDirection: "row", position: "relative", alignItems: "center" }}>
<LinearProgress
variant="determinate"
sx={{
width: "100%",
borderRadius: "4px"
}}
value={50}
/>
<CheckCircleIcon sx={{ color: "blue" }} style={{ position: "absolute", width: "20px", display: "flex", justifyContent: "flex-end", right: "-2px", color: "#fff", fontWeight: "bold" }} />
</div>
Current Design
Expected Design
Here is a live demo where I've customized an MUI Slider with a checkmark SliderThumb.
The demo includes the foundation for using this as a progress bar:
Disable the slider to ignore user input. Keep in mind that disabling will change the color to gray. You can override disabled behavior through .Mui-disabled
Set the slider's value using a state variable that corresponds to your current progress
You may also choose to customize a LinearProgress component in the same way I've customized the Slider above. See the docs for LinearProgress customization.
Full slider code:
import * as React from 'react'
import Slider, { SliderThumb } from '#mui/material/Slider'
import { styled } from '#mui/material/styles'
import Box from '#mui/material/Box'
import CheckCircleIcon from '#mui/icons-material/CheckCircle'
const CheckMarkSlider = styled(Slider)(({ theme }) =>
({
color: '#3a8589',
height: 3,
padding: '13px 0',
'& .MuiSlider-thumb':
{
height: 20,
width: 20,
backgroundColor: '#fff',
border: '1px solid currentColor',
'&:hover': {
boxShadow: '0 0 0 8px rgba(58, 133, 137, 0.16)',
},
'& .checkmark-bar':
{
height: 9,
width: 1,
backgroundColor: 'currentColor',
marginLeft: 1,
marginRight: 1,
},
},
'& .MuiSlider-track':
{
height: 3,
},
'& .MuiSlider-rail':
{
color: theme.palette.mode === 'dark' ? '#bfbfbf' : '#d8d8d8',
opacity: theme.palette.mode === 'dark' ? undefined : 1,
height: 3,
},
}))
const CheckMarkThumbComponent = (props) =>
{
const { children, ...other } = props
return (
<SliderThumb {...other}>
{children}
<CheckCircleIcon />
</SliderThumb>
)
}
const CustomizedSlider = () =>
{
const [value, setValue] = React.useState(20)
React.useEffect(() =>
{
const intervalId = setInterval(() => setValue(Math.random() * 100), 500)
return () => clearInterval(intervalId)
}, [value])
return (
<Box sx={{ width: 320 }}>
<CheckMarkSlider
value = {value}
disabled
components={{ Thumb: CheckMarkThumbComponent }} />
</Box>
)
}
export default CustomizedSlider

How to style HTML element tags in MUI? [duplicate]

This question already has an answer here:
how to apply global backgroundColor using MuiCssBaseline and styleOverrides
(1 answer)
Closed 10 months ago.
I'm using the latest MUI version (v5) and CssBaseline from #mui/materials and given how I normally do this in CSS:
body, html, #root {
width: 100%;
height: 100%;
min-height: 100%;
margin: 0;
padding: 0;
font-size: 62.5%; /* makes 1.2rem === 12px, 1.6rem === 16px, ect... */
text-align: left;
}
MUI Body
(add the following to my theme)
components: {
MuiCssBaseline: {
styleOverrides: {
body: {
width: '100%',
height: '100%',
minHeight: '100%',
margin: 0,
padding: 0,
fontSize: '62.5%', // makes 1.2rem === 12px, 1.6rem === 16px, ect...
textAlign: 'left'
}
}
}
}
MUI Root
(add the following to my sxStyle e.g: sx={{...sxLayout, ...sxLayout.root}})
const sxLayout = {
flexDirection: 'column',
root: {
width: '100%',
height: '100%',
minHeight: '100%',
margin: 0,
padding: 0,
fontSize: '62.5%', // makes 1.2rem === 12px, 1.6rem === 16px, ect...
textAlign: 'left',
'&': {
width: '100%',
height: '100%',
minHeight: '100%',
margin: 0,
padding: 0,
fontSize: '62.5%', // makes 1.2rem === 12px, 1.6rem === 16px, ect...
textAlign: 'left'
},
'&.MuiListItemButton-root': {
width: '100%',
height: '100%',
minHeight: '100%',
margin: 0,
padding: 0,
fontSize: '62.5%', // makes 1.2rem === 12px, 1.6rem === 16px, ect...
textAlign: 'left'
}
}
}
MUI Html
(????)
????
There are a few ways to get components styled. The last one I describe is specific to MUI and is probably likeliest to be what you are looking for.
Some of the css classes belong to specific MUI components, so you just use the MUI component and if your <ThemeProvider /> is used correctly, you shouldn't have to add any classes.
You have the option of defining regular CSS or SASS in a separate file and importing it in your component, then using the class via the className property of a component.
Another option is CSS-in-JS. You can use the style property to use the custom css and you define the CSS in your JS file for the component:
... //inside your component
const mystyle = {
color: "white",
backgroundColor: "DodgerBlue",
padding: "10px",
fontFamily: "Arial"
};
...
return (
<div>
<h1 style={mystyle}>Hello Style!</h1>
<p>Add a little style!</p>
</div>
);
...
Above example adapted from https://www.w3schools.com/react/react_css.asp
The above work in react without MUI as well. The MUI specific way to create a custom style for a component is to use the makeStyles() hook. This will give you variables to use as input to the className property but when you inspect and look at the html, the classes applied will have names that are generated by MUI.
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
const useStyles = makeStyles({
root: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
border: 0,
borderRadius: 3,
boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
color: 'white',
height: 48,
padding: '0 30px',
},
});
export default function MyComponent() {
const classes = useStyles();
return <Button className={classes.root}>Hook</Button>;
}
Above example copied from https://react.school/material-ui/styling
To learn more about the makeStyles() hook, see the MUI documentation for it: https://mui.com/system/styles/api/#makestyles-styles-options-hook
If you scroll on that same page, you can see info about other style related hooks too.

Gradient border on MUI component

I did not manage to find the equivalent of border-image-source css
My goal is to render a border gradient on a button component
This is how you add a gradient border to the button component:
V5
const options = {
shouldForwardProp: (prop) => prop !== 'gradientColors',
};
const GradientButton = styled(
Button,
options,
)(({ theme, gradientColors }) => ({
border: '5px solid',
borderImageSlice: 1,
borderImageSource: `linear-gradient(to left, ${gradientColors.join(',')})`,
}));
If you want a round button with gradient border, you can't use the code above since borderImage doesn't have a radius. A workaround is to create a gradient background in the child element :after because the background can be clipped using borderRadius:
const borderRadius = 15;
const RoundGradientButton = styled(
Button,
options,
)(({ theme, gradientColors }) => ({
position: 'relative',
border: '5px solid transparent',
backgroundClip: 'padding-box',
borderRadius,
'&:after': {
position: 'absolute',
top: -5,
left: -5,
right: -5,
bottom: -5,
background: `linear-gradient(to left, ${gradientColors.join(',')})`,
content: '""',
zIndex: -1,
borderRadius,
},
}));
Usage
<GradientButton gradientColors={['red', 'yellow']} variant="contained">
Default
</GradientButton>
<RoundGradientButton gradientColors={['red', 'yellow']} variant="contained">
Default
</RoundGradientButton>
Live Demo
V4
const useStyles = makeStyles((theme: Theme) => ({
button: {
border: "6px solid",
borderImageSlice: 1,
borderImageSource: "linear-gradient(to left, red, orange)"
}
}));
export default function ContainedButtons() {
const classes = useStyles();
return (
<Button className={classes.button} variant="contained">
Default
</Button>
);
}
Live Demo
Related Answer
How to add linear-gradient color to MUI Chip background?

Adding image to button using Emotion css

I want to style two buttons: Up and Down with an image using emotion css but unable to do so. Currently, I am normally styling my elements within a function. How can I achieve this using emotion css?
I followed https://emotion.sh/docs/introduction but I am unable to implement it the right way.
import up from "../img/up.png";
function PostButton(props) {
let style = {
backgroundRepeat: 'no-repeat',
background: `url(${up})`,
paddingRight: 24,
paddingTop: 26,
paddingLeft: 26,
paddingBottom: 26.6
};
return (
<button style={style} onClick={() => props.handleClick()}>{props.background}</button>
);
}
//I have written similar code for PostButton2
function Post(props) {
return (
<div>
<Up >
<PostButton src={"../images/up.png"} handleClick= .
{props.incrementScore} />
</Up> >
<Down >
<PostButton2 src={"../images/down.png"}
handleClick{props.decrementScore} />
</Down>
</Col>
</Row>
</Container>
</div>
);
}
Assuming that src property holds the background image, I think you need to update background to use the prop like so:
background: `url(${props.src})`,
Use src prop as path to image.
// First way, with css from emotion/react
/** #jsx jsx */
import { jsx, css } from '#emotion/react'
const PostButton = ({ background, handleClick, src }) => (
<button css={css`
background: ${`no-repeat url(${src})`};
padding: 26px 24px 26.6px 26px;
`}
onClick={handleClick}>{background}</button>
)
// Second way, with css from emotion/css
import React from 'react'
import { css } from '#emotion/css'
const PostButton = ({ background, handleClick, src }) => (
<button className={css`
background: ${`no-repeat url(${src})`};
padding: 26px 24px 26.6px 26px;
`}
onClick={handleClick}>{background}</button>
)
// Third way, with css from emotion/css, but pass styles as object
import React from 'react'
import { css } from '#emotion/css'
const PostButton = ({ background, handleClick, src }) => (
<button className={css({
background: `no-repeat url(${src})`,
padding: '26px 24px 26.6px 26px'
})}
onClick={handleClick}>{background}</button>
)

react css style syntax - set value of css prop with variables and text in one line

I have this code:
const styles = theme => ({
root: {
paddingTop: theme.spacing.unit * 3,
paddingBottom: theme.spacing.unit * 3,
paddingLeft: 0,
paddingRight: 0,
}
});
Is it posible to set padding with only one line?
(I want to do something like this:)
const styles = theme => ({
root: {
padding: 0 theme.spacing.unit * 3',
}
});
Yes, you can do it by creating the string like so (using template literals):
const styles = theme => ({
root: {
padding: `${theme.spacing.unit * 3} 0`,
}
});
If the theme spacing unit was 10px that would result in padding: 10px 0, which is shorthand for padding: 10px 0 10px 0;
It is important to use the back ticks (`) and not quotes.
One thing to note, if your theme.spacing.unit does not include the unit of measure, add it after the curly braces like so:
padding: `${theme.spacing.unit * 3}px 0`,

Resources