Left space between two texts (Dynamic) - javascript

const Btn = () => {
const options = ['test1', 'test2', 'test3'];
return (
<div style={{ position: 'absolute', left: '8px', widht: 'auto', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', backgroundColor: '#006C84' }}>
{options.map(opt => (
<span style={{ paddingRight: '10px' }}>{opt}</span>)
)}
</div>
)
}
Above is my code and after the end of the text, there is some extra space are left. How to remove that space.

So you are giving paddingRight: 10px to the span, so at the end of the last child it's showing some space left.
There are two ways you can achive this
JS way
Css way
JS way
{options.map((opt,index) => (
<span style={{ paddingRight: options.length - 1 === index ? '10px' : "0px" }}>{opt}</span>)
)}
Css way
you need to change the inline style to explicit style for this, I would say this is the recommended way of giving css over inline style or may be you can create one style object for that.
<div className="parent">
{options.map(opt => (
<span style={{ paddingRight: '10px' }}>{opt}</span>)
)}
</div>
.parent{//parent css goes here}
.parent span:not(::last-of-type){padding-right: 10px}

const Btn = () => {
const options = ['test1', 'test2', 'test3'];
return (
<div style={{ position: 'absolute', left: '8px', widht: 'auto', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', backgroundColor: '#006C84', display: 'flex', gap: '10px' }}>
{options.map(opt => (
<span>{opt}</span>)
)}
</div>
)
}
use display: flex and gap inside the parent div style
https://codesandbox.io/s/keen-ganguly-kl4ys7?file=/src/App.js

Related

Is there a better way to change style based on screen size on react app?

Im using Material UI on my react app and I'm using useMediaQuery and useTheme from mui. This is the code I have right now. Is there a better way to optimize less code? There are only a few style changes between the 2 codes.
const MainPage = () => {
const theme = useTheme();
const isMatch = useMediaQuery(theme.breakpoints.down('md'))
return (
<div className='mainPage'>
{
isMatch ? (
<>
<Box sx={{ display: "flex", justifyContent: "center", alignContent: "center", flexDirection: "column", padding: "60px 10px 10px 10px" }}>
<Box component="img" src={LandingImage} sx={{ width: "100%" }} />
<Box sx={{ paddingTop: 8 }}>
<Typography sx={{ fontSize: 26, fontWeight: "bold", fontFamily: "sans-serif", textAlign: "center", paddingBottom: 5 }}>About us</Typography>
</Box>
</Box>
</>
) : (
<>
<Box sx={{ display: "flex", justifyContent: "center", alignContent: "center", flexDirection: "row", paddingTop: 20 }}>
<Box component="img" src={LandingImage} />
<Box sx={{ width: 700, paddingTop: 8 }}>
<Typography sx={{ fontSize: 30, fontWeight: "bold", fontFamily: "sans-serif", textAlign: "center", paddingBottom: 5 }}>About us</Typography>
</Box>
</Box>
</>
)}
</div>
)
}
There really is no need to do a media query like this, as the sx prop provides per-breakpoint customization if you want it.
Notice, for example, the flexDirection styling on the first Box component. Everything up to the md breakpoint gets column, then it becomes row.
const MainPage = () => {
const theme = useTheme();
return (
<div className='mainPage'>
<Box sx={{
display: "flex",
justifyContent: "center",
alignContent: "center",
flexDirection: { xs: "column", md: "row" },
padding: { xs: "60px 10px 10px 10px", md: "20px 0 0 0" }
}}>
<Box
component="img"
src={LandingImage}
sx={{
width: { xs: "100%", md: 'unset' }
}}/>
<Box sx={{
paddingTop: 8,
width: { md: 700 }
}}>
<Typography
sx={{
fontSize: { xs: 26, md: 30 },
fontWeight: "bold",
fontFamily: "sans-serif",
textAlign: "center",
paddingBottom: 5
}}>
About us
</Typography>
</Box>
</Box>
</div>
)
}
https://mui.com/system/basics/#responsive-values
As the structure of JSX for mobile / desktop is the same, you could drop one of those two JSX templates, build a variable to store component configuration based on isMatch and pass this variable into component template.
const MainPage = () => {
const theme = useTheme();
const isMatch = useMediaQuery(theme.breakpoints.down('md'))
// Subset of props, to illustrate the idea.
const config = isMatch ? {fontSize: 26} : {fontSize: 30};
// Here only root <Box/> is configured, but you can configure all the nested components the same way.
return (
<div className='mainPage'>
<Box sx={config}>[...]</Box>
</div>
)
}
(Same with components nested inside <Box/> - the idea is the same - declare some variables with value based on your state and pass them to JSX declaration)
There are several options. The first is to create a style object in javascript, which can be interacted with like normal javascript. You are already doing this in-line, but if we do it in the code above, we can make it dynamic.
const myOuterBoxStyle = {
display: "flex",
justifyContent: "center",
alignContent: "center",
flexDirection: "row",
paddingTop: 20
}
if (isMatch) {
myOuterBoxStyle.flexDirection = "column";
myOuterBoxStyle.paddingTop = undefined;
myOuterBoxStyle.padding = "60px 10px 10px 10px";
}
Once you do all of the dynamic styling you need, you can make a single return for your component and simply put
<Box sx={{myOuterBoxStyle}}>
The other option is to make a seperate CSS sheet and import it, and then use classes. Something like
.outer-box {
display: "flex";
justify-content: "center";
align-content: "center";
}
.is-match {
flex-direction: "column";
padding: "60px 10px 10px 10px"
}
And then you can either add the is-match class or, perhaps, the is-not-match class depending.
The final option is to use a third-party package that does most of this for you, like Tailwind
Mui has breakpoints shorthand syntax, as you can check here.
So, for example, your code will also work with:
const MainPage = () => {
return (
<div className="mainPage">
<Box
sx={{
display: "flex",
justifyContent: "center",
alignContent: "center",
flexDirection: ["column", "column", "row"],
paddingTop: ["60px 10px 10px 10px", "60px 10px 10px 10px", 20]
}}
>
<Box component="img" />
<Box sx={{ width: ["unset", "unset", 700], paddingTop: 8 }}>
<Typography
sx={{
fontSize: [26, 26, 30],
fontWeight: "bold",
fontFamily: "sans-serif",
textAlign: "center",
paddingBottom: 5
}}
>
About us
</Typography>
</Box>
</Box>
</div>
);
};
In the example above i use the Breakpoints as an array and mui docs says:
The second option is to define your breakpoints as an array, from the smallest to the largest breakpoint.
So imagine that array positions would be: [xs, sm, md, lg, xl] and the breakpoints are equivalent to theme.breakpoints.up.
Another way to do it is use Breakpoints as an object:
Simple example
<Box
sx={{
width: {
xs: 100, // theme.breakpoints.up('xs')
sm: 200, // theme.breakpoints.up('sm')
md: 300, // theme.breakpoints.up('md')
lg: 400, // theme.breakpoints.up('lg')
xl: 500, // theme.breakpoints.up('xl')
},
}}
>

responsive div height on conditional rendering?

I am working on a react project, where I want to conditionally render a div above an existing div that currently covers the screen with an image. I would like the existing div to reduce in height, by shrinking the size of the image, when the second div conditionally renders. The second div can have a varied height. ( e.g. list of items).
This is simplified version of what I have in my App so far:
function App() {
const [show, setShow] = useState(false);
return (
<div
style={{
border: "solid",
width: "100%",
maxHeight: "100vh"
}}
>
{show && (
<div>
<div style={{ height: "300px", backgroundColor: "red" }}></div>
<button
onClick={() => {
setShow(false);
}}
>
Close
</button>
</div>
)}
<div
style={{
display: "flex",
justifyContent: "center"
}}
>
<img
src="https://i.imgur.com/LiAUjYw.png"
alt="test"
style={{
maxWidth: "100%",
height: "auto"
}}
/>
</div>
<button onClick={() => setShow(true)}>SHow</button>
</div>
);
}
It initially looks like this: https://imgur.com/a/R0e74Xk
And on clicking the 'Show' button, it looks like this: https://imgur.com/a/Iy6osio
As you can see the bottom div gets shifted down, and goes over the container div.
I was wondering how I can make the div responsive enough to change its height when the other element is rendered.
I am fairly new to styling so any help on this would be greatly appreciated.
Thank you.
Here's one simple idea. See how the style is given to the divs like so:
<div
style={{
display: "flex",
justifyContent: "center"
}}
>
Note how the style has this weird {{ }} notation. That's because style accepts an object, and the object here is:
{
display: "flex",
justifyContent: "center"
}
You could take that object and save it as a variable somewhere, for example:
const styleWhenShow = {
display: "flex",
justifyContent: "center",
height: "100px"
}
const styleWhenNoShow = {
display: "flex",
justifyContent: "center",
height: "500px"
}
Since you already have your show state, now it's just a matter of replacing the style prop with:
style={show ? styleWhenShow : styleWhenNoShow}
In case you don't want to repeat some common styles between the show and noshow styles, you can also do something like:
const commonStyle = {
display: "flex",
justifyContent: "center"
}
const styleWhenShow = {
height: "100px"
}
const styleWhenNoShow = {
height: "500px"
}
And set the style prop like:
style={show ? { ...commonStyle, ...styleWhenShow } : { ...commonStyle, ...styleWhenNoShow }}

I want to be able to change the content of modal each time the map function iterates

I want to use the map function to show on the same modal different content and update them when necessary, I decided to go with props and I don't get why it isn't working.
What I get instead is
when I click on View All
This is my Parent component
<div
style={{
display: "flex",
justifyContent: "space-between",
fontWeight: 600,
}}
>
{Res.AdmissionsRes.slice(0, 3).map((admission, index) => (
<S.BackCardGuIn
bR="16px"
bg="#f8f9fa"
bS="0 1px 2px 0 rgb(60 64 67 / 30%), 0 1px 3px 1px rgb(60 64 67 / 15%)"
style={{ textAlign: "center" }}
height="32rem"
width="calc(100% - 190px)"
padding="0"
margin="2%"
>
<S.BackCardGuInCir
border="none"
// bR="20px"
// bBL="0"
// bBR="0"
bPos="center"
bg={admission.programImg}
bSize="cover"
position="relative"
top="30px"
width="9rem"
height="9rem"
/>
<p
style={{
textAlign: "center",
fontSize: "20px",
lineHeight: "28px",
fontWeight: 600,
marginTop: "35px",
}}
>
{admission.programType}
</p>
<p
style={{
fontWeight: 500,
textAlign: "center",
minHeight: "40px",
}}
>
Accelerate your growth in the medical domain with the fully
managed RHIBMS school which stands at {admission.programFee}
</p>
<div
style={{
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
}}
>
<S.ApplyForThis onClick={()=> {
setProgramInstance(admission)
handleShow();
}}>
View All {admission.programType.slice(0, 3)}
</S.ApplyForThis>
<Modal
title={admission.programType}
programImg={admission.programImg}
programFee={admission.programFee}
onClose={() => setShow(false)}
show={show}
/>
</div>
My Modal component is below
<E.Modal onLoad={()=>setProgramType(`${props.title}`)} onClick={props.onClose}>
<E.ModalContent
className="animate__animated animate__bounceInUp"
onClick={(e) => e.stopPropagation()}
>
<E.ModalHeader>
<E.ModalTitle></E.ModalTitle>
</E.ModalHeader>
<E.ModalBody>
<S.BackCardGuInCir
border="none"
// bR="20px"
// bBL="0"
// bBR="0"
bPos="center"
bg={props.programImg}
bSize="cover"
position="relative"
top="0"
width="22rem"
height="22rem"
/>
<ProgramTable tuition={props.programFee} title={props.title}/>
</E.ModalBody>
<E.ModalFooter>
<E.ModalBtn onClick={props.onClose}>Close!</E.ModalBtn>
</E.ModalFooter>
</E.ModalContent>
</E.Modal>
So far, only the last object is rendering on the modal always and not updating. I'm really stuck!

react native items not align vertically center

I am trying to center the items of flatlist using alignItems but none of justifyContent, alignItems is working on this
<View style={styles.citiesContainer}>
<FlatList
data={cities}
renderItem={renderItem}
keyExtractor={item => item}
horizontal={true}
/>
</View>
// styling part
const styles = StyleSheet.create({
citiesContainer: {
height: 110,
justifyContent: 'center',
alignItems: 'center',
width: '100%',
backgroundColor: 'red'
}
}
Check those black circles in the red box in the image, I want to vertically center those circles (items)
try https://reactnative.dev/docs/flatlist#columnwrapperstyle
<FlatList
columnWrapperStyle={styles.citiesContainer}}
data={cities}
renderItem={renderItem}
keyExtractor={item => item}
horizontal={true}
/>
change the flex direction will do, try flexDirection : 'row'
const styles = StyleSheet.create({
citiesContainer: {
height: 110,
justifyContent: 'center',
alignItems: 'center',
width: '100%',
flexDirection : 'row', //this right here!! :)
backgroundColor: 'red'
}
}

React Native place a text over SVG image

I'm using libraries: "react-native-svg": "12.1.0" & "react-native-svg-transformer": "0.14.3"
import FooIcon from '../assets/images/icons/fooIcon.svg';
<View style={{ flex: 1, paddingTop: 8 }}>
<FooIcon></FooIcon>
<View style={{ position: 'absolute', top: 35, bottom: 0, left: 14, right: 0 }} >
<Text>foo</Text>
</View>
</View>
How can I have "foo" text centered over the FooIcon. The solution above does not center the text which is important because "foo" text length can change and it has to be in center in every case.
this chunk of code should do the work for you
<View
style={{
justifyContent: 'center',
alignItems: 'center'
}}
>
<SVG /> //your svg image component goes here
<Text
style={{
position: 'absolute'
}}
>
Test
</Text>
</View>
I would recommend not to use an absolute position if the content size can change dynamically. I would build this with just using flex-box:
...
<View style={styles.itemContainer}>
<Text>Foo</Text>
<View style={styles.iconMock} />
</View>
...
const styles = StyleSheet.create({
itemContainer: {
alignItems: "center",
//this has default flex: 0, which means the container will always have the size the children take.
//we then tell it to centre all the children (items) which gives the needed effect.
},
iconMock: {
backgroundColor: "blue",
height: 50,
width: 150,
}
});
Building it this way the text will always be centred:

Categories