Image
Displays an AI-generated image from base64 or bytes.
Generated · 1024×1024 · png
Generated · 1024×1024 · png
Generated · 1024×1024 · png
import { Image } from "@/components/ai/image";
// A gradient SVG stands in for a generated image (base64 + media type, like the AI SDK returns).const base64 = "PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPSc2MDAnIGhlaWdodD0nNDAwJz48ZGVmcz48cmFkaWFsR3JhZGllbnQgaWQ9J2EnIGN4PScyNSUnIGN5PSczMCUnIHI9JzQ1JSc+PHN0b3Agb2Zmc2V0PScwJyBzdG9wLWNvbG9yPScjZThhMzNkJy8+PHN0b3Agb2Zmc2V0PScxJyBzdG9wLWNvbG9yPScjZThhMzNkJyBzdG9wLW9wYWNpdHk9JzAnLz48L3JhZGlhbEdyYWRpZW50PjxyYWRpYWxHcmFkaWVudCBpZD0nYicgY3g9JzcyJScgY3k9JzY4JScgcj0nNDAlJz48c3RvcCBvZmZzZXQ9JzAnIHN0b3AtY29sb3I9JyMzODZmZDYnLz48c3RvcCBvZmZzZXQ9JzEnIHN0b3AtY29sb3I9JyMzODZmZDYnIHN0b3Atb3BhY2l0eT0nMCcvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHdpZHRoPSc2MDAnIGhlaWdodD0nNDAwJyBmaWxsPScjNjJhMDdhJy8+PHJlY3Qgd2lkdGg9JzYwMCcgaGVpZ2h0PSc0MDAnIGZpbGw9J3VybCgjYSknLz48cmVjdCB3aWR0aD0nNjAwJyBoZWlnaHQ9JzQwMCcgZmlsbD0ndXJsKCNiKScvPjwvc3ZnPg==";
export default function Demo() { return ( <div className="flex flex-wrap items-start gap-6"> <div className="flex flex-col gap-2"> <Image alt="Generated portfolio cover" base64={base64} 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";
// A gradient SVG stands in for a generated image (base64 + media type, like the AI SDK returns).const base64 = "PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPSc2MDAnIGhlaWdodD0nNDAwJz48ZGVmcz48cmFkaWFsR3JhZGllbnQgaWQ9J2EnIGN4PScyNSUnIGN5PSczMCUnIHI9JzQ1JSc+PHN0b3Agb2Zmc2V0PScwJyBzdG9wLWNvbG9yPScjZThhMzNkJy8+PHN0b3Agb2Zmc2V0PScxJyBzdG9wLWNvbG9yPScjZThhMzNkJyBzdG9wLW9wYWNpdHk9JzAnLz48L3JhZGlhbEdyYWRpZW50PjxyYWRpYWxHcmFkaWVudCBpZD0nYicgY3g9JzcyJScgY3k9JzY4JScgcj0nNDAlJz48c3RvcCBvZmZzZXQ9JzAnIHN0b3AtY29sb3I9JyMzODZmZDYnLz48c3RvcCBvZmZzZXQ9JzEnIHN0b3AtY29sb3I9JyMzODZmZDYnIHN0b3Atb3BhY2l0eT0nMCcvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHdpZHRoPSc2MDAnIGhlaWdodD0nNDAwJyBmaWxsPScjNjJhMDdhJy8+PHJlY3Qgd2lkdGg9JzYwMCcgaGVpZ2h0PSc0MDAnIGZpbGw9J3VybCgjYSknLz48cmVjdCB3aWR0aD0nNjAwJyBoZWlnaHQ9JzQwMCcgZmlsbD0ndXJsKCNiKScvPjwvc3ZnPg==";const bytes = new Uint8Array();</script>
<template> <div class="flex flex-wrap items-start gap-6"> <div class="flex flex-col gap-2"> <Image alt="Generated portfolio cover" :base64="base64" class="aspect-[3/2] w-72" media-type="image/svg+xml" :uint8-array="bytes" /> <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";
// A gradient SVG stands in for a generated image (base64 + media type, like the AI SDK returns). const base64 = "PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPSc2MDAnIGhlaWdodD0nNDAwJz48ZGVmcz48cmFkaWFsR3JhZGllbnQgaWQ9J2EnIGN4PScyNSUnIGN5PSczMCUnIHI9JzQ1JSc+PHN0b3Agb2Zmc2V0PScwJyBzdG9wLWNvbG9yPScjZThhMzNkJy8+PHN0b3Agb2Zmc2V0PScxJyBzdG9wLWNvbG9yPScjZThhMzNkJyBzdG9wLW9wYWNpdHk9JzAnLz48L3JhZGlhbEdyYWRpZW50PjxyYWRpYWxHcmFkaWVudCBpZD0nYicgY3g9JzcyJScgY3k9JzY4JScgcj0nNDAlJz48c3RvcCBvZmZzZXQ9JzAnIHN0b3AtY29sb3I9JyMzODZmZDYnLz48c3RvcCBvZmZzZXQ9JzEnIHN0b3AtY29sb3I9JyMzODZmZDYnIHN0b3Atb3BhY2l0eT0nMCcvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHdpZHRoPSc2MDAnIGhlaWdodD0nNDAwJyBmaWxsPScjNjJhMDdhJy8+PHJlY3Qgd2lkdGg9JzYwMCcgaGVpZ2h0PSc0MDAnIGZpbGw9J3VybCgjYSknLz48cmVjdCB3aWR0aD0nNjAwJyBoZWlnaHQ9JzQwMCcgZmlsbD0ndXJsKCNiKScvPjwvc3ZnPg==";</script>
<div class="flex flex-wrap items-start gap-6"> <div class="flex flex-col gap-2"> <Image alt="Generated portfolio cover" {base64} 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>Loading is handled by the parent (spinner and shimmer text, see the demo).
Installation
Section titled “Installation”npx shadcn@latest add @edmi-ui/ai-imagepnpm dlx shadcn@latest add @edmi-ui/ai-imageyarn dlx shadcn@latest add @edmi-ui/ai-imagebunx shadcn@latest add @edmi-ui/ai-imagePick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Install the dependencies:
Terminal window npm install aiTerminal window pnpm add aiTerminal window yarn add aiTerminal window bun add aiCopy the code from Component source into your project and update the import paths to match your aliases.
npx shadcn-vue@latest add @edmi-ui/ai-imagepnpm dlx shadcn-vue@latest add @edmi-ui/ai-imageyarn dlx shadcn-vue@latest add @edmi-ui/ai-imagebunx shadcn-vue@latest add @edmi-ui/ai-imagePick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Install the dependencies:
Terminal window npm install aiTerminal window pnpm add aiTerminal window yarn add aiTerminal window bun add aiCopy the code from Component source into your project and update the import paths to match your aliases.
npx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-image.jsonpnpm dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-image.jsonyarn dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-image.jsonbunx --bun shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/ai-image.jsonPick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Copy the code from Component source into your project and update the import paths to match your aliases.
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>Component source
Section titled “Component source”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}`} />);<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>export { default as Image } from "./Image.vue";<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}/>import Image from "./image.svelte";
export { Image };| Part | Prop | Type | Default |
|---|---|---|---|
| Image | base64, uint8Array, mediaType |
AI SDK GeneratedFile fields |
|
| Image | alt, className |
string |