Browse docs
Browse docs
A thin, declarative wrapper over the native <img>. It renders a URL you give it — no data fetching, no eval — and adds what a bare <img> lacks: it reserves the box before load (no layout shift), shows a skeleton while loading, degrades to a graceful fallback on error, and supports access / visibleWhen gating like the form components.
The MUI twin of @dashforge/tw's Image — same public API, MUI internals.
<Image src="https://picsum.photos/seed/dashforge/800/450" alt="A calm mountain lake at dawn" aspectRatio={16 / 9} rounded="lg" sx={{ width: "100%", maxWidth: 420 }} />An aspect-locked, rounded image. Because aspectRatio reserves the box, the surrounding layout doesn't shift while the image loads — and a skeleton fills the space until it does.
// fit="cover" crops to fill; fit="contain" letterboxes — both need a reserved box
<Image src={SRC} alt="Landscape" aspectRatio={1} fit="cover" rounded="md" />fit maps to CSS object-fit. cover (default) crops to fill; contain letterboxes. Both need a reserved box (here a square aspectRatio={1}).


// on load error, a muted fallback replaces the broken-image glyph
<Image src="/missing.jpg" alt="Product" aspectRatio={1} rounded="md" fallback={<span>Image unavailable</span>} />When the source fails to load, Image replaces the broken-image glyph with a muted placeholder. Pass your own via fallback.
import { Image } from '@dashforge/ui';
// Responsive, aspect-locked
<Image src={photo} alt="Product" aspectRatio={4 / 3} rounded="md" />
// Fixed thumbnail
<Image src={avatar} alt="Jane Doe" width={48} height={48} rounded="full" />
// Permission-gated (hidden if the user can't read this photo)
<Image src={secret} alt="Sensitive" access={{ resource: 'photo', action: 'read', onUnauthorized: 'hide' }} />| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — | Image source URL. Same-origin / data: keeps it inside your boundary; an external host is egress. |
alt | string | — | Alternative text (a11y). Use alt="" for purely decorative images. |
aspectRatio | number | string | — | Locks the box shape before load (no layout shift). 16 / 9, 1, or a CSS string. |
fit | 'cover' | 'contain' | 'fill' | 'none' | 'scale-down' | 'cover' | How the image fills its box — CSS object-fit. |
rounded | 'none' | 'sm' | 'md' | 'lg' | 'full' | 'none' | Corner-radius token. |
loading | 'lazy' | 'eager' | 'lazy' | Native lazy/eager loading. |
showSkeleton | boolean | true | Show a <Skeleton> while loading. Requires a reserved box (aspectRatio, or width + height). |
fallback | ReactNode | — | Shown on load error. Defaults to a muted broken-image glyph. |
access | AccessRequirement | — | RBAC gate. hide → not rendered; disable/readonly → dimmed. Resolved against the nearest RbacProvider. |
visibleWhen | (engine: Engine) => boolean | — | Reactive visibility predicate against the form engine. No-op outside a <DashForm>. |
sx | SxProps<Theme> | — | MUI style override on the root wrapper. |
...rest | ImgHTMLAttributes | — | Native <img> attributes (srcSet, sizes, decoding, …) forwarded to the element. |
aspectRatio, or width + height) — the skeleton and the no-layout-shift guarantee both need a reserved box. Without one the image still renders, but the layout shifts and the skeleton is skipped.src is fetched by the browser from that host. Self-host the asset to keep it inside your boundary.access and visibleWhen work exactly as on the form components (e.g. TextField): hide a photo a user can't see, or show a preview only once a file field has a value.