Skip to content
hightouchUI

Design system

7abf83d

Media preview

Media preview shows a larger view of an image or video beside the element it belongs to, on the dark tooltip surface, when that element is hovered or reached with the keyboard.

Example

Usage

The child is the anchor: the preview opens 150ms after the pointer enters it or it takes focus, and closes when the pointer leaves, focus moves on, Escape is pressed, or the page scrolls. Clicking the anchor keeps it open. The child must forward its ref to a focusable DOM element. MediaPreview is built on the same Chakra tooltip as tooltip, so its open delay, focus, Escape, and positioning work the same way.

Width and aspect ratio

width takes a size token or a CSS length, and aspectRatio is the media's width divided by its height. The preview takes that shape before the media loads, so it opens once at its final size. Tall media on a short screen gets narrower, so it stays within 60% of the viewport height and still fills the preview.

When the caller doesn't store the media's size, read it from the thumbnail once it loads, and anchor the preview after that.

Placement

The preview opens above the anchor, lined up with its left edge, by default. Set placement to prefer another side. When it has no room, the preview flips to the opposite side, and stays on screen when neither fits. Pass preferredPlacements to try other sides in order, as tooltip does.

Video

A src ending in a video extension plays muted on a loop, without controls. Under reduced motion it shows the first frame. Pass video={{ playback: "none" }} to show only the first frame, for a screen where a playing video would distract. The preview takes no pointer input, so video accepts only autoplay and none.

Controlled open state

Pass isOpen when something other than the child's hover and focus decides when the preview opens, such as a hovered row around a thumbnail. The child then only anchors the preview, so the caller opens and closes it, including from keyboard focus.

Guidelines

When to use

  • A thumbnail is too small to judge, and the user needs a closer look before choosing, such as an ad mockup or a color direction.
  • The larger view only repeats media already on the page, so nothing is lost if it never opens.

When not to use

  • The media is the content itself. Show it at full size instead.
  • The user needs to act on what's inside it. The preview takes no pointer input and closes on leave; use a popover or a dialog.
  • The preview would hold only text. Use a tooltip.

Accessibility

  • The anchor is described by the preview's title and description, as a tooltip is. Give the thumbnail an alt when it says more than that text.
  • Focus opens it, so anchor it to a focusable control or a control's thumbnail. Escape closes it, and also reaches a dialog around it, as it does for a tooltip.

Props

NameDefaultDescription
src

—

stringImage or video URL, resolved by the caller. A URL ending in a video extension renders a video without controls, playing as video sets.
title

—

stringLabel under the media.
description

—

stringSupporting copy under the title.
width

—

stringWidth of the media: a size token such as "xs", or a CSS length such as "320px".
aspectRatio

—

numberWidth divided by height of the media, such as 16 / 9. The preview takes this shape before the media loads, so it opens once at its final size. Read it from the thumbnail's naturalWidth and naturalHeight when the caller doesn't store it. The preview stays closed until it is a positive finite number.
video{ playback: "autoplay" }Extract< NonNullable<HtMediaProps["video"]>, { playback: "autoplay" | "none" } > & { controls?: never; muted?: never; controlsList?: never }Playback for a video src, with HtMedia's video keys. The preview takes no pointer input, so only autoplay and none apply: none shows the first frame. An image ignores it.
placement"top-start"PlacementWithLogicalPreferred side of the anchor. The preview flips to the opposite side when this one has no room, and stays on screen when neither fits.
preferredPlacements

—

PlacementWithLogical[]Sides to try, in order, when placement has no room.
isOpen

—

booleanControls the preview. The child then only anchors it: the caller opens and closes it, including from keyboard focus and Escape.
children

—

ReactElement<RefAttributes<HTMLElement>>Element the preview anchors to. It must forward its ref to a focusable DOM element, so keyboard users can open the preview.