How to make react-modal scrollable? - reactjs

Im trying to make my modal (react-modal node package) scrollable (There is an img inside)
here is my code:
content: {
position: 'absolute',
backgroundColor: '#FFF',
padding: '15px',
zIndex: '1000',
width: '90%',
borderRadius: '.5em',
},
overlay: {
position: 'fixed',
display: 'flex',
justifyContent: 'center',
top: '0',
left: '0',
width: '100%',
height: '100%',
backgroundColor: 'rgba(0,0,0, .8)',
zIndex: '1000',
overflowY: 'auto',
},
}
Modal.setAppElement('#__next')
export const langContext = React.createContext()
export default function Home() {
const [isEn, setIsEn] = useState(true)
const [modalIsOpen, setIsOpen] = useState(false)
const { width } = useWindowDimensions()
function openModal() {
setIsOpen(true)
}
function closeModal() {
setIsOpen(false)
}
function updateLang() {
setIsEn((isEn) => !isEn)
}
return (
<langContext.Provider value={{ isEn, updateLang }}>
<div id="modal" className="overflow-hidden relative">
<Header />
<Modal
isOpen={modalIsOpen}
onRequestClose={closeModal}
style={customStyles}>
<div className="relative m-h-[1000px] h-full w-full overflow-y-scroll">
{isEn ? (
<Image
layout="fill"
objectFit={width >= 750 ? 'fill' : ' cover'}
quality={100}
src={
width >= 750 ? '/assets/menu-en.png' : '/assets/Menu_en_m.png'
}
alt="Menu"
/>
) : (
<Image
layout="fill"
objectFit={width >= 750 ? 'fill' : ' cover'}
quality={100}
src={
width >= 750 ? '/assets/menu-he.png' : '/assets/Menu_he_m.png'
}
alt="Menu"
/>
)}
</div>
</Modal>
</div>
</langContext.Provider>
)
}
Any ideas on how can I do it? (I'm trying to play with the overflow and position element but I can't find the proper solution
The scrolling suppose to happen on Mobile and the Image dimensions are: 550*1550 (I can resize it if necessary)
Right now the image is cut
Thanks for the helpers!

I think your modal is good in terms of vertical scrolling, but the problem has may come from this line
objectFit={width >= 750 ? 'fill' : 'cover'}
Your mobile dimension is 500*1550 which means the image will take object-fit:cover;
You can check object-fit:cover; definition here
The image keeps its aspect ratio and fills the given dimension. The image will be clipped to fit
If you already check the dimension to load the device-respective image, you can remove the condition to check for cover.
object-fit:fill is sufficient for your case
The change can be
objectFit="fill"
Another potential problem I can see here that you have layout="fill" for that image which will make it absolute. The image container has relative which restricts the original size of your image.
To fix it, you may need to remove relative from the image container too.

Related

How to display an image for few seconds on load?

I'm trying to display an opening screen image that will last 5 seconds once the app loads. I'm using setTimeout but it won't work. Does anyone have an idea?
import OpeningScreen from '../../../../../../assets/images/OPENING_SCREEN.png';
function ProgressComponent() {
const [isOpeningScreenVisible, setOpeningScreenVisible] = useState(true)
setTimeout(() => {
setOpeningScreenVisible(false);
}, 5000);
return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
}}
>
{isOpeningScreenVisible && <img src={OpeningScreen} className="image" />}
</div>
);
}
export default ProgressComponent;```
Try changing the img src.
From
{isOpeningScreenVisible && <img src={OpeningScreen} className="image" />}
To this
{isOpeningScreenVisible && <img src={OpeningScreen.src} className="image" />}
I've tested your code and it works fine. try these:
check your image path and be sure it's correct.
check and see if there is any error in the console and fix all of them.
maybe the loading time is taking more time than 5000ms. try 10000ms for showing the image.
You can update your code to use native events so you don't have to re-invent the wheel.
What i would do:
import OpeningScreen from '../../../../../../assets/images/OPENING_SCREEN.png';
function ProgressComponent() {
return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
}}
>
<img
src={OpeningScreen}
alt="opening screen"
onLoad={e => {
console.log("init event")
setTimeout(() => (e.target as HTMLImageElement).remove(), 5000)
}}
/>
</div>
);
}
export default ProgressComponent;
Anyway, this isn't the best approach. The best you can do is to use css transitions to animate just an opening screen
function App() {
const [loading, setLoading] = useState(false);
document.onreadystatechange = function () {
if (document.readyState !== "complete") {
setLoading(true);
} else if (document.readyState === "complete") {
setTimeout(() => {
setLoading(false);
}, 5000);
}
};
return (
<div style={{ background: "black" }}>
{loading && (
<div id="loadingScreen">
<img src={OpeningScreen} className="image" />
</div>
)}
{!loading && (
<div className="App" id="app"></div>
</div>
Try this It should work as it is still working in one of my project
The Basic Idea is the <img src={openingScreen}/> will be on the screen untill the react build file is loaded to on the site.
Add the everything inside <div className="App" id="app"></div> once they are loaded the image will fade.

Showing prohibition Icon even in dragging time and need an empty space on dragged slide

I am using drag and drop in my project for slides. What I done is drag a slide and swap slide position with other.It works perfectly. But the issue is the symbol
comes even if it is allow to drag .I want to remove this icon and show drag icon while draging.Also I need an empty space on dragged slide. My code is
onDragStart = (event, index) => {
this.draggedItem = this.state.slides[index];
event.dataTransfer.setDragImage(event.target.parentNode, 20, 20);
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.setData("text/html", event.target.parentNode);
};
onDragOver = index => {
const { slides } = this.state;
const hoveredItem = slides[index];
if (this.draggedItem === hoveredItem) {
return;
}
const filteredItems = slides.filter(item => item !== this.draggedItem);
filteredItems.splice(index, 0, this.draggedItem);
this.setState({ slides: filteredItems });
};
onDragEnd = () => {
this.draggedIdx = null;
};
<div className="draggableList">
<div key={data} onDragOver={() => onDragOver(index)}>
<div className="handle"
draggable
onDragStart={event => onDragStart(event, index)}
onDragEnd={onDragEnd}>
<div class="d-flex justify-content-center" style={{ fontWeight: "bold", paddingTop: "20px" }}>{"Slide " + (index + 1)}</div>
<div className={"py-3 d-flex justify-content-center course_slide slide_" + index}>
<div style={{ backgroundColor: 'white', height: 150, width: 120, boxShadow: '4px 4px 5px grey', cursor: 'pointer', overflowY: 'hidden', border: selected ? '2px solid limegreen' : '', position: 'relative' }} onClick={onClick}>
<h1 style={{ fontSize: 7 }}>{data.title}</h1>
<div style={{ fontSize: 4 }} dangerouslySetInnerHTML={{ __html: data.description }}>
</div>
{onDelete && <div onClick={onDelete} style={{ padding: 4, position: 'absolute', bottom: 0, right: 0 }}><DeleteOutline /></div>}
</div>
</div>
</div>
</div>
</div>
Can anyone please help me to sort out this issue?

is it possible to animate a strikethrough with React Spring?

I'm new to React Spring and I initially tried this
const strikeProps = useSpring({
textDecoration: "line-through",
from: { textDecoration: "none" },
});
But it's not working. I think there should be a way simulate the CSS solution for this.
The problem here is, that the original CSS solution is uses pseudo element for emulating the strike trough. We can only add react-spring properties for normal html elements. So the most compact way is to create a separate strike through component for this problem. For example:
const StrikeTroughtText = ({ children, weight = 1 }) => {
const props = useSpring({
from: { width: "0%" },
to: { width: "100%" }
});
return (
<div style={{ position: "relative", display: "inline-block" }}>
{children}
<animated.div
style={{
position: "absolute",
top: "50%",
left: 0,
width: props.width,
height: `${weight}px`,
background: "black"
}}
/>
</div>
);
};
We basically animate the width of the absolutely positioned div containing a black line over the text.
You can use it like a div component:
<StrikeTroughtText>text</StrikeTroughtText>
For bigger font size the default 1 px line weight is not enough, so I added a weight property also.
Here is my example: https://codesandbox.io/s/react-strike-trought-text-component-with-react-spring-animation-86cfd?file=/src/App.js

Linking to a different page using react-day-picker and react router v4

I'm trying to utilize this example in order to create a calendar that lists out the events in the current month, I have this part working, but what I have yet to figure out is how to make it so that the user can click the event name and it would take them to that event page.
So per that example, if they click on one of the birthdays, it would take them to an events page where they could see more about that birthday.
Currently, my events page is being rendered using this function:
renderEvents() {
const {events} = this.state
this.state.events = {};
let eventItems = this.state.eventGet.map(event => {
console.log(event.id)
if(typeof(events[moment(event.date).date()]) !== "undefined") {
events[moment(event.date).date()].push(event.name)
} else {
events[moment(event.date).date()] = [event.name]
}
});
function renderDay(day) {
const date = day.getDate();
const dateStyle = {
position: 'absolute',
color: 'lightgray',
bottom: 0,
right: 0,
fontSize: 20,
};
const containerStyle = {
margin:'2px',
border: '1px solid #3a87ad',
borderRadius: '3px',
position: 'relative',
display: 'block',
cursor: 'pointer'
};
const textStyle = {
fontSize: '0.8em',
textAlign: 'left',
margin: '1.5px',
}
const cellStyle = {
height: 150,
width: 160,
position: 'relative',
};
return (
<div style={cellStyle}>
<div style={dateStyle}>{date}</div>
{events[date] &&
events[date].map((name, i) => (
<div onClick={() => this.props.history.push('/organizations/' + this.props.match.params.orgID + '/events' + i)} key={i} style={containerStyle}>
<div style={textStyle}> {name} </div>
</div>
))}
</div>
);
}
return (
<div>
<Grid component="section" className="section--center" shadow={0} noSpacing>
<Cell col={12}>
<FABButton style={{margin: '10px', float: "right"}} colored ripple onClick={() => this.props.history.push('/organizations/' + this.props.match.params.orgID + '/events')}>
<Icon name="add" />
</FABButton>
</Cell>
<DayPicker
canChangeMonth={true}
className="Birthdays"
renderDay={renderDay}
/>
</Grid>
</div>
);
}
The current problem is within the sub-function, renderDay which is called by the DayPicker component that gets the events associated with the day. When I try to push to the history property, it errors out and says that I cannot read property 'history' from undefined, which makes sense because we did not pass the history property to that function.
Can someone help me in figuring out how to modify that sub-function so that the onClick event on the div will take a user to that events page?
and says that I cannot read property 'history' from undefined
Make sure your renderDay function is bound to the correct this:
<DayPicker
canChangeMonth
className="Birthdays"
renderDay={renderDay.bind(this)}
/>

Put a PNG image over a background image

I'm trying to replicate http://www.milkbardigital.com.au/ as a learning project in react.
Currently I'm struggling to get the PNG image over the top of the background image.
Here's my code,
import React from 'react';
import {Image} from 'react-bootstrap';
export default React.createClass ( {
render() {
var background = {backgroundSize : 'cover'};
var textStyle = {
position: 'absolute',
top: '50%',
left: '50%'
};
return (
<div style={{width: 'auto'}}>
<Image
style={background} responsive
src="http://www.milkbardigital.com.au/wp-content/uploads/2015/11/Milkbar-Home-Background.jpg">
</Image>
<h1 style={textStyle}>Agile Media Content</h1>
</div>
);
}
});
<Image src="http://www.milkbardigital.com.au/wp-content/uploads/2015/11/Milkbar-Digital-Media.png" responsive/>
This "Image src" I've tried to place inside the above code but it won't work.
Anyone able to work this out?
It's with React Bootstrap!
Thanks,
Edit - - -
I've worked out how to get it slightly on top, now trying to get it put in the right position.
This is the code, ignore the opacity part,
/**
* Created by Hewlbern on 21-Jan-17.
*/
import React from 'react';
import {Image} from 'react-bootstrap';
export default React.createClass ( {
render() {
var background = {backgroundSize : 'cover',
opacity: '0.5',
};
var textStyle = {
position: 'absolute',
top: '50%',
left: '50%'
};
var ontop = {
display: 'block',
margin: 'auto',
width: '50%',
};
return (
<div style={{width: 'auto'}}>
<Image
style={background} responsive
src="http://www.milkbardigital.com.au/wp-content/uploads/2015/11/Milkbar-Home-Background.jpg">
</Image>
<h1 style={textStyle}>Agile Media Content</h1>
<Image style={textStyle} responsive src="http://www.milkbardigital.com.au/wp-content/uploads/2015/11/Milkbar-Digital-Media.png" />
</div>
);
}
});

Resources