Skip to main content

Media Object

A small, reusable layout primitive for "image/icon on one side, descriptive content on the other" — the foundational media object pattern. Use it to compose avatars-with-text, icons-with-copy, thumbnails-with-titles, and similar two-up rows without re-implementing flexbox each time.

When to use

  • Comment threads (avatar + name + body).
  • Compact list items (icon + label + secondary text).
  • Notification rows.
  • Feature lists, profile cards, attachment previews.

When not to use

  • For complex multi-region layouts — reach for Card or build a bespoke flex/grid.
  • When the media is purely decorative and adds no information — drop it and use a plain block.

Spacing & alignment

Default gap is gap-4; override by passing a different gap-* class to MediaObject.Root. Use standard flex utilities (items-start, items-center, etc.) to align media and content vertically.

Compose the <MediaObject> with the <MediaObject.Media> and <MediaObject.Content> components as direct children. Each part accepts asChild for swapping the rendered element (e.g. render Root as an <a> to make the whole row clickable).

Lorem ipsum

Repudiandae sint consequuntur vel. Amet ut nobis explicabo numquam expedita quia omnis voluptatem. Minus quidem ipsam quia iusto.

Ea eiusmod eiusmod aute reprehenderit exercitation eu ea id adipisicing occaecat.

import { MediaObject } from "@ngrok/mantle/media-object"; <MediaObject.Root>	<MediaObject.Media>		<ExampleMedia />	</MediaObject.Media>	<MediaObject.Content>		<h4 className="text-lg font-medium">Lorem ipsum</h4>		<p className="mb-4 mt-1">			Repudiandae sint consequuntur vel. Amet ut nobis explicabo numquam expedita quia omnis			voluptatem. Minus quidem ipsam quia iusto.		</p>		<p>Ea eiusmod eiusmod aute reprehenderit exercitation eu ea id adipisicing occaecat.</p>	</MediaObject.Content></MediaObject.Root>;

Composition

Compose the parts of a MediaObject together to build your own:

MediaObject.Root├── MediaObject.Media└── MediaObject.Content

Polymorphism

Each part accepts an asChild prop. When true, the part renders its single child instead of its default <div>, forwarding its styling and props onto that child. Render MediaObject.Root as an <a> to make the whole row a link.

import { MediaObject } from "@ngrok/mantle/media-object"; <MediaObject.Root asChild>	<a href="https://ngrok.com">		<MediaObject.Media>			<ExampleMedia />		</MediaObject.Media>		<MediaObject.Content>			<h4 className="text-lg font-medium">Lorem ipsum</h4>			<p>Repudiandae sint consequuntur vel.</p>		</MediaObject.Content>	</a></MediaObject.Root>;

API Reference

MediaObject.Root

The MediaObject is an image/icon (media) to the left, with descriptive content (title and subtitle/description) to the right. Root container for all MediaObject.Root sub-components.

All props from div, plus:

PropTypeDefaultDescription
asChildbooleanfalseUse the asChild prop to compose the MediaObject styling and functionality onto alternative element types or your own React components.

MediaObject.Media

The container for an image or icon to display in the media slot of the MediaObject.

All props from div, plus:

PropTypeDefaultDescription
asChildbooleanfalseUse the asChild prop to compose the MediaObject.Media styling and functionality onto alternative element types or your own React components.

MediaObject.Content

The container for the content slot of a MediaObject.

All props from div, plus:

PropTypeDefaultDescription
asChildbooleanfalseUse the asChild prop to compose the MediaObject.Content styling and functionality onto alternative element types or your own React components.