How to control scrolling of component in React? - css

I have 4 main components for my React portfolio site called Home, Portfolio, About, Contact. The components are linked in Navigation. If I click on those link, Component appears. But the problem is if I scroll the Portfolio page 50% and click on About. The About page stay automatically scrolled top by 50%. I don't want an automated scroll. Rather I want the component will start from top 0;
I have tried "css-snap-type" but it doesn't work.
How can I solve the problem?

you could solve this using a react component that will scroll the window up everytime you click on a different link.
checkout this documentation is pretty straight forward https://reactrouter.com/web/guides/scroll-restoration
If you are using gatsby it comes with and API called called shouldUpdateScroll you could implement it on the gatsby.browser.js
const transitionDelay= 500
exports.shouldUpdateScroll = ({
routerProps: { location }, //location
getSavedScrollPosition, //last position on the previous page
}) => {
if(location.action === 'PUSH'){
window.setTimeout(()=> window.scrollTo (0,0), transitionDelay)
}
else {
const savedPosition = getSavedScrollPosition(location)
window.setTimeout(
()=> window.scrollTo((savedPosition || [0,0])),
transitionDelay
)
}
return false
}

U need to set window.scrollTo(0, 0) when u click on link so it would start on top of page.

Related

Lenis smooth scroll preventing Next Links default behaviour of scrolling to top of page on route change

I am building a Next app where I have implemented smooth scrolling with Lenis. Everything is working perfectly apart from when you navigate between pages using nexts link element. The scroll position just remains where it was before the route change instead of the default behaviour of linking to the top of the page. If I remove Lenis then it works properly so it must be that which is causing the issue.
Has anyone else ran into this problem and know a work around for it?
The code snippet below shows how I have set up Lenis in my _app.js file.
Any help would be greatly appreciated.
useIsomorphicLayoutEffect(() => {
const lenis = new Lenis({
duration: 2.5,
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t))
})
function raf(time) {
lenis.raf(time)
requestAnimationFrame(raf)
}
requestAnimationFrame(raf)
}, []);

cypress can't take screenshot of iFrame and it's elements?

i want to do visual testing with cypress-image-diff. So far, so good. I can take and compare screenshots of the complete page, but never of the element itself, as they are in an iFrame. With help of cypress-iframe I can check e.g. name, stype etc of the element. But screenshots are always taken from another area. Pls help
verifyLogoShown() {
cy.log("Verify if diconium logo is visible");
cy.frameLoaded(this.IFRAME)
// after the frame has loaded, we can use "cy.iframe()"
// to retrieve it
cy.iframe().find(this.TEST_OBJECT).should('have.text', 'Styled Button - primary') // works. I can test all kinds of CSS or other values from the button TEST_OBJECT
cy.wait(1000);
cy.getIframeBody(this.IFRAME).find(this.TEST_OBJECT).should('have.text', "Styled Button - primary")
cy.getIframeBody(this.IFRAME).type("a")
cy.compareSnapshot('button (replaceable)');
//doesn't take screenshot of that part I expect (e.g. iFrame box or button itself, instead of the menu part on the left)
}
My commands.js
Cypress.Commands.add('getIframeDocument', (iFrameSelector) => {
return cy
.get(iFrameSelector)
.its('0.contentDocument');
})
Cypress.Commands.add('getIframeBodyOtherWay', (iFrameSelector) => {
return cy
.getIframeDocument(iFrameSelector).should('exist').its('body').should('not.be.undefined')
.then(cy.wrap);
})
Cypress.Commands.add("getIframeBody", (framename) => {
// get the iframe > document > body
// and retry until the body element is not empty
return cy
.get(framename)
.its('0.contentDocument.body').should('not.be.empty')
// wraps "body" DOM element to allow
// chaining more Cypress commands, like ".find(...)"
// https://on.cypress.io/wrap
.then(cy.wrap);
});

How to move elements on scroll in React.js?

