Commit 4e07b742 by Moorthy G

feat(responsive-image): add ResponsiveImage component

parent 387b17a2
import ResponsiveImage from './ResponsiveImage';
import type { ResponsiveImageProps } from './ResponsiveImage';
export default {
title: 'Shared/ResponsiveImage',
component: ResponsiveImage,
parameters: {
layout: 'fullscreen'
},
tags: ['autodocs']
};
export const Image = {
args: {
src: 'https://dummyimage.com/1920x570',
width: 1920,
height: 570,
sizes: '100vw'
}
};
export const ArtDirection = {
args: {
src: 'https://dummyimage.com/576x540',
width: 576,
height: 540,
sizes: '100vw'
},
render: (args: ResponsiveImageProps) => (
<ResponsiveImage {...args}>
<ResponsiveImage.Source
media="xxl"
src="https://dummyimage.com/1920x540"
width={1920}
height={540}
sizes="100vw"
/>
<ResponsiveImage.Source
media="xl"
src="https://dummyimage.com/1536x540"
width={1536}
height={540}
sizes="100vw"
/>
<ResponsiveImage.Source
media="lg"
src="https://dummyimage.com/1280x540"
width={1280}
height={540}
sizes="100vw"
/>
<ResponsiveImage.Source
media="md"
src="https://dummyimage.com/1024x540"
width={1024}
height={540}
sizes="100vw"
/>
<ResponsiveImage.Source
media="sm"
src="https://dummyimage.com/768x540"
width={768}
height={540}
sizes="100vw"
/>
<ResponsiveImage.Source
media="(min-width: 576px)"
src="https://dummyimage.com/640x540"
width={640}
height={540}
sizes="100vw"
/>
</ResponsiveImage>
)
};
import { memo } from 'react';
import React from 'react';
import { getImageProps } from 'next/image';
import breakpoints from './breakpoints';
export type Image = {
url: string;
width: number;
height: number;
alternativeText?: string;
};
export interface ResponsiveImageProps
extends React.HTMLAttributes<HTMLImageElement> {
src: string;
width: number;
height: number;
sizes: string;
alt?: string;
priority?: boolean;
quality?: number;
children?: React.ReactNode;
}
export interface SourceProps extends React.HTMLAttributes<HTMLSourceElement> {
src: string;
width: number;
height: number;
media: string;
sizes: string;
quality?: number;
}
export const ResponsiveImage: React.FC<ResponsiveImageProps> & {
Source: React.FC<SourceProps>;
} = ({
src,
width,
height,
alt,
sizes,
quality,
priority,
children,
...rest
}) => {
if (src) {
const { props } = getImageProps({
src,
width,
height,
sizes,
quality,
priority,
alt: alt || ''
});
return (
<picture>
{children}
<img alt="" {...props} {...rest} />
</picture>
);
}
};
ResponsiveImage.Source = memo(
({ src, width, height, sizes, media, quality, ...rest }: SourceProps) => {
if (src) {
const query = breakpoints[media] || media;
const { props } = getImageProps({
width,
height,
src,
sizes,
quality,
alt: ''
});
return (
<source
media={query}
src={props.src}
srcSet={props.srcSet}
width={props.width}
height={props.height}
sizes={props.sizes}
{...rest}
/>
);
}
}
);
ResponsiveImage.displayName = 'ResponsiveImage';
ResponsiveImage.Source.displayName = 'ResponsiveImageSource';
export default ResponsiveImage;
type Breakpoints = {
[key: string]: string;
};
const breakpoints: Breakpoints = {
sm: '(min-width: 640px)',
md: '(min-width: 768px)',
lg: '(min-width: 1024px)',
xl: '(min-width: 1280px)',
xxl: '(min-width: 1536px)'
};
export default breakpoints;
export * from './ResponsiveImage';
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment