PageImage
A flexible image component with loading states, fallback support, and various display options.
Installation
npm install @pagedotapp/page-image
Usage
import { PageImage } from "@pagedotapp/page-image"
function App() {
return (
<PageImage
src="/path/to/image.jpg"
alt="Description of image"
width={400}
height={300}
fallback={<div>Failed to load</div>}
/>
)
}
Props
src | string | - | Image source URL (required) |
alt | string | - | Alternative text for accessibility (required) |
fallback | React.ReactNode | Default icon | Fallback content when image fails to load |
fallbackSrc | string | - | Fallback image URL to try if main src fails |
width | string | number | - | Width of the image container |
height | string | number | - | Height of the image container |
fit | ImageFit | 'cover' | Object fit behavior (contain, cover, fill, none, scale-down) |
aspectRatio | ImageAspectRatio | 'auto' | Aspect ratio (auto, square, 4/3, 16/9, 21/9, 9/16, 3/4) |
loading | 'eager' | 'lazy' | 'lazy' | Loading strategy |
showSkeleton | boolean | true | Whether to show loading skeleton |
rounded | boolean | false | Whether the image should be rounded |
circle | boolean | false | Whether the image should be circular |
radius | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Border radius size (when rounded) |
className | string | '' | Additional CSS class name for the image |
containerClassName | string | '' | Additional CSS class name for the container |
onLoad | function | - | Called when image loads successfully |
onError | function | - | Called when image fails to load |
fadeIn | boolean | true | Whether to fade in on load |
onClick | function | - | Click handler for the image |
Examples
Basic Usage
<PageImage src="https://example.com/photo.jpg" alt="Example photo" />
With Dimensions and Aspect Ratio
<PageImage
src="/hero-image.jpg"
alt="Hero image"
width={800}
height={400}
/>
<PageImage
src="/photo.jpg"
alt="Photo"
aspectRatio="16/9"
width="100%"
/>
<PageImage
src="/avatar.jpg"
alt="User avatar"
aspectRatio="square"
width={200}
/>
Object Fit Options
<PageImage
src="/banner.jpg"
alt="Banner"
fit="cover"
aspectRatio="21/9"
/>
<PageImage
src="/logo.png"
alt="Logo"
fit="contain" // Maintains aspect ratio within container
width={200}
height={100}
/>
Shape Variants
<PageImage
src="/avatar.jpg"
alt="User avatar"
circle
width={100}
height={100}
/>
<PageImage
src="/card-image.jpg"
alt="Card image"
rounded
radius="lg"
/>
Loading States
<PageImage
src="/slow-loading.jpg"
alt="Slow loading image"
showSkeleton
/>
<PageImage
src="/fast-loading.jpg"
alt="Fast loading image"
showSkeleton={false}
/>
<PageImage
src="/hero.jpg"
alt="Hero image"
loading="eager"
/>
Error Handling
<PageImage
src="/might-fail.jpg"
alt="Image that might fail"
fallback={
<div style={{ padding: '2rem', textAlign: 'center' }}>
<p>Unable to load image</p>
<button>Retry</button>
</div>
}
/>
<PageImage
src="/primary-image.jpg"
alt="Product photo"
fallbackSrc="/placeholder.jpg"
/>
<PageImage
src="/tracked-image.jpg"
alt="Tracked image"
onLoad={() => console.log('Image loaded successfully')}
onError={() => console.log('Image failed to load')}
/>
Interactive Images
<PageImage
src="/clickable.jpg"
alt="Click to enlarge"
onClick={(e) => console.log('Image clicked')}
style={{ cursor: 'pointer' }}
/>
<PageImage
src="/gallery-item.jpg"
alt="Gallery item"
onClick={() => openLightbox()}
rounded
fadeIn
/>
Advanced Examples
<PageImage
src={product.imageUrl}
alt={product.name}
fallbackSrc="/product-placeholder.jpg"
aspectRatio="4/3"
fit="contain"
rounded
radius="md"
fadeIn
loading="lazy"
onClick={() => setShowZoom(true)}
className="product-image"
containerClassName="product-image-container"
/>
<PageImage
src={user.avatarUrl}
alt={`${user.name}'s avatar`}
fallback={
<div className="avatar-fallback">
{user.name.charAt(0)}
</div>
}
circle
width={60}
height={60}
/>
<PageImage
src="/hero-banner.jpg"
alt="Welcome to our site"
aspectRatio="21/9"
fit="cover"
loading="eager"
showSkeleton
fadeIn={false} // No fade for hero images
onLoad={() => setHeroLoaded(true)}
/>
Default Fallback
When an image fails to load and no custom fallback is provided, the component displays a default fallback with:
- A subtle image icon
- The alt text as a caption
- Proper styling to match your design
TypeScript
The component exports the following types:
import type {
PageImageProps,
ImageFit,
ImageAspectRatio,
ImageLoadingStrategy,
} from "@pagedotapp/page-image"
Styling
The component uses CSS modules for styling. You can override styles by:
- Passing a custom
className for the image element
- Passing a custom
containerClassName for the container
- Targeting the component's CSS classes in your global styles
Accessibility
- Always provide meaningful
alt text
- When using
onClick, the component automatically adds role="button" and tabIndex={0}
- The component maintains proper aspect ratios to prevent layout shift
Performance
- Lazy loading is enabled by default
- Images fade in smoothly when loaded (can be disabled)
- Skeleton loader provides visual feedback during loading
- Prevents layout shift with proper aspect ratio handling
Development
To run the component in development mode:
npm run storybook
To run tests:
npm run test
To lint the component:
npm run lint