Component reference
ImageCropper
Crop a profile image and inspect the exported result.
Preview
Live previewOptional six-digit hex. Clear to restore the preset. Check contrast with your brand color.
Changes apply to this preview only.
Profile photo
Choose the part of the image shown next to your name.
Déplacez le cadre ou utilisez les flèches. Tirez une poignée pour redimensionner ; Maj accélère le déplacement.

Crop position 12%, 12%, size 76% by 76%.
{
"x": 12,
"y": 12,
"width": 76,
"height": 76
}Width adapts to the available space
"use client";
import {
Card,
CardHeader,
Badge,
CardTitle,
CardDescription,
CardContent,
type PimoluCropArea,
type PimoluImageCropperLabels,
ImageCropper,
Code
} from "@pimolu/react";
import { useState } from "react";
const CROPPER_SRC = "/images/pimolu-studio.webp";
function CropperDemo({ aspectRatio, defaultCrop, defaultZoom, disabled, labels, }: {
aspectRatio?: number;
defaultCrop?: PimoluCropArea;
defaultZoom?: number;
disabled?: boolean;
labels?: PimoluImageCropperLabels;
}) {
const [crop, setCrop] = useState<PimoluCropArea>(defaultCrop ?? {
x: 0,
y: 0,
width: 100,
height: 100
});
const [result, setResult] = useState<string | null>(null);
return (
<div className="grid gap-5 min-w-0">
<ImageCropper
src={CROPPER_SRC}
alt="Pimolu Studio product illustration"
aspectRatio={aspectRatio}
defaultCrop={defaultCrop}
defaultZoom={defaultZoom}
disabled={disabled}
labels={labels}
onChange={setCrop}
onComplete={(blob, area) => {
if(!blob) {
setResult("Canvas output is unavailable in this environment.");
return;
}
setResult(`${blob.type || "image"} · ${Math.max(
1,
Math.round(blob.size / 1024)
)} KB · ${Math.round(area.width)}% × ${Math.round(area.height)}%`);
}}
/>
<div className="flex flex-wrap items-center gap-3 min-w-0">
<Badge variant="secondary">
x {crop.x}%
</Badge>
<Badge variant="secondary">
y {crop.y}%
</Badge>
<Badge variant="secondary">
{crop.width}% ×{" "}
{crop.height}%
</Badge>
{
result && (<Badge variant="success">
{result}
</Badge>)
}
</div>
<Code block>
{JSON.stringify(crop, null, 2)}
</Code>
</div>
);
}
export function DemoExample() {
return (
<Card>
<CardHeader>
<div className="flex flex-wrap items-center gap-3 min-w-0 justify-between">
<Badge variant="primary">Account</Badge>
<span className="text-sm text-muted leading-relaxed">PNG · square · 512 px</span>
</div>
<CardTitle>Profile photo</CardTitle>
<CardDescription>
Choose the part of the image shown next to your name.
</CardDescription>
</CardHeader>
<CardContent>
<CropperDemo
aspectRatio={1}
defaultCrop={{
x: 12,
y: 12,
width: 76,
height: 76,
}}
labels={{
cropper: "Recadreur de photo",
instructions: (
"Déplacez le cadre ou utilisez les flèches. Tirez une poignée " +
"pour redimensionner ; Maj accélère le déplacement."
),
cropArea: "Zone de recadrage",
zoom: "Agrandissement",
reset: "Réinitialiser",
apply: "Enregistrer la photo",
resizeTopLeft: "Redimensionner en haut à gauche",
resizeTop: "Redimensionner en haut",
resizeTopRight: "Redimensionner en haut à droite",
resizeRight: "Redimensionner à droite",
resizeBottomRight: "Redimensionner en bas à droite",
resizeBottom: "Redimensionner en bas",
resizeBottomLeft: "Redimensionner en bas à gauche",
resizeLeft: "Redimensionner à gauche",
}}
/>
</CardContent>
</Card>
);
}More examples
Different configurations and compositions using the real Pimolu API. Each preview runs independently and follows the site appearance.
Square avatar
Drag the crop area to move it, drag a handle to resize it, or use the arrow keys. Shift moves by five percent. The default zoom enlarges the image inside the stage without changing the crop rectangle.
Cover crop
A 16 / 9 stage with a locked ratio is ready for a hero image. The stage crops the source with object-fit: cover and maps the visible rectangle back to the source pixels on export.
Free crop and disabled state
Without aspectRatio, width and height resize independently. The same component can be disabled while an upload or a save is in flight.
Usage
Canvas export requires a readable image source; cross-origin images need compatible CORS headers.
API reference
Generated from the public TypeScript declarations. Native HTML attributes are inherited where the component extends them; this reference includes Pimolu props and selected common native attributes.
PimoluCropArea
Type source| Name | Type | Default | Description |
|---|---|---|---|
xRequired | number | — | Public Pimolu prop; see the source declaration for details. |
yRequired | number | — | Public Pimolu prop; see the source declaration for details. |
widthRequired | number | — | Public Pimolu prop; see the source declaration for details. |
heightRequired | number | — | Public Pimolu prop; see the source declaration for details. |
xRequirednumberNo default extracted.
Public Pimolu prop; see the source declaration for details.
yRequirednumberNo default extracted.
Public Pimolu prop; see the source declaration for details.
widthRequirednumberNo default extracted.
Public Pimolu prop; see the source declaration for details.
heightRequirednumberNo default extracted.
Public Pimolu prop; see the source declaration for details.
PimoluImageCropperLabels
Type source| Name | Type | Default | Description |
|---|---|---|---|
cropper | string | undefined | "Image cropper" | Accessible name of the cropper region. Defaults to "Image cropper". |
instructions | string | undefined | — | Keyboard and pointer instructions. |
cropArea | string | undefined | "Crop area" | Accessible name of the draggable crop area. Defaults to "Crop area". |
zoom | string | undefined | "Zoom" | Zoom slider label. Defaults to "Zoom". |
reset | string | undefined | "Reset" | Defaults to "Reset". |
apply | string | undefined | "Crop image" | Defaults to "Crop image". |
status | ((crop: PimoluCropArea) => string) | undefined | an English position/size sentence | Live description announced after crop changes. Defaults to an English position/size sentence. |
resizeTopLeft | string | undefined | — | Public Pimolu prop; see the source declaration for details. |
resizeTop | string | undefined | — | Public Pimolu prop; see the source declaration for details. |
resizeTopRight | string | undefined | — | Public Pimolu prop; see the source declaration for details. |
resizeRight | string | undefined | — | Public Pimolu prop; see the source declaration for details. |
resizeBottomRight | string | undefined | — | Public Pimolu prop; see the source declaration for details. |
resizeBottom | string | undefined | — | Public Pimolu prop; see the source declaration for details. |
resizeBottomLeft | string | undefined | — | Public Pimolu prop; see the source declaration for details. |
resizeLeft | string | undefined | — | Public Pimolu prop; see the source declaration for details. |
cropperstring | undefinedDefault: "Image cropper"
Accessible name of the cropper region. Defaults to "Image cropper".
instructionsstring | undefinedNo default extracted.
Keyboard and pointer instructions.
cropAreastring | undefinedDefault: "Crop area"
Accessible name of the draggable crop area. Defaults to "Crop area".
zoomstring | undefinedDefault: "Zoom"
Zoom slider label. Defaults to "Zoom".
resetstring | undefinedDefault: "Reset"
Defaults to "Reset".
applystring | undefinedDefault: "Crop image"
Defaults to "Crop image".
status((crop: PimoluCropArea) => string) | undefinedDefault: an English position/size sentence
Live description announced after crop changes. Defaults to an English position/size sentence.
resizeTopLeftstring | undefinedNo default extracted.
Public Pimolu prop; see the source declaration for details.
resizeTopstring | undefinedNo default extracted.
Public Pimolu prop; see the source declaration for details.
resizeTopRightstring | undefinedNo default extracted.
Public Pimolu prop; see the source declaration for details.
resizeRightstring | undefinedNo default extracted.
Public Pimolu prop; see the source declaration for details.
resizeBottomRightstring | undefinedNo default extracted.
Public Pimolu prop; see the source declaration for details.
resizeBottomstring | undefinedNo default extracted.
Public Pimolu prop; see the source declaration for details.
resizeBottomLeftstring | undefinedNo default extracted.
Public Pimolu prop; see the source declaration for details.
resizeLeftstring | undefinedNo default extracted.
Public Pimolu prop; see the source declaration for details.
PimoluImageCropperProps
Type source| Name | Type | Default | Description |
|---|---|---|---|
srcRequired | PimoluImageCropperSource | — | Image URL, `File` or `Blob`. Object URLs are created and revoked. |
alt | string | undefined | an empty string | Alternative text of the preview image. Defaults to an empty string. |
aspectRatio | number | undefined | — | Locked crop ratio (width / height in pixels). Also fixes the stage ratio, so the default crop fills the stage exactly. |
crop | PimoluCropArea | undefined | — | Controlled crop area. Omit to let the cropper own it. |
defaultCrop | PimoluCropArea | undefined | the whole stage | Initial crop when uncontrolled. Defaults to the whole stage. |
onChange | ((crop: PimoluCropArea) => void) | undefined | — | Called on every move, resize, zoom-independent crop change and reset. |
onComplete | ((blob: Blob | null, crop: PimoluCropArea) => void) | undefined | — | Called by the "Crop image" button. The blob is `null` when the browser cannot read the image size or a canvas context (for example in tests or a server-side render); the crop area is always provided. |
outputType | string | undefined | "image/png" | MIME type passed to `canvas.toBlob`. Defaults to "image/png". |
outputQuality | number | undefined | — | Quality (0–1) for lossy output types. |
minZoom | number | undefined | 1 | Smallest zoom. Values below 1 are raised to 1. Defaults to 1. |
maxZoom | number | undefined | 3 | Largest zoom. Defaults to 3. |
defaultZoom | number | undefined | 1 | Initial zoom. Defaults to 1. |
disabled | boolean | undefined | false | Disable every interaction. |
labels | PimoluImageCropperLabels | undefined | — | Localizable labels. |
className | string | undefined | — | Class applied to the cropper wrapper. |
srcRequiredPimoluImageCropperSourceNo default extracted.
Image URL, `File` or `Blob`. Object URLs are created and revoked.
altstring | undefinedDefault: an empty string
Alternative text of the preview image. Defaults to an empty string.
aspectRationumber | undefinedNo default extracted.
Locked crop ratio (width / height in pixels). Also fixes the stage ratio, so the default crop fills the stage exactly.
cropPimoluCropArea | undefinedNo default extracted.
Controlled crop area. Omit to let the cropper own it.
defaultCropPimoluCropArea | undefinedDefault: the whole stage
Initial crop when uncontrolled. Defaults to the whole stage.
onChange((crop: PimoluCropArea) => void) | undefinedNo default extracted.
Called on every move, resize, zoom-independent crop change and reset.
onComplete((blob: Blob | null, crop: PimoluCropArea) => void) | undefinedNo default extracted.
Called by the "Crop image" button. The blob is `null` when the browser cannot read the image size or a canvas context (for example in tests or a server-side render); the crop area is always provided.
outputTypestring | undefinedDefault: "image/png"
MIME type passed to `canvas.toBlob`. Defaults to "image/png".
outputQualitynumber | undefinedNo default extracted.
Quality (0–1) for lossy output types.
minZoomnumber | undefinedDefault: 1
Smallest zoom. Values below 1 are raised to 1. Defaults to 1.
maxZoomnumber | undefinedDefault: 3
Largest zoom. Defaults to 3.
defaultZoomnumber | undefinedDefault: 1
Initial zoom. Defaults to 1.
disabledboolean | undefinedDefault: false
Disable every interaction.
labelsPimoluImageCropperLabels | undefinedNo default extracted.
Localizable labels.
classNamestring | undefinedNo default extracted.
Class applied to the cropper wrapper.
Accessibility
- Provide keyboard-operable crop controls and a non-drag alternative for essential image tasks.