Creating a React CSS object with clamp and focus - javascript

I'm trying to create an object to use it in inline style but I don't know how to how to write clamp and after the right way.
const PhoneInputStyle = {
fontSize: clamp("13px", "1.111vw", "16px"), /*this is giving me trouble
lineHeight: clamp("15px", "1.319vw", "19px"), */
position: "relative",
width: "100%",
height: "51px",
cursor: "pointer",
display: "flex",
flexDirection: "row",
alignItems: "center",
padding: "8px 16px",
border: "1px solid ${COLOR_NOT_BLACK}",
boxSizing: "border-box",
borderRadius: "10px",
outline: "none",
&:focus { /*this is giving me trouble
border: "1px solid ${COLOR_SALMON} !important",
} */
gridRowStart: "1",
gridColumnStart: "1"
}
The error I get on clamp is : Cannot find name 'clamp'
What I get on focus is : Expression expected (on the &)

You need to make the whole thing a string e.g. {fontSize: "clamp(13px, 1.111vw, 16px)"}
For the focus, I think you'll need something like: https://styled-components.com/
-edit-
Perhaps you could create a wrapper component that you can set an onHover event handler on.
Something along the lines of...
<div
style={isShown ? {border: "1px solid ${COLOR_SALMON}"}: ""}
onMouseEnter={() => setIsShown(true)}
onMouseLeave={() => setIsShown(false)}
>
{children}
</div>
This would probably even work without needing to set a wrapper component.

Related

CSS Slanding Div edges over an Image

I am trying to design a simple report with the format as shown in the following Figma file using React and Material UI. However, I am encountering a challenge when designing the slanting edges of the divs as shown on the report. Plus the purple border. This is what I have done so far, but it is far from being perfect:
const leftDiv = {
content: "",
position: "absolute",
top: "50%",
right: 0,
width: "100%",
height: "50%",
backgroundColor: 'rgb(255, 255, 255)',
clipPath: "polygon(0 0, 0% 0%, 100% 100%, 0% 100%)"
}
const rightDiv = {
position: "absolute",
bottom: 0,
right: 0,
display: 'inline-block',
width: 0,
height: 0,
borderStyle: 'solid',
borderWidth: '0 0 500px 100vw',
borderColor: 'transparent transparent #FFFFFF transparent',
}
const contentDiv = {
backgroundColor: 'rgb(255, 255, 255)',
width: "100%",
height: "100%",
clipPath: "polygon(100% 0, 100% 0%, 100% 100%, 0% 100%)"
}
const Coverpage = () => {
return (
<Container>
<Grid>
<Paper>
<Box sx={{ position: 'relative', width: '100%' }}>
<CardMedia
component='img'
alt="cover page image"
image='https://unsplash.com/photos/vbxyFxlgpjM'
/>
<Box style={leftDiv}></Box>
<Box style={rightDiv}>
<Box style={contentDiv}>
<Box sx={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', alignItems: 'flex-end', textAlign: 'right', pr: 8 }}>
<Typography sx={{ fontSize: '24px', mb: 2 }}>Lorem ipsum</Typography>
<Typography sx={{ fontSize: '48px', fontWeight: 'bold', textTransform: 'uppercase', color: '#000133' }}>Lorem ipsum</Typography>
<Typography sx={{ fontSize: '64px', fontWeight: 'bold', textTransform: 'uppercase', color: 'blue' }}>Lorem ipsum</Typography>
</Box>
</Box>
</Box>
</Box>
</Paper>
</Grid>
</Container>
);
}
export default Coverpage;
I found using clipPath as the easiest, even though I would prefer using triangles to design the slanting edges since later, I am planning to use react-pdf-renderer which I am not sure if it supports clipPath in its CSS styling.
I will appreciate a pointer to the right direction.
Dan touched on the purple border. About the slanted div you can use this trick:
.slanted{
height: 0;
width: 0;
border-top: solid 100px transparent;
border-right: solid 50vw blue;
border-left: solid 50vw blue;
border-bottom: solid 100px blue;
}
You're making a div with no height or width. The borders meet along a diagonal line and so you can have a triangle effect.
You can use an additional div for the text
Edit: making the borders responsive
To make the border trick dynamic you can use some JS:
function App() {
const footerRef = React.useRef()
useEffect(() => {
window.addEventListener('resize', setBorders)
return () => {
window.removeEventListener('resize', setBorders)
}
}, [])
useEffect(() => {
if (!footerRef.current) return
setBorders()
}, [footerRef])
const setBorders = () => {
let containerWidth = document.querySelector('.container').clientWidth
let footerStyle = footerRef.current.style
footerStyle.borderRightWidth = containerWidth/2+'px'
footerStyle.borderLeftWidth = containerWidth/2+'px'
}
return (
<div className='App'>
<div className='container'>
<div className='footer' ref={footerRef}>
</div>
</div>
</div>
);
}
export default App
We are adding a 'resize' eventListener to the window that will trigger the setBorders() function. In this function we select the container element and set the width of the footer borders to be half of it.
To make sure the function also fires on initial load I added a useEffect which will fire when the footer is created and its Ref is set. You can also use a callback ref instead.
The css, I assumed the footer will be static height:
.container{
height: 200px;
width: 100%;
background: red;
}
.footer{
position: relative;
height: 0;
width: 0;
top: calc(100% - 100px);
/*border-top width + border-bottom width = 100px*/
border-top: 50px solid transparent;
border-bottom: 50px solid green;
border-right: solid blue;
border-left: solid blue;
}
If you don't mind making the container position: relative; you can then just do:
.footer{
position: absolute;
bottom: 0;
}
You just need to use a simple CSS transform on the element.
transform: skew(-15deg, -15deg);

How do I override a MaterialUI outlined input through a global theme overrides file?

I am working on my theme file that contains all of my overrides and I am trying to complete the outlined input however, I get this weird bug when I try to do so. It appears that there are 2 input borders when these styles are applied.
MUI outlined input overrides section:
MuiOutlinedInput: {
styleOverrides: {
root: {
borderRadius: "4px",
border: "1px solid green ",
"&:hover": { borderRadius: "4px", border: "1px solid red" },
"&:disabled": { borderRadius: "4px", border: "1px solid black" },
"&.Mui-focused": { borderRadius: "4px", border: "2px solid blue" },
},
},
},
Any tips on fixing this are greatly appreciated!
If you inspect the Outlined Input you'll see that there's 2 child elements. The first is the input element, the second is a fieldset element. You're needing to apply styles to the fieldset.
I am not sure exactly what you're attempting to do with the styling since you've got 4 different border colors being applied... I'm guessing you'd want something similar to
MuiOutlinedInput: {
styleOverrides: {
root: {
"& fieldset" {
borderColor: "red";
}
},
},
},

Move react component to another component

I'm working on a react. The code below is an example. ArrayExample is mapped and returned to the div component. Whenever I click the mapped div component, I want to change the value of the top of div (position: 'absolute') and place it on the right side according to the mapped div topBorder. Is there a way? I want to move it smoothly like an animation.
import React from "react";
const sample = () => {
const arrayExample = ["AAAA", "BBBB", "CCCC"];
return (
<div
style={{
display: "flex",
flexDirection: "column",
width: "100%",
height: "500px",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#f3f3f3",
}}
>
{arrayExample.map((v, i) => {
return (
<div
style={{
width: "50%",
padding: 50,
border: "1px solid black",
marginTop: 15,
}}
onClick={() => {
console.log("Event!")
}}
>
{v}
</div>
);
})}
<div style={{position: 'absolute', top: 70, right: '22%', backgroundColor: "#4285F4", width: 50, height: 150, borderRadius: 5}}>
moving screen(I want to Change top value)
</div>
</div>
);
};
export default sample;
On click of the item div, you need to figure out the distance of that div from the top, and then change the top css property of your right div according to that. To find this distance you can use offsetTop property. For animation you can use transition property. Here is the code:
import React, { useRef } from "react";
const Sample = () => {
const arrayExample = ["AAAA", "BBBB", "CCCC"];
const rightDiv = useRef();
const itemClickHandler = (i) => {
const newTopHeight = document.getElementById("container").children[i].offsetTop;
rightDiv.current.style.top = newTopHeight + 'px';
}
return (
<div
id="container"
style={{
display: "flex",
flexDirection: "column",
width: "100%",
height: "500px",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#f3f3f3",
}}
>
{arrayExample.map((v, i) => {
return (
<div
key={i}
style={{
width: "50%",
padding: 50,
border: "1px solid black",
marginTop: 15,
}}
onClick={() => itemClickHandler(i)}
>
{v}
</div>
);
})}
<div
ref={rightDiv}
style={{
position: 'absolute',
top: 70,
right: '22%',
backgroundColor: "#4285F4",
width: 50,
height: 150,
borderRadius: 5,
transition: "top 0.5s ease-in-out"
}}>
moving screen(I want to Change top value)
</div>
</div>
);
};
export default Sample;
You can see this in action here: https://codesandbox.io/s/thirsty-curie-7mskj
In your click handler you can get the current position of the clicked div in px, you can easily google how to do this this (relative to the page, not the viewport). I would suggest storing this value in state, call it something like activeItemOffsetTop, then just set top to the current state

How to position a child div to span from the beginning to the end of a parent div?

I'm trying to position the FullWidthDiv component to span from the beginning of the MainDiv side, all the way to the end. I've tried giving in an absolute position and playing around with flex, but I can't get it to not start from the SubDiv component.
Is it possible to achieve this?
My CodeSandbox approach.
Here is what I'm trying to achieve
It is a little bit hacky, but you can center ChildDiv with align-items: center.
Also, shrink the FullWidthDiv to 280.
And last you have to add flex: 1, width: 100% to the div, that hold SubChildDiv inside App component.
export default function App() {
return (
<MainDiv>
<ChildDiv>
<div style={{flex: 1, width: '100%'}}>
<SubChildDiv />
<SubChildDiv />
</div>
<FullWidthDiv />
</ChildDiv>
</MainDiv>
);
}
const MainDiv = ({ children }) => (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
width: 250,
height: 250,
backgroundColor: "red",
padding: "1rem"
}}
>
{children}
</div>
);
const ChildDiv = ({ children }) => (
<div
style={{
width: 200,
height: 200,
backgroundColor: "blue",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "space-between"
}}
>
{children}
</div>
);
const SubChildDiv = () => (
<div
style={{
display: "flex",
width: "100%",
height: 30,
backgroundColor: "green",
border: "1px solid black"
}}
/>
);
const FullWidthDiv = () => (
<div
style={{
width: 280,
height: 30,
border: "1px solid black",
backgroundColor: "green"
}}
/>
);
If you want the FullWidthDiv to be with 100% width, you have to calculate the 100% width and add the padding from both sides of MainDiv it will look something like that: calc(100% + 2rem).

