@pagedotapp/page-image
v0.0.0-alpha.14
Published
PageImage - A reusable React component
Readme
PageImage
A flexible image component with loading states, fallback support, and various display options.
Installation
npm install @pagedotapp/page-imageUsage
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
| Prop | Type | Default | Description |
| -------------------- | ------------------------------ | ------------ | ------------------------------------------------------------ |
| 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
// Fixed dimensions
<PageImage
src="/hero-image.jpg"
alt="Hero image"
width={800}
height={400}
/>
// Aspect ratio
<PageImage
src="/photo.jpg"
alt="Photo"
aspectRatio="16/9"
width="100%"
/>
// Square image
<PageImage
src="/avatar.jpg"
alt="User avatar"
aspectRatio="square"
width={200}
/>Object Fit Options
<PageImage
src="/banner.jpg"
alt="Banner"
fit="cover" // Default - covers entire container
aspectRatio="21/9"
/>
<PageImage
src="/logo.png"
alt="Logo"
fit="contain" // Maintains aspect ratio within container
width={200}
height={100}
/>Shape Variants
// Circular image (perfect for avatars)
<PageImage
src="/avatar.jpg"
alt="User avatar"
circle
width={100}
height={100}
/>
// Rounded corners
<PageImage
src="/card-image.jpg"
alt="Card image"
rounded
radius="lg"
/>Loading States
// With skeleton loader (default)
<PageImage
src="/slow-loading.jpg"
alt="Slow loading image"
showSkeleton
/>
// Without skeleton loader
<PageImage
src="/fast-loading.jpg"
alt="Fast loading image"
showSkeleton={false}
/>
// Eager loading for above-the-fold images
<PageImage
src="/hero.jpg"
alt="Hero image"
loading="eager"
/>Error Handling
// With custom fallback content
<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>
}
/>
// With fallback image
<PageImage
src="/primary-image.jpg"
alt="Product photo"
fallbackSrc="/placeholder.jpg"
/>
// Handle load/error events
<PageImage
src="/tracked-image.jpg"
alt="Tracked image"
onLoad={() => console.log('Image loaded successfully')}
onError={() => console.log('Image failed to load')}
/>Interactive Images
// Clickable image with proper accessibility
<PageImage
src="/clickable.jpg"
alt="Click to enlarge"
onClick={(e) => console.log('Image clicked')}
style={{ cursor: 'pointer' }}
/>
// Image gallery item
<PageImage
src="/gallery-item.jpg"
alt="Gallery item"
onClick={() => openLightbox()}
rounded
fadeIn
/>Advanced Examples
// Product image with all features
<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"
/>
// Avatar with fallback
<PageImage
src={user.avatarUrl}
alt={`${user.name}'s avatar`}
fallback={
<div className="avatar-fallback">
{user.name.charAt(0)}
</div>
}
circle
width={60}
height={60}
/>
// Hero banner with specific handling
<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
classNamefor the image element - Passing a custom
containerClassNamefor the container - Targeting the component's CSS classes in your global styles
Accessibility
- Always provide meaningful
alttext - When using
onClick, the component automatically addsrole="button"andtabIndex={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 storybookTo run tests:
npm run testTo lint the component:
npm run lint