Skip to content
edmi-ui

Image

Displays an AI-generated image from base64 or bytes.

StackBlitz ↗StackBlitz ↗StackBlitz ↗
Generated portfolio cover

Generated · 1024×1024 · png

Generating image...
Generated portfolio cover

Generated · 1024×1024 · png

Generating image...
Generated portfolio cover

Generated · 1024×1024 · png

Generating image...

Loading is handled by the parent (spinner and shimmer text, see the demo).

Terminal window
npx shadcn@latest add @edmi-ui/ai-image
Terminal window
pnpm dlx shadcn@latest add @edmi-ui/ai-image
Terminal window
yarn dlx shadcn@latest add @edmi-ui/ai-image
Terminal window
bunx shadcn@latest add @edmi-ui/ai-image

Pick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.

Terminal window
npx shadcn-vue@latest add @edmi-ui/ai-image
Terminal window
pnpm dlx shadcn-vue@latest add @edmi-ui/ai-image
Terminal window
yarn dlx shadcn-vue@latest add @edmi-ui/ai-image
Terminal window
bunx shadcn-vue@latest add @edmi-ui/ai-image

Pick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.

Terminal window
npx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-image.json
Terminal window
pnpm dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-image.json
Terminal window
yarn dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-image.json
Terminal window
bunx --bun shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-image.json

Pick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.

import { Image } from "@/components/ai/image";
<div className="flex flex-wrap items-start gap-6">
<div className="flex flex-col gap-2">
<Image
alt="Generated portfolio cover"
className="aspect-[3/2] w-72"
mediaType="image/svg+xml"
uint8Array={new Uint8Array()}
/>
<p className="text-xs text-muted-foreground">
Generated · 1024×1024 · png
</p>
</div>
<div className="flex aspect-[3/2] w-72 items-center justify-center gap-2 rounded-xl border border-border bg-muted text-sm text-muted-foreground">
<span className="size-4 animate-spin rounded-full border-2 border-current border-t-transparent opacity-60" />
Generating image...
</div>
</div>
<script setup lang="ts">
import { Image } from "@/components/ai/image";
</script>
<template>
<div class="flex flex-wrap items-start gap-6">
<div class="flex flex-col gap-2">
<Image
alt="Generated portfolio cover"
class="aspect-[3/2] w-72"
media-type="image/svg+xml"
/>
<p class="text-xs text-muted-foreground">Generated · 1024×1024 · png</p>
</div>
<div class="flex aspect-[3/2] w-72 items-center justify-center gap-2 rounded-xl border border-border bg-muted text-sm text-muted-foreground">
<span class="size-4 animate-spin rounded-full border-2 border-current border-t-transparent opacity-60" />
Generating image...
</div>
</div>
</template>
<script lang="ts">
import { Image } from "$lib/components/ai/image";
</script>
<div class="flex flex-wrap items-start gap-6">
<div class="flex flex-col gap-2">
<Image alt="Generated portfolio cover" class="aspect-[3/2] w-72" mediaType="image/svg+xml" />
<p class="text-xs text-muted-foreground">Generated · 1024×1024 · png</p>
</div>
<div class="flex aspect-[3/2] w-72 items-center justify-center gap-2 rounded-xl border border-border bg-muted text-sm text-muted-foreground">
<span class="size-4 animate-spin rounded-full border-2 border-current border-t-transparent opacity-60"></span>
Generating image...
</div>
</div>
registry/components/ai/image.tsx
import type { Experimental_GeneratedImage } from "ai";
import { cn } from "cn";
export type ImageProps = Experimental_GeneratedImage & {
className?: string;
alt?: string;
};
/** AI SDK generated image as a responsive `img` (base64 + media type). Loading state belongs to the parent. */
export const Image = ({
base64,
uint8Array: _uint8Array,
mediaType,
...props
}: ImageProps) => (
<img
data-slot="ai-image"
{...props}
alt={props.alt}
className={cn(
"h-auto max-w-full overflow-hidden rounded-xl border border-border",
props.className,
)}
src={`data:${mediaType};base64,${base64}`}
/>
);
registry/components/ai/image/Image.vue
<script setup lang="ts">
import type { Experimental_GeneratedImage } from "ai"
import type { HTMLAttributes } from "vue"
import { computed } from "vue"
import { cn } from "@/registry/edmi/lib/utils"
/** AI SDK generated image as a responsive img (base64 + media type). Loading state belongs to the parent. */
interface Props extends Experimental_GeneratedImage {
class?: HTMLAttributes["class"]
alt?: string
}
const props = defineProps<Props>()
const classes = computed(() => cn(
"h-auto max-w-full overflow-hidden rounded-xl border border-border",
props.class,
))
const src = computed(() => `data:${props.mediaType};base64,${props.base64}`)
</script>
<template>
<img data-slot="ai-image" :class="classes" :src="src" :alt="props.alt">
</template>
registry/components/ai/image/index.ts
export { default as Image } from "./Image.vue";
src/lib/registry/ai/image/image.svelte
<script lang="ts">
import type { Experimental_GeneratedImage } from "ai";
import type { HTMLImgAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
/** AI SDK generated image as a responsive img (base64 + media type). Loading state belongs to the parent. */
let {
ref = $bindable(null),
base64,
uint8Array: _uint8Array,
mediaType,
alt,
class: className,
...restProps
}: Partial<Experimental_GeneratedImage> &
HTMLImgAttributes & {
ref?: HTMLImageElement | null;
base64: string;
mediaType: string;
} = $props();
</script>
<img
bind:this={ref}
data-slot="ai-image"
{alt}
class={cn("h-auto max-w-full overflow-hidden rounded-xl border border-border", className)}
src={`data:${mediaType};base64,${base64}`}
{...restProps}
/>
src/lib/registry/ai/image/index.ts
import Image from "./image.svelte";
export { Image };
Part Prop Type Default
Image base64, uint8Array, mediaType AI SDK GeneratedFile fields
Image alt, className string