Usage
Image renders responsive raster and URL-based images as a native <img>, and trusted local SVGs as an inline <svg>. It is modeled on the Next.js Image layout and performance subset: intrinsic width/height, fill, objectFit, objectPosition, lazy loading, priority preloading, and blur placeholders. Use inline SVG mode when size and class changes must apply to the actual <svg> node (for example application logos).
sizes help avoid layout shift.fill layouts inside a positioned container (covers, thumbnails).svg={ImportedSvg} when size and class changes must affect the actual <svg> node.| Mode | Prop | Renders | When to choose |
|---|---|---|---|
| URL / raster | src | Native <img> | Photos, remote assets, URL SVGs (rendered safely as <img>) |
| Inline SVG | svg | Inline <svg> via SVGR (?react import) | Trusted local logos and illustrations that must resize with CSS |
| Themed URL | lightSrc / darkSrc | Two native <img> elements | Logos or marks that differ by light/dark theme |
| Themed inline SVG | lightSvg / darkSvg | Two inline <svg> elements | Trusted local logos that differ by light/dark theme |
For URL SVGs, pass src and the component renders a native <img>. For trusted local SVGs imported via SVGR (?react), pass svg to render the actual <svg> element.
Pass lightSrc/darkSrc or lightSvg/darkSvg when a logo or mark needs a different asset in light and dark mode. Visibility follows the same theme class selectors as other ui-core styles:
.light, .light-theme, or .radix-themes.light.dark, .dark-theme, or .radix-themes.darkImage renders both variants and uses CSS (display) to reveal the one that matches the active theme. This follows the Next.js theme-aware image pattern (render both, toggle with CSS) adapted to this repo's class-based theming. Benefits:
<html>.display: none, so it is removed from the accessibility tree (no duplicate alt announcement).In themed modes, id is applied to a display: contents themed root (not to either variant) so SSR and hydration stay aligned without useTheme() branching. onLoad and onError are forwarded to both variants so a background-loaded image still notifies consumers after a theme switch.
Name assets by contrast (for example logo-dark-new.svg is the dark mark used on light backgrounds), not by the active theme. Next.js apps that rely heavily on next/image optimization may still use a local wrapper (for example docs ThemedImage) for raster-heavy imagery.
<img> with BEM classes for fill, object-fit, object-position, and optional blur placeholder. When sources is set, that <img> sits inside a layout-transparent <picture> so fill / object-fit still resolve on the image itself.<svg> node. Numeric width/height are forwarded as SVG attributes (matching URL mode); omit them to use intrinsic/viewBox sizing.URL mode accepts:
| Prop | Role |
|---|---|
srcSet | Native srcset candidate set; pair with sizes so the browser can pick a width |
sizes | Native sizes hint — only meaningful alongside srcSet or a sources entry |
sources | Array of { srcSet, type?, media?, sizes? } rendered as <source> elements ahead of src |
ImageMediaType covers the common MIME gates (Avif, Webp, Png, Jpeg, Gif, Svg). Order sources newest-first; keep src as a universally supported fallback.
alt that describes purpose, not decoration. Use alt="" only when the image is purely decorative and surrounding context carries the meaning.width and height (or fill inside a sized container) to reserve layout space and reduce cumulative layout shift.ImageLoading.Lazy). Set priority for above-the-fold imagery (eager load, high fetch priority).ImagePlaceholder.Blur with blurDataURL shows a low-resolution preview until the main image loads (URL mode only). Changing src resets the blur state so the placeholder can reappear.ImageObjectFit and ImageObjectPosition map to CSS via BEM modifiers.fill is true, omit width/height and place Image inside a positioned ancestor.Server-only Next.js Image props (loader, quality, unoptimized) are not supported in ui-core.
Do
fill container.priority sparingly for hero or LCP imagery.?react and pass them via svg when CSS must target the SVG node.lightSvg/darkSvg or lightSrc/darkSrc for theme-aware logos instead of hand-rolling useTheme() branches.Don't
src (native <img>) instead.useTheme() in render to swap logo src/svg — use themed props so CSS handles the toggle.Image for icon-sized glyphs — use Icon.alt for non-decorative images; empty alt for decorative images only.role="img" and aria-label when alt is non-empty; decorative images get aria-hidden and focusable={false}.