I am trying to create an E-commerce Store and I'm a beginner in React.JS. What I want is for 5 images to come together on top of eachother when the user scrolls. (so they should move TranslateX on scroll). Previously, on Vanilla Javascript I would have added a window.addEventListener('scroll') and then set a value like value = window.scrollY and then I would have selected the image I wanted to move and simply translateX or Y based on that value.
However, I'm not sure how to do this in React. Where can I set the window event listener? Is there a state needed, or useEffect?
I'm attaching an image so you can clearly see what I am trying to do:
What I have in react is the "Scroll" component which contains 2 divs
-1 div on the left 2/3 flex size containing all the images that should come together
-1 div on the right 1/3 flex size containing the text and the button
inside the left div I have 5 images, and in CSS i've used position absolute to position them on top of eachother (they are all PNGs so they have transparent background).
How would I go about implementing this on my website?
HUGE thanks in advance!
You can save the scrollY in a useState, which you then use to transofrm your images. The window listeners can be loaded inside a useEffect.
It (could) look like this:
const [scrollY, setScrollY] = useState(0);
useEffect(() => {
const handleScroll = () => {
setScrollY(window.scrollY);
};
handleScroll();
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
(You may have to add some ESLint rules if you use it)

Replace default play button on Brightcove's Smart Player on mobile devices

Quite likely I just need the right terms to find the answer; however, I imagine someone else has already encountered this problem and knows right away how to solve it.
I'm using Brightcove's services and their Smart Player. I've configured a Chromeless player and tried to eliminate ALL controls because my page's controls will use their API to play, pause, etc. On desktop, this works just ok. On mobile devices (iOS7 Safari) there is a play button overlay on the video player that I'd like to replace with my own graphic.
I'd like to turn this:
into this:
Anyone know how to do this? I can't just reach into the player with JavaScript because it's in an iframe filled by Brightcove services.
You can do this with a javascript player plugin, which runs inside the player iframe. Use the overlay API to create your custom play button and playOverlayCallbacks() to prevent the default play overlay from being displayed.
Something like this would work in a plugin:
(function() {
function addPlayOverlay() {
var overlay = videoPlayer.overlay();
$(overlay).css('background', 'transparent url("http://example.com/playbutton.png") no-repeat center center')
.width($(document).width())
.height($(document).height())
.css("-webkit-box-shadow","inset 0 0 150px rgba(0,0,0,0.9)")
;
$(overlay).click(function(){
// Play when custom overlay is clicked
videoPlayer.play();
});
videoPlayer.playOverlayCallbacks({
show: function() {
// Show custom overlay
$(overlay).fadeIn();
// Prevent standard play overlay
return false;
},
hide: function() {
// Hide play overlay
$(overlay).fadeOut();
return false;
}
});
}
var
bcplayer = brightcove.api.getExperience(),
videoPlayer = bcplayer.getModule(brightcove.api.modules.APIModules.VIDEO_PLAYER),
experience = bcplayer.getModule(brightcove.api.modules.APIModules.EXPERIENCE);;
if (experience.getReady()) {
addPlayOverlay();
} else {
experience.addEventListener(brightcove.player.events.ExperienceEvent.TEMPLATE_READY, addPlayOverlay);
}
}());

Adding css with jQuery based on class

Seeking a solution to my problem...
I partially found an answer from another thread on here, using this script
$(function () {
$(".myclass").hover(function ()
{}, function ()
{
$(".myclass>li").fadeTo(200, 1)
});
$(".myclass>li").hoverIntent(function ()
{
$(this).attr("id", "current");
$(this).siblings().fadeTo(200, .6);
$(this).fadeTo(300, 1)
}, function ()
{
$(".myclass>li").removeAttr("id");
$(this).fadeTo(200, 1)
})})
When an item in the list is hovered, the script fades all other items out. Original demo is here http://jsbin.com/usobe
This works OK on my site, though the list ( a grid of thumbnails) is part of a bigger slider script, which loads "previews" via ajax. When a list item is clicked a hidden section expands on the page, and the slider script assigns the list item a class "active".
When the hidden section is open I would like the activated thumbnail to remain at 1 opacity, while the rest are faded to .6, exactly as it is with the hover effect using the script above. What I am trying to achieve becomes obvious when you click a thumbnail to activate the ajax script. Is it possible to use the active class to make this happen i.e. if class is not active set to .6 opacity?
Thanks in advance
----EDIT
Thanks everyone for suggestions - I am not having much luck so far! Using the code above, would it be possible to modify it so that when a list item is clicked it holds the specified levels of opacity? That would do nicely, I think. Then I could use onclick I guess to fade all items back to full opacity when the hidden div is closed.
I'm trying to guess how your code work, for what I understand you should do something like this:
// this is the selector that gets the click on the thumbnail
$('li.item').click(function() {
// fade all the thumbnails to op 1.0
$('#li.item').css('opacity', '.6');
// let the active thumbnail to 1.0
$(this).css('opacity', 1);
//show your hidden div
});
Then, when you close the hidden div:
$('div#hiddenDiv').onClose(function()
// about to close
$(this).fadeTo('fast', 1);
});
You could use an on click targeting the zetaThumbs li elements, set the current target to 1 and its siblings to .6
$('.zetaThumbs li').click(function(){
$(this).css({'opacity':1}).siblings().css({'opacity':.6});
})

Resources