Controls

Circular, absolutely positioned overlay buttons for previous/next navigation over carousels and media.

Controls is an object grouping three client components — Control, ControlLeft, and ControlRight — that render a white circular motion.div positioned absolutely at the vertical centre of the nearest positioned ancestor. Use them for previous/next navigation over carousels and media.

Mountain lake

Import#

typescript
import { Controls } from "@reactberry/system/blocks";

Usage#

typescript
"use client";

import { useState } from "react";
import { Controls } from "@reactberry/system/blocks";
import { Box, Text } from "@reactberry/system/elements";

const slides = ["One", "Two", "Three"];

export default function SlideViewer() {
  const [index, setIndex] = useState(0);
  const prev = () => setIndex((i) => (i - 1 + slides.length) % slides.length);
  const next = () => setIndex((i) => (i + 1) % slides.length);

  return (
    <Box position="relative" height="12rem" skin="surface" shape="rounded" p="l">
      <Text>{slides[index]}</Text>
      <Controls.ControlLeft onClick={prev} title="Previous slide" />
      <Controls.ControlRight onClick={next} title="Next slide" left="auto" right="0" />
    </Box>
  );
}

Examples#

Custom content#

Controls.Control renders any children, for example a dismiss button in the corner of a card.

New: shared workspaces

Invite your team and edit projects together.

✕

Bottom placement#

Every position default can be overridden. Here both arrows sit in the bottom-right corner and fade at the ends.

Harbour at dawn1 / 3

API#

Control#

PropTypeDefaultDescription
children*
ReactNode
—

Content of the control, typically an icon.

as
any
—

Element to render instead of the default motion.div.

href
string
—

Passed through to the element, e.g. with as="a".

target
string
—

Passed through to the element, e.g. with as="a".

title
string
—

Native title attribute (hover tooltip).

rel
string
—

Passed through to the element, e.g. with as="a".

onClick
(() => void)
—

Click handler.

children (React.ReactNode, required) is the content of the control, typically an icon.

Control extends BoxProps and accepts any additional prop. All props are spread onto the Box after its defaults, so every default can be overridden. Defaults: position="absolute", top="calc(50% - 1.25rem)", left="0", bg="white", color="black", $shadow="small", size="2.5rem", p="xsmall", shape="circle", cursor="pointer", zIndex of 99, and centred flex content.

ControlLeft#

Control with a left arrow icon (IconArrowLeft, 1.125rem). Accepts any props and spreads them onto Control; children is replaced by the icon.

ControlRight#

Control with a right arrow icon (IconArrowRight, 1.125rem). Accepts any props and spreads them onto Control; children is replaced by the icon.

Control, ControlLeft, and ControlRight are also named exports of the Controls module source, but @reactberry/system/blocks exports only the Controls object.

Accessibility#

  • The default element is a div, not a button. It is not keyboard-focusable and has no role or accessible name.
  • For accessible controls, pass as="button" (or role and tabIndex) plus an aria-label. title only adds a hover tooltip.
  • The arrow icons have no text alternative.

Notes#

  • The parent must establish a positioning context (for example position="relative"), otherwise the controls are positioned against a higher ancestor.
  • ControlRight also defaults to left="0"; pass left="auto" and right="0" to place it on the right edge.
  • The motion props (variants, initial, animate, whileHover) are always set. With as set to a plain element such as "button" or "a", they are forwarded to the DOM element.
  • The hover variants (initial and active) are empty objects, so whileHover produces no visual change.