Image
Content & statusBrick 0.1.2

Image

Image presents ordinary raster or vector media with authored alternative text, deterministic loading/fallback anatomy, fit and focal-position recipes, stable aspect ratio, and finished framing. Atom owns source lifecycle; Brick owns paint.

Live example

Built from the published package

Interactive
Brick artwork
Choose with confidence

Know when Image is the right part

Use it when

Use Image for project thumbnails, article media, product screenshots, and other ordinary responsive media that needs a stable frame, crop/contain behavior, or an authored unavailable state.

Choose another path when

Use Avatar for people or entity identity, Icon for inline SVG symbols, and native CSS backgrounds for decorative background paint. Image is not an optimizer, gallery, lightbox, figure/caption, upload editor, or framework image loader.

Installation and imports

tsx
import { Image } from "@flowstack-ui/brick";
// or
import { Image } from "@flowstack-ui/brick/image";
import "@flowstack-ui/brick/styles.css";

The complete stylesheet above is the recommended default. For a measured route-aware build, replace it with the shared foundation and this component's stylesheet:

tsx
import "@flowstack-ui/brick/styles/core.css"; // once at the application root
import "@flowstack-ui/brick/styles/image.css";

Add the modular stylesheet for every other Brick component the route renders. Do not combine modular styles with styles.css or tokens.css.

Public exports are Image, ImageRootProps, ImageContentProps, ImageFallbackProps, ImageFit, ImagePosition, ImageRadius, and ImageFrame.

Quick start

tsx
<Image.Root src="/workspace.jpg" ratio={16 / 9}>
  <Image.Content alt="Designers reviewing the workspace" width={1200} height={675} />
  <Image.Fallback>Image unavailable</Image.Fallback>
</Image.Root>

Visual recipes and states

Fit changes only object-fit; position changes only object-position. Logical start/end reverse under RTL without mirroring pixels. Radius clips the complete frame. frame="subtle" adds a semantic canvas and border. Ratio reserves the box; without it, loaded native dimensions remain intrinsic.

Atom exposes data-state="idle | loading | loaded | error". Content appears only when loaded. Authored Fallback fills the same reserved box for its selected states.

Examples

Decorative media inside a named link

tsx
<Link aria-label="Open workspace" href="/workspace">
  <Image.Root asChild src="/workspace.jpg" ratio={16 / 9}>
    <span><Image.Content alt="" /></span>
  </Image.Root>
</Link>

Separate loading and error content

tsx
<Image.Root src={source} frame="subtle">
  <Image.Content alt="Quarterly report chart" />
  <Image.Fallback when="loading">Loading chart</Image.Fallback>
  <Image.Fallback when={["idle", "error"]}>Chart unavailable</Image.Fallback>
</Image.Root>
Public contract

API

Start with the public parts and root options below. Components with multiple parts separate each area into its own named subsection.

Root

PropValuesDefault
srcimage URL stringabsent / idle
fitcover, contain, fill, none, scale-downcover
positioncenter, top, bottom, start, endcenter
radiusnone, sm, md, lg, fullnone
framenone, subtlenone
ratiopositive finite numberintrinsic
onLoadingStatusChange(status) => voidnone

Content and Fallback

Image.Content requires alt. It forwards native image attributes including width, height, srcSet, sizes, loading, decoding, fetchPriority, crossOrigin, referrerPolicy, events, data/ARIA attributes, class, style, and its image ref. src belongs to Root.

Image.Fallback accepts Atom when="idle" | "loading" | "error" or an array of those values. Its default covers all three non-loaded states. All parts retain Atom render and asChild composition.

Shared responsibility

Accessibility

Every Content requires an authored alt decision. Use concise contextual alt for informative media and alt="" for decoration. Inside an already named action, the image is usually decorative. Never repeat nearby text, derive a name from a filename, or write “image of.” Complex images need adjacent extended content.

Fallback adds no live region, focus, role, or generated announcement. Add application status messaging only when a source change matters to the task. Image has no keyboard interaction. Forced colors preserves a visible subtle frame and readable fallback.

Responsive behavior

Root and Content stay within their available inline size. Native width/height reserve intrinsic ratio; srcSet and sizes let the browser choose a source. Image defines no breakpoints. Its owner chooses surrounding Grid, Stack, Container, and responsive dimensions.

Stable visual contract

Styling and tokens

Customization

Prefer recipes, then override component variables for a deliberate exception:

tsx
<Image.Root
  frame="subtle"
  style={{ "--brick-image-frame-background": "var(--brick-color-accent-soft)" }}
>
  <Image.Fallback>Preview unavailable</Image.Fallback>
</Image.Root>

Classes and inline styles remain escape hatches. Applications own source selection, optimization, priority policy, and fallback content.

Tokens and CSS hooks

Stable classes are .brick-image, .brick-image__content, and .brick-image__fallback. Stable slots are image, image-content, and image-fallback through data-slot. Root exposes data-fit, data-position, data-radius, data-frame, optional data-ratio, and Atom data-state.

Public variables:

  • --brick-image-fit
  • --brick-image-position
  • --brick-image-radius
  • --brick-image-frame-background
  • --brick-image-frame-border
  • --brick-image-fallback-foreground
  • --brick-image-fallback-inset

Advanced reference

Open these details only when you need to inspect DOM ownership, native forwarding, or lower-level composition.

Maintainer resources

Tests, playground evidence, source notes, and release history remain available without crowding the plug-and-play guide.