feat(29-02): create GearImage component for fit-within rendering
Renders images with object-contain by default (letterbox/pillarbox), object-cover when cover prop is set, or CSS transform when crop values are present. Parent container uses dominant color background. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
65
src/client/components/GearImage.tsx
Normal file
65
src/client/components/GearImage.tsx
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
interface GearImageProps {
|
||||||
|
src: string;
|
||||||
|
alt: string;
|
||||||
|
dominantColor?: string | null;
|
||||||
|
cropZoom?: number | null;
|
||||||
|
cropX?: number | null;
|
||||||
|
cropY?: number | null;
|
||||||
|
className?: string;
|
||||||
|
cover?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GearImage({
|
||||||
|
src,
|
||||||
|
alt,
|
||||||
|
dominantColor,
|
||||||
|
cropZoom,
|
||||||
|
cropX,
|
||||||
|
cropY,
|
||||||
|
className = "",
|
||||||
|
cover = false,
|
||||||
|
}: GearImageProps) {
|
||||||
|
const hasCrop = cropZoom != null && cropZoom > 1;
|
||||||
|
|
||||||
|
if (cover) {
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={src}
|
||||||
|
alt={alt}
|
||||||
|
className={`w-full h-full object-cover ${className}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCrop) {
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={src}
|
||||||
|
alt={alt}
|
||||||
|
className={`w-full h-full object-cover ${className}`}
|
||||||
|
style={{
|
||||||
|
transform: `scale(${cropZoom}) translate(${cropX ?? 0}%, ${cropY ?? 0}%)`,
|
||||||
|
transformOrigin: "center center",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={src}
|
||||||
|
alt={alt}
|
||||||
|
className={`w-full h-full object-contain ${className}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the background color for an image container.
|
||||||
|
* Uses the dominant color if available, otherwise a neutral fallback.
|
||||||
|
*/
|
||||||
|
export function imageContainerBg(
|
||||||
|
dominantColor?: string | null,
|
||||||
|
): string | undefined {
|
||||||
|
return dominantColor || "#f3f4f6";
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user