Skip to navigation

Buttons

Rotate turns the photo a quarter turn, Flip mirrors it and Reset undoes every change.

Open
Download

Anatomy

Each one is a button that goes anywhere inside Root. Put an icon or a word inside, and give an icon-only button an aria-label:

<Cropper.Rotate aria-label="Rotate left">
  <svg
    aria-hidden="true"
    width={20}
    height={20}
    viewBox="0 0 20 20"
  >
    <path
      d="M4 4v4h4M4.5 8a6 6 0 1 1 1.5 6.5"
      fill="none"
      stroke="currentColor"
      strokeWidth={1.5}
    />
  </svg>
</Cropper.Rotate>
<Cropper.Flip aria-label="Flip">
  <svg
    aria-hidden="true"
    width={20}
    height={20}
    viewBox="0 0 20 20"
  >
    <path
      d="M10 3v14M7 5l-4 10h4zM13 5l4 10h-4z"
      fill="none"
      stroke="currentColor"
      strokeWidth={1.5}
    />
  </svg>
</Cropper.Flip>
<Cropper.Reset>Reset</Cropper.Reset>

zriz ships them bare, with no paint and no icons. The demo above adds a right turn and a vertical flip, and uses the icons and styles from the zriz site.

See what each button moves

PartWhat it does
RotateTurns the photo 90° with a spring. A 3:2 crop becomes 2:3
FlipMirrors the photo, left to right by default, with a spring
ResetSprings back to where the crop started: defaultValue and the starting aspect, rotation and zoom, or the full photo

Every button part sets touch-action: manipulation and user-select: none inline, so a double tap on a phone never zooms the page and a long press never selects the label and loses the click.

While Root is disabled, a press does nothing, and before the photo loads only Reset acts. The buttons stay natively enabled and report aria-disabled, so style them from data-disabled on Root, as root shows.

While a move runs, Root carries data-transition: "rotate", "flip" or "morph" for Reset. A Reset across a quarter turn runs as "rotate", and so does a Flip or Reset pressed while a rotate still runs. During "rotate" the photo turns under the crop, the crop frame changes shape to the new side ratio, and the frame, its handles and the photo outside the crop stay visible, as during a flip. Accessibility lists how long each move takes, with and without reduced motion.

Rotate both ways

Rotate turns left, like iOS Photos. direction="cw" turns right:

<Cropper.Rotate>Rotate left</Cropper.Rotate>
<Cropper.Rotate direction="cw">Rotate right</Cropper.Rotate>

Keep reset hidden

Reset hides with the hidden attribute while nothing has changed. If a class sets display on it, add this rule:

[data-zriz-item="reset"][hidden] {
  display: none;
}

API

Rotate

Renders a <button type="button"> anywhere inside Root. Every part also takes className, render and the props of its element, see composition.

Prop
direction "ccw" | "cw" = "ccw"
"ccw" turns left, "cw" turns right

Flip

Renders a <button type="button"> with aria-pressed anywhere inside Root. className and render get { mirrored }.

Prop
axis "x" | "y" = "x"
"x" swaps left and right, "y" swaps top and bottom
AttributeWhen
data-mirroredWhile the photo is mirrored, with aria-pressed="true"

Reset

Renders a <button type="button"> anywhere inside Root. It has no props of its own. className and render get { pristine }.

AttributeWhen
data-pristineWhile nothing has changed. The button is hidden then