Have text above icon in React JS

I am learning React and I came across a youtube video that teaches how to use spinners.
https://www.youtube.com/watch?v=T3L4zQnLrVA
I've written the code inside of codesandbox.io here:
https://codesandbox.io/s/late-thunder-sise4?fontsize=14&hidenavigation=1&theme=dark
Now if you click on the "Fake Fetch" button, you'll see the word "Text" in black to the left of the spinner and I was wondering how I could get the word above the spinner.
Thanks for the help!
Just add the following style to your h3 with Text
<h3 style={{ position: 'absolute', top: '250px' }}>Text</h3>
https://codesandbox.io/s/nifty-borg-k3d2u
FWIW - in the future try to use StackOverflow's code snippets, since links to codesandbox aren't guaranteed to exist in the future in case someone else can benefit from your question.
You can use flex to achieve this. In your styled styles, use:
display: "flex",
flexDirection: "column"
So your entire style would be:
const styled = props.overlay
? {
background: "rgba(0, 0, 0, 0.5)",
height: "100vh",
width: "100vw",
position: "fixed",
display: "flex",
flexDirection: "column"
}
: null;
Keep in mind the style above is only applied when the overlay is selected. Otherwise you don't apply any special styles to the Spinner (because they styles are null).
If you want the Text and Spinner stacked for both overlay and non-overlay, use:
const styled = props.overlay
? {
background: "rgba(0, 0, 0, 0.5)",
height: "100vh",
width: "100vw",
position: "fixed",
display: "flex",
flexDirection: "column"
}
: {
display: "flex",
flexDirection: "column"
};
Here's the full working example - https://codesandbox.io/s/proud-frost-3zjob
This definately works. Add some flex properties such as:
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
If you use the styles as such, it works perfectly.
import React from "react";
import SpinnerIcon from "./SpinnerIcon";
import "./Spinner.css";
const Spinner = props => {
return (
<div className="Spinner" style={{
background: "rgba(0, 0, 0, 0.5)",
position: "fixed",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
}}>
<h3 style={{ margin: 0 }}>Text</h3>
<SpinnerIcon />
</div>
);
};
export default Spinner;
Check this fiddle

Categories