Created
July 12, 2024 14:43
-
-
Save danieljpgo/44258925964f38cca9411dae7f713596 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { type ImageProps, getImageProps } from "next/image"; | |
type DynamicImageProps = Omit<React.ComponentProps<"img">, "src"> & { | |
alt: string; | |
src: ImageProps["src"]; | |
srcMobile: ImageProps["src"]; | |
srcTablet: ImageProps["src"]; | |
srcDesktop: ImageProps["src"]; | |
priority?: ImageProps["priority"]; | |
quality?: ImageProps["quality"]; | |
placeholder?: ImageProps["placeholder"]; | |
}; | |
/** | |
* `<DynamicImage/>` should be used to render different images depending on the size of the viewport. | |
* | |
* To learn more: | |
* | |
* https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#art_direction | |
* | |
* @example | |
* ```tsx | |
* return ( | |
* <DynamicImage | |
* className="h-full w-full object-cover object-center" | |
* alt="alt description" | |
* src={imageDesktop} | |
* srcDesktop={imageDesktop} | |
* srcTablet={imageTablet} | |
* srcMobile={imageMobile} | |
* quality={100} | |
* priority | |
* /> | |
* ); | |
* ``` | |
* If you do not have specific images for one of the viewport sizes, you can repeat the src: | |
* @example | |
* ```tsx | |
* return ( | |
* <DynamicImage | |
* ... | |
* src={imageDesktop} | |
* srcDesktop={imageDesktop} | |
* srcTablet={imageDesktop} | |
* srcMobile={imageMobile} | |
* ... | |
* /> | |
* ); | |
* ``` | |
*/ | |
export function DynamicImage(props: DynamicImageProps) { | |
const { | |
alt, | |
srcMobile, | |
srcTablet, | |
srcDesktop, | |
quality, | |
priority, | |
placeholder, | |
...attrs | |
} = props; | |
const mobile = getImageProps({ | |
quality, | |
priority, | |
alt, | |
placeholder, | |
src: srcMobile, | |
...(attrs.width && { width: Number(attrs.width) }), | |
...(attrs.height && { height: Number(attrs.height) }), | |
}); | |
const tablet = getImageProps({ | |
quality, | |
priority, | |
alt, | |
placeholder, | |
src: srcTablet, | |
...(attrs.width && { width: Number(attrs.width) }), | |
...(attrs.height && { height: Number(attrs.height) }), | |
}); | |
const desktop = getImageProps({ | |
quality, | |
priority, | |
alt, | |
placeholder, | |
src: srcDesktop, | |
...(attrs.width && { width: Number(attrs.width) }), | |
...(attrs.height && { height: Number(attrs.height) }), | |
}); | |
return ( | |
<picture> | |
<source media="(min-width: 1280px)" srcSet={desktop.props.srcSet} /> | |
<source media="(min-width: 768px)" srcSet={tablet.props.srcSet} /> | |
<source srcSet={mobile.props.srcSet} /> | |
<img alt={alt} {...attrs} {...desktop.props} /> | |
</picture> | |
); | |
} | |
// @TODO: document props |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment