Skip to content

Commit

Permalink
fix(picture): add loading transition to Picture
Browse files Browse the repository at this point in the history
  • Loading branch information
morewings committed May 31, 2024
1 parent 7ce275c commit 84fb78f
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 31 deletions.
19 changes: 19 additions & 0 deletions src/lib/Picture/Picture.module.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
.wrapper {
height: var(--height);
max-height: 100%;
max-width: 100%;
position: relative;
width: var(--width);
}

.picture {
max-height: 100%;
max-width: 100%;
transition: opacity var(--fg-time-sm) ease-in;

& img {
display: block;
height: auto;
max-height: inherit;
max-width: inherit;
}

&.loading {
opacity: 0;
}
}

.skeleton {
left: 0;
position: absolute;
top: 0;
}
4 changes: 4 additions & 0 deletions src/lib/Picture/Picture.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ export const Primary: Story = {
};

export const Responsive: Story = {
parameters: {
// More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
layout: 'fullscreen',
},
render: args => {
return <Picture {...args} />;
},
Expand Down
72 changes: 45 additions & 27 deletions src/lib/Picture/Picture.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type {DetailedHTMLProps, ImgHTMLAttributes} from 'react';
import {forwardRef} from 'react';
import {useCallback, forwardRef, useState} from 'react';
import classNames from 'classnames';

import type {DataAttributes, LibraryProps} from '@/internal/LibraryAPI';
import {SkeletonShape} from '@/lib/Skeleton';

import classes from './Picture.module.css';

Expand Down Expand Up @@ -103,34 +104,51 @@ export type Props = DataAttributes &

export const Picture = forwardRef<HTMLDivElement, Props>(
({className, alt, src, sources, width, height, loading = 'lazy', ...nativeProps}, ref) => {
const [isLoaded, setLoaded] = useState(false);
const handleLoad = useCallback(() => {
setLoaded(true);
}, []);
return (
<picture {...nativeProps} className={classNames(classes.picture, className)} ref={ref}>
{sources?.map(
({
src,
mediaCondition,
density = '1x',
intrinsicWidth,
slotWidth = '',
type,
width: srcWidth,
height: srcHeight,
}) => {
const srcParam = intrinsicWidth ?? density;
return (
<source
type={type}
srcSet={`${src} ${srcParam}`}
media={`${mediaCondition} ${slotWidth}`}
width={srcWidth}
height={srcHeight}
key={src}
/>
);
}
<div className={classes.wrapper}>
<picture
{...nativeProps}
className={classNames(
classes.picture,
{[classes.loading]: !isLoaded},
className
)}
ref={ref}
onLoad={handleLoad}>
{sources?.map(
({
src,
mediaCondition,
density = '1x',
intrinsicWidth,
slotWidth = '',
type,
width: srcWidth,
height: srcHeight,
}) => {
const srcParam = intrinsicWidth ?? density;
return (
<source
type={type}
srcSet={`${src} ${srcParam}`}
media={`${mediaCondition} ${slotWidth}`}
width={srcWidth}
height={srcHeight}
key={src}
/>
);
}
)}
<img width={width} height={height} loading={loading} src={src} alt={alt} />
</picture>
{!isLoaded && (
<SkeletonShape width={width} height={height} className={classes.skeleton} />
)}
<img width={width} height={height} loading={loading} src={src} alt={alt} />
</picture>
</div>
);
}
);
Expand Down
4 changes: 4 additions & 0 deletions src/lib/Skeleton/Skeleton.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
color-mix(in srgb, var(--fg-color-sol) 22%, transparent);
height: var(--height);
margin: calc(var(--margin-y) * 1px) calc(var(--margin-x) * 1px);
max-height: 100%;
max-width: 100%;
padding: calc(var(--fg-size-unit) * 3);
width: var(--width);
}
Expand Down Expand Up @@ -37,6 +39,8 @@
border-radius: calc(var(--border-radius) * 1px);
height: var(--height);
margin: calc(var(--margin-y) * 1px) calc(var(--margin-x) * 1px);
max-height: 100%;
max-width: 100%;
width: var(--width);
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/Skeleton/SkeletonFrame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const SkeletonFrame = forwardRef<HTMLDivElement, Props>(
children,
className,
width = 'fluid',
height = 'fluid',
height,
borderRadius = 12,
marginY = 0,
marginX = 0,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/Skeleton/SkeletonShape.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const SkeletonShape = forwardRef<HTMLDivElement, Props>(
{
className,
width = 'fluid',
height = 'fluid',
height,
borderRadius = 6,
marginY = 0,
marginX = 0,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/Skeleton/SkeletonText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const SkeletonText = forwardRef<HTMLDivElement, Props>(
{
className,
width = 'fluid',
height = 'fluid',
height,
lines: linesProp = 3,
marginY = 36,
marginX = 0,
Expand Down
4 changes: 3 additions & 1 deletion src/lib/Skeleton/normalizeUnit.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type {Unit} from './SkeletonTypes.ts';

export const normalizeUnit = (unitProp?: Unit) => {
if (unitProp === 'fluid' || unitProp === undefined) {
if (unitProp === undefined) {
return 'auto';
} else if (unitProp === 'fluid') {
return '100%';
}
return `${unitProp}px`;
Expand Down

0 comments on commit 84fb78f

Please sign in to comment.