I am attempting to build an image slider using Gatsby JS (SSG) and framer motion. I am running into an issue where images which are not visible on the page (all tabs aside from tab 1) are not being pre-rendered, despite GatsbyImage being provided with the loading="eager" prop.
I have built an image provider to query for images in the image slider:
const ImageProvider = ({ fileName, alt, imgStyle, style, loading, placeholder }) => {
const { allImageSharp } = useStaticQuery(graphql`
{
allImageSharp {
nodes {
parent {
... on File {
base
}
}
gatsbyImageData
}
}
}
`)
const image = allImageSharp.nodes.find(node => node.parent.base === fileName).gatsbyImageData;
if (!image) return null;
return (
<GatsbyImage image={image} alt={alt} imgStyle={imgStyle} style={style} loading={loading} placeholder={placeholder} />
)
}
export default ImageProvider;
Here is the image slider:
export const TabSlider = ({
tabs,
}) => {
const [[page, direction], setPage] = useState([0, 0]);
const elementRef = useRef(null);
const elementSize = useElementSize(elementRef);
// We only have 3 images, but we paginate them absolutely (ie 1, 2, 3, 4, 5...) and
// then wrap that within 0-2 to find our image ID in the array below. By passing an
// absolute page index as the `motion` component's `key` prop, `AnimatePresence` will
// detect it as an entirely new image. So you can infinitely paginate as few as 1 images.
// const imageIndex = wrap(0, images.length, page);
const paginate = (newDirection) => {
setPage([page + newDirection, newDirection]);
};
return (
<Container>
<ImageProvider style={{ width: "100%" }} alt="" loading="eager" placeholder="none" />
<AnimateSharedLayout>
<TabsContainer>
<TabsHeader>
{tabs.map(({ title }, i) => {
const isActive = i === page;
return (
<TabItem
key={i}
className={isActive ? "active-header" : ""}
onClick={() => {
// set page and determine which direction we're going
setPage([i, i - page]);
}}
>
<TabHeaderContainer>
<TabHeader>{title}</TabHeader>
</TabHeaderContainer>
{isActive && (
<Underline as={motion.div} layoutId="underline" />
)}
</TabItem>
);
})}
<UnderlineBg />
</TabsHeader>
</TabsContainer>
<ContentContainer>
<AnimatePresence initial={false} custom={direction}>
<Section
as={motion.section}
ref={elementRef}
key={page}
custom={direction}
variants={variants}
initial="enter"
animate="center"
exit="exit"
transition={{
x: { type: "spring", stiffness: 300, damping: 30, duration: 2 },
opacity: { duration: 0.2 }
}}
drag="x"
dragConstraints={{ left: 0, right: 0 }}
dragElastic={1}
onDragEnd={(e, { offset, velocity }) => {
const swipe = swipePower(offset.x, velocity.x);
if (swipe < -swipeConfidenceThreshold) {
paginate(1);
} else if (swipe > swipeConfidenceThreshold) {
paginate(-1);
}
}}
>
<Background height={elementSize.height} />
<Wrapper>
<SlideContainer ref={elementRef}>
<CopywritingContainer>
<H2Header>{tabs[page].header}</H2Header>
<Text>{tabs[page].text}</Text>
</CopywritingContainer>
<ImageContainer>
<ImageProvider fileName={tabs[page].imageFilename} style={{ width: "50%" }} alt="" loading="eager" placeholder="none" />
</ImageContainer>
</SlideContainer>
</Wrapper>
</Section>
</AnimatePresence>
</ContentContainer>
</AnimateSharedLayout>
</Container>
);
};
I can't see where I am going wrong here and would greatly appreciate any guidance.
Thank you!
Does not appear to be possible using gatsby-plugin-image at this current time. Achieved by using traditional HTML image tags.