I want a close button that needs to work outside the dialog box.
I want this modal where the close button is outside div.
Expected:
Implementation:
const Component = styled(Box)`
display: flex;
height: 528px;
`;
const Image = styled(Box)`
width: 270px;
background: url(https://static-assets-web.flixcart.com/www/linchpin/fk-cp-zion/img/login_img_c4a81e.png)
no-repeat;
color: #fff;
background-color: #2874f0;
background-position: 50% 85%;
padding: 40px 33px;
& > p {
margin-top: 12px;
color: #dbdbdb;
font-size: 18px;
}
`;
const ReqBtn = styled(Button)`
background-color: #fb641b;
text-transform: none;
height: 48px;
width: 305px;
padding: 10px 20px 10px 20px;
`;
const Wrapper = styled(Box)`
padding: 56px 35px 16px 35px;
& > p {
color: #878787;
font-size: 12px;
}
`;
// <--------------------------------------- styled section ends-------------------------------->
const LoginDialog = ({ open, setOpen }) => {
const handleCloseDialog = () => {
setOpen(false);
};
return (
<Dialog
open={open}
onClose={handleCloseDialog}
sx={{
"& .MuiDialog-container": {
"& .MuiPaper-root": {
width: "100%",
maxWidth: "750px",
},
},
}}
>
<Component>
<Image>
{/* <Typography
style={{ fontWeight: "bold", fontSize: "28px", color: "#fff" }}
>
Login
</Typography>
<Typography>
Get access to your Orders, Wishlist and Recommendations
</Typography> */}
</Image>
<Wrapper>
{/* <TextField label="Enter Email/Mobile Number" variant="standard" />
<Typography>
By continuing, you agree to Flipkart's Terms of Use and Privacy
Policy.
</Typography>
<ReqBtn
variant="contained"
sx={{
"&.MuiButtonBase-root:hover": { backgroundColor: "#fb641b" },
}}
>
Request OTP
</ReqBtn>
<Typography>New to Flipkart?Create an Account</Typography> */}
</Wrapper>
//close button
<ClearIcon
onClick={handleCloseDialog}
style={{ cursor: "pointer", backgroundColor: "yellow" }}
/>
</Component>
</Dialog>
);
};
export default LoginDialog;
I tried pasting the <ClearICon> outside <Dialog> component but the issue is the close button came in my navbar position
<>
<ClearIcon
onClick={handleCloseDialog}
style={{ cursor: "pointer", backgroundColor: "yellow" }}
/>
</>
How can I place the CloseIcon outside the dialog box as per provided design?
something like this...
.box{
position:relative;
background:gray;
width:100px;
height:100px;
}
.box>.controls{
position:absolute;
right:-30px;
}
<div class="box">
<div class="controls">
<button>x</button>
</div>
</div>
Related
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);
i am creating a website for my nft collection, with a whitelist sale and a public sale. My problem, once the user is logged in with his metamask account, he should put a check if his wallet is whitelisted. If your wallet belongs to the whitelist, then it appears as a screen and you can proceed with the purchase of the NFT, if your wallet does not belong to the whitelist you will have another screen that you have to pass to buy the NFT. Can someone help me?
import React, { useEffect, useState, useRef } from "react";
import { useDispatch, useSelector } from "react-redux";
import { connect } from "./redux/blockchain/blockchainActions";
import { fetchData } from "./redux/data/dataActions";
import * as s from "./styles/globalStyles";
import styled from "styled-components";
const truncate = (input, len) =>
input.length > len ? `${input.substring(0, len)}...` : input;
const whitelistedAddresses = ['here the first address', 'here the second address'];
const whitelisted = "Congratulations, you are whitelisted!";
const notWhitelisted = "You are not whitelisted";
export const StyledButton = styled.button`
padding: 10px;
border-radius: 50px;
border: none;
background-color: var(--secondary);
padding: 10px;
font-weight: bold;
color: var(--secondary-text);
width: 100px;
cursor: pointer;
box-shadow: 0px 6px 0px -2px rgba(250, 250, 250, 0.3);
-webkit-box-shadow: 0px 6px 0px -2px rgba(250, 250, 250, 0.3);
-moz-box-shadow: 0px 6px 0px -2px rgba(250, 250, 250, 0.3);
:active {
box-shadow: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
}
`;
export const StyledRoundButton = styled.button`
padding: 10px;
border-radius: 100%;
border: none;
background-color: var(--primary);
padding: 10px;
font-weight: bold;
font-size: 15px;
color: var(--primary-text);
width: 30px;
height: 30px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0px 4px 0px -2px rgba(250, 250, 250, 0.3);
-webkit-box-shadow: 0px 4px 0px -2px rgba(250, 250, 250, 0.3);
-moz-box-shadow: 0px 4px 0px -2px rgba(250, 250, 250, 0.3);
:active {
box-shadow: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
}
`;
export const ResponsiveWrapper = styled.div`
display: flex;
flex: 1;
flex-direction: column;
justify-content: stretched;
align-items: stretched;
width: 100%;
#media (min-width: 767px) {
flex-direction: row;
}
`;
export const StyledLogo = styled.img`
width: 200px;
#media (min-width: 767px) {
width: 300px;
}
transition: width 0.5s;
transition: height 0.5s;
`;
export const StyledImg = styled.img`
box-shadow: 0px 5px 11px 2px rgba(0, 0, 0, 0.7);
border: 4px dashed var(--secondary);
background-color: var(--accent);
border-radius: 100%;
width: 200px;
#media (min-width: 900px) {
width: 250px;
}
#media (min-width: 1000px) {
width: 300px;
}
transition: width 0.5s;
`;
export const StyledLink = styled.a`
color: var(--secondary);
text-decoration: none;
`;
function App() {
const whitelistedAddresses = ['0x74be05EDACC9c0CcEb78BC0fCB76315069b6F411', '0x7490ED764e113F9283507E8401b011c8eF8F2Dbe'];
const dispatch = useDispatch();
const blockchain = useSelector((state) => state.blockchain);
const data = useSelector((state) => state.data);
const [claimingNft, setClaimingNft] = useState(false);
const [feedback, setFeedback] = useState(`Click buy to mint your NFT.`);
const [mintAmount, setMintAmount] = useState(1);
const [CONFIG, SET_CONFIG] = useState({
CONTRACT_ADDRESS: "",
SCAN_LINK: "",
NETWORK: {
NAME: "",
SYMBOL: "",
ID: 4,
},
NFT_NAME: "",
SYMBOL: "",
MAX_SUPPLY: 1,
WEI_FREE_MINT_COST: 0,
DISPLAY_FREE_MINT_COST: 0,
WEI_PUBLIC_COST: 0,
DISPLAY_PUBLIC_COST: 0,
GAS_LIMIT: 0,
MARKETPLACE: "",
MARKETPLACE_LINK: "",
SHOW_BACKGROUND: false,
});
const FreeMint = () => {
let freeMintCost = CONFIG.WEI_FREE_MINT_COST;
let gasLimit = CONFIG.GAS_LIMIT;
let totalFreeMintCostWei = String(freeMintCost * mintAmount);
let totalGasLimit = String(gasLimit * mintAmount);
console.log("Cost: ", totalFreeMintCostWei);
console.log("Gas limit: ", totalGasLimit);
setFeedback(`Minting your ${CONFIG.NFT_NAME}...`);
setClaimingNft(true);
blockchain.smartContract.methods
.freeMint(mintAmount)
.send({
gasLimit: String(totalGasLimit),
to: CONFIG.CONTRACT_ADDRESS,
from: blockchain.account,
value: totalFreeMintCostWei,
})
.once("error", (err) => {
console.log(err);
setFeedback("Sorry, something went wrong please try again later.");
setClaimingNft(false);
})
.then((receipt) => {
console.log(receipt);
setFeedback(
`WOW, the ${CONFIG.NFT_NAME} is yours! go visit Opensea.io to view it.`
);
setClaimingNft(false);
dispatch(fetchData(blockchain.account));
});
};
const claimNFTs = () => {
let publicCost = CONFIG.WEI_PUBLIC_COST;
let gasLimit = CONFIG.GAS_LIMIT;
let totalPublicCostWei = String(publicCost * mintAmount);
let totalGasLimit = String(gasLimit * mintAmount);
console.log("Cost: ", totalPublicCostWei);
console.log("Gas limit: ", totalGasLimit);
setFeedback(`Minting your ${CONFIG.NFT_NAME}...`);
setClaimingNft(true);
blockchain.smartContract.methods
.mint(mintAmount)
.send({
gasLimit: String(totalGasLimit),
to: CONFIG.CONTRACT_ADDRESS,
from: blockchain.account,
value: totalPublicCostWei,
})
.once("error", (err) => {
console.log(err);
setFeedback("Sorry, something went wrong please try again later.");
setClaimingNft(false);
})
.then((receipt) => {
console.log(receipt);
setFeedback(
`WOW, the ${CONFIG.NFT_NAME} is yours! go visit Opensea.io to view it.`
);
setClaimingNft(false);
dispatch(fetchData(blockchain.account));
});
};
const decrementMintAmount = () => {
let newMintAmount = mintAmount - 1;
if (newMintAmount < 1) {
newMintAmount = 1;
}
setMintAmount(newMintAmount);
};
const incrementMintAmount = () => {
let newMintAmount = mintAmount + 1;
if (newMintAmount > 10) {
newMintAmount = 10;
}
setMintAmount(newMintAmount);
};
const getData = () => {
if (blockchain.account !== "" && blockchain.smartContract !== null) {
dispatch(fetchData(blockchain.account));
}
};
const getConfig = async () => {
const configResponse = await fetch("/config/config.json", {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});
const config = await configResponse.json();
SET_CONFIG(config);
};
useEffect(() => {
getConfig();
}, []);
useEffect(() => {
getData();
}, [blockchain.account]);
return (
<s.Screen>
<s.Container
flex={1}
ai={"center"}
style={{ padding: 24, backgroundColor: "var(--primary)" }}
image={CONFIG.SHOW_BACKGROUND ? "/config/images/bg.png" : null}
>
<StyledLogo alt={"logo"} src={"/config/images/logo.png"} />
<s.SpacerSmall />
<ResponsiveWrapper flex={1} style={{ padding: 24 }} test>
<s.Container flex={1} jc={"center"} ai={"center"}>
<StyledImg alt={"example"} src={"/config/images/example.gif"} />
</s.Container>
<s.SpacerLarge />
<s.Container
flex={2}
jc={"center"}
ai={"center"}
style={{
backgroundColor: "var(--accent)",
padding: 24,
borderRadius: 24,
border: "4px dashed var(--secondary)",
boxShadow: "0px 5px 11px 2px rgba(0,0,0,0.7)",
}}
>
<s.TextTitle
style={{
textAlign: "center",
fontSize: 50,
fontWeight: "bold",
color: "var(--accent-text)",
}}
>
{data.totalSupply} / {CONFIG.MAX_SUPPLY}
</s.TextTitle>
<s.TextDescription
style={{
textAlign: "center",
color: "var(--primary-text)",
}}
>
<StyledLink target={"_blank"} href={CONFIG.SCAN_LINK}>
{truncate(CONFIG.CONTRACT_ADDRESS, 50)}
</StyledLink>
</s.TextDescription>
<s.SpacerSmall />
{Number(data.totalSupply) >= CONFIG.MAX_SUPPLY ? (
<>
<s.TextTitle
style={{ textAlign: "center", color: "var(--accent-text)" }}
>
The sale has ended.
</s.TextTitle>
<s.TextDescription
style={{ textAlign: "center", color: "var(--accent-text)" }}
>
You can still find {CONFIG.NFT_NAME} on
</s.TextDescription>
<s.SpacerSmall />
<StyledLink target={"_blank"} href={CONFIG.MARKETPLACE_LINK}>
{CONFIG.MARKETPLACE}
</StyledLink>
</>
) : (
<>
<s.TextTitle
style={{ textAlign: "center", color: "var(--accent-text)" }}
>
1 {CONFIG.SYMBOL} costs {CONFIG.DISPLAY_COST}{" "}
{CONFIG.NETWORK.SYMBOL}.
</s.TextTitle>
<s.SpacerXSmall />
<s.TextDescription
style={{ textAlign: "center", color: "var(--accent-text)" }}
>
Excluding gas fees.
{feedback}
</s.TextDescription>
<s.SpacerSmall />
{blockchain.account === "" ||
blockchain.smartContract === null ? (
<s.Container ai={"center"} jc={"center"}>
<s.TextDescription
style={{
textAlign: "center",
color: "var(--accent-text)",
}}
>
Connect to the {CONFIG.NETWORK.NAME} network
</s.TextDescription>
<s.SpacerSmall />
<StyledButton
onClick={(e) => {
e.preventDefault();
dispatch(connect());
getData();
}}
>
CONNECT
</StyledButton>
{blockchain.errorMsg !== "" ? (
<>
<s.SpacerSmall />
<s.TextDescription
style={{
textAlign: "center",
color: "var(--accent-text)",
}}
>
{blockchain.errorMsg}
</s.TextDescription>
</>
) : null}
</s.Container>
) : (
<>
<s.TextDescription
style={{
textAlign: "center",
color: "var(--accent-text)",
}}
>
</s.TextDescription>
<s.SpacerMedium />
<s.Container ai={"center"} jc={"center"} fd={"row"}>
<StyledRoundButton
style={{ lineHeight: 0.4 }}
disabled={claimingNft ? 1 : 0}
onClick={(e) => {
e.preventDefault();
decrementMintAmount();
}}
>
-
</StyledRoundButton>
<s.SpacerMedium />
<s.TextDescription
style={{
textAlign: "center",
color: "var(--accent-text)",
}}
>
{mintAmount}
</s.TextDescription>
<s.SpacerMedium />
<StyledRoundButton
disabled={claimingNft ? 1 : 0}
onClick={(e) => {
e.preventDefault();
incrementMintAmount();
}}
>
+
</StyledRoundButton>
</s.Container>
<s.SpacerSmall />
<s.Container ai={"center"} jc={"center"} fd={"row"}>
<StyledButton
disabled={claimingNft ? 1 : 0}
onClick={(e) => {
e.preventDefault();
FreeMint();
getData();
}}
>
{claimingNft ? "BUSY" : "BUY"}
</StyledButton>
</s.Container>
</>
)}
</>
)}
<s.SpacerMedium />
</s.Container>
<s.SpacerLarge />
<s.Container flex={1} jc={"center"} ai={"center"}>
<StyledImg
alt={"example"}
src={"/config/images/example.gif"}
style={{ transform: "scaleX(-1)" }}
/>
</s.Container>
</ResponsiveWrapper>
<s.SpacerMedium />
<s.Container jc={"center"} ai={"center"} style={{ width: "70%" }}>
<s.TextDescription
style={{
textAlign: "center",
color: "var(--primary-text)",
}}
>
Please make sure you are connected to the right network (
{CONFIG.NETWORK.NAME} Mainnet) and the correct address. Please note:
Once you make the purchase, you cannot undo this action.
</s.TextDescription>
<s.SpacerSmall />
<s.TextDescription
style={{
textAlign: "center",
color: "var(--primary-text)",
}}
>
We have set the gas limit to {CONFIG.GAS_LIMIT} for the contract to
successfully mint your NFT. We recommend that you don't lower the
gas limit.
</s.TextDescription>
</s.Container>
</s.Container>
</s.Screen>
);
}
export default App;
I'm writing a social media app that allows you to post either text or image posts. I'm struggling to be able to show image as preview when posting.
It doesn't seem to be able to set the imageData, or does so async and idk how to await the result so it shows in my preview.
Heres the parent component:
import React, { useState } from "react";
import { collection, addDoc, getFirestore } from "firebase/firestore";
import { useUserContext } from "../../../services/user-context";
import { getStorage, ref, uploadBytes } from "firebase/storage";
import TextPost from "./TextPost";
import ImagePost from "./ImagePost";
export const CreatePostModal = ({ open, setOpen }) => {
const { user } = useUserContext();
const db = getFirestore();
const storage = getStorage();
const [imageData, setImageData] = useState(null);
const handleImageUpload = async (e) => {
if (e.target.files[0]) {
const reader = new FileReader();
reader.onload = (img) => setImageData(img.target.result);
reader.readAsDataURL(await e.target.files[0]);
console.log(imageData);
}
};
const pictureUploadRef = ref(storage, "posts/");
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
console.log(formData);
const title = formData.get("title");
const content = formData.get("content");
const postRef = await addDoc(collection(db, "posts"), {
comments: [],
content: content,
likes: [],
picture: imageData,
technologies: [],
timestamp: new Date(),
title: title,
userAvatar: "avatarUrl",
userID: user.id,
});
};
return imageData ? (
<div>
<ImagePost
open={open}
setOpen={setOpen}
handleImageUpload={handleImageUpload}
handleSubmit={handleSubmit}
/>
</div>
) : (
<div>
<TextPost
open={open}
setOpen={setOpen}
handleImageUpload={handleImageUpload}
handleSubmit={handleSubmit}
imageData={imageData}
/>
</div>
);
};
And here is child:
import React from "react";
import Box from "#mui/material/Box";
import Typography from "#mui/material/Typography";
import Modal from "#mui/material/Modal";
import styled from "styled-components";
import { Button } from "#mui/material";
import ImageIcon from "#mui/icons-material/Image";
const TitleInput = styled.textarea`
width: 100%;
height: 10%;
border: none;
background-color: inherit;
font-size: 25px;
resize: none;
&:focus-visible {
outline: none;
}
&::placeholder {
color: black;
}
text-align: center;
margin: 10px 0 15px;
color: black;
`;
const ContentInput = styled.textarea`
width: 100%;
height: 20%;
border: none;
background-color: inherit;
font-size: 20px;
resize: none;
&:focus-visible {
outline: none;
}
&::placeholder {
color: black;
}
`;
const ImageContainer = styled.div`
width: 100%;
height: 50%;
// background-color: red;
`;
const style = {
position: "absolute",
height: "50%",
minWidth: "400px",
minHeight: "550px",
width: "40%",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
bgcolor: "#f0f2f5",
boxShadow: 24,
p: 4,
borderRadius: "20px",
display: "flex",
justifyContent: "flex-start",
alignItems: "center",
flexDirection: "column",
outline: "none",
padding: "15px 25px 25px",
};
const ImagePost = ({
open,
setOpen,
handleImageUpload,
handleSubmit,
imageData,
}) => {
return (
<Modal
open={open}
onClose={() => setOpen(false)}
aria-labelledby="modal-modal-title"
>
<Box sx={style}>
<Typography
id="modal-modal-title"
variant="h4"
component="h2"
sx={{ fontSize: "30px" }}
>
Create a post
</Typography>
<div
style={{
border: "0.5px solid #a6a6a6",
width: "100%",
margin: "15px 0 0",
}}
/>
<form style={{ width: "100%", height: "100%" }}>
<TitleInput placeholder="Post title" required name="title" />
<ContentInput placeholder="Post content" required name="content" />
<ImageContainer>
{imageData ? <img src={imageData} alt="" /> : <p>failed</p>}
</ImageContainer>
<div style={{ display: "flex", justifyContent: "center" }}>
<label htmlFor="upload-button">
<input
onChange={handleImageUpload}
accept="image/*"
id="upload-button"
type="file"
style={{ display: "none" }}
/>
<Button
variant="contained"
size="large"
sx={{ ml: "-70px" }}
component="span"
>
<ImageIcon />
</Button>
</label>
<label htmlFor="submit-button">
<Button
type="submit"
id="submit-button"
variant="contained"
size="large"
color="success"
sx={{ ml: "10px", width: "150px" }}
onClick={handleSubmit}
>
Submit
</Button>
</label>
</div>
</form>
</Box>
</Modal>
);
};
export default ImagePost;
Can you help me figure out what I'm doing wrong?
1 key thing that you are missing here is that react state updates are not instantaneous, they are scheduled. You make api call which is async and may complete after the page has already been rendered. you may wanna look into useEffect hook to solve this problem.
https://codesandbox.io/s/goofy-pasteur-ntcuj
import "./styles.css";
export default function App() {
const separator = {
backgroundColor: "#E9E9E9",
height: "12px",
margin: "8px",
borderRadius: "4px"
};
return (
<div className="App">
<hr style={separator} />
<hr className="line-separator" />
</div>
);
}
.line-separator {
background-color: #e9e9e9;
height: 2px;
margin: 8px;
border-radius: 4px;
}
styles applied via java script is working fine but the same is not working from css for <hr /> tag.
Your className is wrong.
try: <hr className="line-separator" />
You have another Typo in your CSS, your height should be 12px not 2px
you have a typo in setting className of the second hr as "separator". It should match the className specified in the css file.
Correct code:
import "./styles.css";
export default function App() {
const separator = {
backgroundColor: "#E9E9E9",
height: "12px",
margin: "8px",
borderRadius: "4px"
};
return (
<div className="App">
<hr style={separator} />
<hr className="line-separator" />
</div>
);
}
.line-separator {
background-color: #e9e9e9;
height: 2px;
margin: 8px;
border-radius: 4px;
}
this should be a super quick fix:
Your className needs to match the name of the css class .line-separator
import "./styles.css";
export default function App() {
const separator = {
backgroundColor: "#E9E9E9",
height: "12px",
margin: "8px",
borderRadius: "4px"
};
return (
<div className="App">
<hr style={separator} />
<hr className="line-separator" />
</div>
);
}
The height value here just needs changing to 12px
.line-separator {
background-color: #e9e9e9;
height: 12px;
margin: 8px;
border-radius: 4px;
}
This question already has answers here:
React-Native, Scroll View Not Scrolling
(13 answers)
Closed 1 year ago.
Right now, I am creating a modal with items inside the modal to scroll. However, I am noticing the touch function is being extremely obscured and not passing through appropriately. With this current implementation, scrolling on the ScrollView is not working. I am just trying to have this scrollview inside the modal, I have set it up so that the modal can be pressable inside and an outside press of the modal will cause it to close. So I need to pass the proper touchable properties down.
Some resources and previous stack overflow pages I was looking at was:
React-Native, Scroll View Not Scrolling
return (
<Container {...props}>
<BottomModal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}>
<CenterView onPress={() => setModalVisible(!modalVisible)}>
<ModalContent>
<ModalHeader>
<CloseButtonContainer>
<Pressable onPress={() => setModalVisible(!modalVisible)}>
<CloseButton
name="times-circle"
type={vectorIconTypes.MEDIUM}
/>
</Pressable>
</CloseButtonContainer>
<TitleContainer>
<TitleText>{title}</TitleText>
</TitleContainer>
</ModalHeader>
<ModalList>
<ScrollContainer>
<LeftTextRightCheckBox>
<TitleText>Newest</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Points High to Low</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
</ScrollContainer>
</ModalList>
</ModalContent>
</CenterView>
</BottomModal>
</Container>
...
const Container = styled.View`
flex-direction: column;
background-color: white;
padding: 10px;
`;
const BottomModal = styled.Modal`
flex-direction: row;
height: 100%;
`;
const CenterView = styled.Pressable`
justify-content: flex-end;
align-items: center;
background-color: rgba(0, 0, 0, 0.3);
height: 100%;
`;
const ModalContent = styled.Pressable`
flex-direction: column;
background-color: white;
width: 100%;
border-top-left-radius: 50px;
border-top-right-radius: 50px;
padding-bottom: 30px;
height: 300px;
`;
const ModalHeader = styled.View`
flex-direction: row;
width: 100%;
padding: 20px;
height: 60px;
`;
const ModalList = styled(ScrollView).attrs(() => ({
contentContainerStyle: {
flexDirection: 'column',
justifyContent: 'center',
flexGrow: 1,
},
showsVerticalScrollIndicator: true,
persistentScrollbar: true,
}))`
border: solid pink 5px;
width: 100%;
height: 200px;
padding: 10px;
`;
My question was answered perfectly in the same link I had in my question. All credit goes to freddrivett.
If your ScrollView is within something that handles touch (Pressable,
TouchableWithoutFeedback etc) then you either need to stop the touch
event propagating up to that parent handler or else the ScrollView
won't handle the touch event and therefore won't scroll.
This can be done either with onStartShouldSetResponder={() => true} or
by wrapping the children in an element which itself handles the touch
event (e.g. Pressable):
<Pressable>
<Text>This is scrollable</Text>
<Pressable>
<Pressable>
<Text>As is this</Text>
<Pressable> </ScrollView> );