# Image generation

> An image studio where each image forms on a dot matrix: a soft halftone wave breathes across the grid, the dots take the colours of the coming photo and grow into a coloured halftone, then blur away into the sharp photo. One large canvas with a mono size label, a filmstrip of four variations, a prompt bar with model and ratio, and upscale with a sweeping dot band, vary or download, with real provider marks and a built-in simulation.

- Type: Component (special)
- Access: Arc Pro
- Page: https://uiarc.dev/components/image-generation
- Markdown: https://uiarc.dev/components/image-generation/markdown
- Source file: `registry/components/image-generation/image-generation.tsx`
- Dependencies: motion, lucide-react, @radix-ui/react-tooltip
- Keywords: special, ai, new, image generation, text to image, ai image, diffusion, prompt, upscale, variations, filmstrip, generate images, aspect ratio, dot matrix, halftone, loading state, dot spinner, blur to sharp

## When to use

- A text to image feature inside a product: marketing asset tools, listing photo helpers, slide or doc illustration.
- Any flow where people compare a few candidates and continue with one (upscale, vary, download).
- Prototyping an image model integration before the backend exists, using the built in simulation.

## When not to use

- A full canvas editor with layers, masks and inpainting; build on a canvas library instead.
- Drawing a sketch to turn into an image; use sketch-to-image.
- Showing a single image with a loading state and no generation controls; use blur-image.

## Installation

Image generation is part of Arc Pro. The live preview is public; the source and install command need Pro.

### CLI with a Pro token

1. Create a token in your account and set it in the environment (or `.env.local`). Never commit it.

```bash
export ARC_PRO_TOKEN=arc_pro_...
```

2. Add the Pro registry to `components.json`:

```json
{
  "registries": {
    "@uiarc": "https://uiarc.dev/r/{name}.json",
    "@uiarc-pro": {
      "url": "https://uiarc.dev/r/pro/{name}.json",
      "headers": {
        "Authorization": "Bearer ${ARC_PRO_TOKEN}"
      }
    }
  }
}
```

3. Install:

```bash
npx shadcn@latest add @uiarc-pro/image-generation
```

### Manual

Signed-in Pro members can copy the source from the Manual tab on the docs page.

- Plans: https://uiarc.dev/pricing
- Create a Pro token: https://uiarc.dev/account#pro-access
- Setup guide: https://uiarc.dev/docs/ai#pro-access

## Usage

```tsx
import { ImageGeneration } from "@/components/arc/image-generation/image-generation";

export function Studio() {
  return <ImageGeneration
    onGenerate={async (request, { signal, onProgress }) => {
      const job = await fetch("/api/images", {
        method: "POST",
        signal,
        body: JSON.stringify({ prompt: request.prompt, model: request.model.id, size: `${request.aspect.width}x${request.aspect.height}`, seedFrom: request.variationOf?.id }),
      }).then(response => response.json());
      onProgress(1);
      return { id: job.id, src: job.url, alt: request.prompt, width: request.aspect.width, height: request.aspect.height };
    }}
    onDownload={image => window.open(image.src)}
  />;
}
```

## API reference

### ImageGeneration

An image studio card: one large canvas shows the chosen image, a filmstrip of four variations sits under it beside Upscale, Vary and Download, and a prompt bar with model and aspect chips closes the card. Each image forms on a dot matrix: a soft halftone wave breathes across the grid, the dots take the colours of the coming photo and grow into a coloured halftone, then blur away into the sharp photo. A mono size label sits top right and a status pill with a 3×3 dot spinner bottom left. With no props it runs a local simulation on sample photos.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `prompt` | `string` | – | Controlled prompt. Pair with onPromptChange. |
| `defaultPrompt` | `string` | `sample golden hour landscape prompt` | Starting prompt when uncontrolled. |
| `onPromptChange` | `(prompt: string) => void` | – | Fires as the person types or picks a suggestion. |
| `models` | `ImageGenerationModel[]` | `imageGenerationModels` | Models offered as chips: { id, name, mark? }. The chosen chip shows its name, the others collapse to their 16px mark with a tooltip. |
| `model` | `string` | – | Controlled model id. Pair with onModelChange. |
| `defaultModel` | `string` | `first model` | Starting model id when uncontrolled. |
| `onModelChange` | `(id: string) => void` | – | Fires when a model chip is chosen. |
| `aspectRatios` | `ImageGenerationAspect[]` | `1:1, 4:5, 16:9` | Output shapes: { id, label, width, height }. Width and height are the pixels a generation returns, drive the canvas shape and show in the size label. |
| `aspectRatio` | `string` | – | Controlled aspect id. Pair with onAspectRatioChange. |
| `defaultAspectRatio` | `string` | `first ratio` | Starting aspect id when uncontrolled. |
| `onAspectRatioChange` | `(id: string) => void` | – | Fires when an aspect chip is chosen. Before the first generation the canvas springs to the new shape; after that the shape applies to the next generation and the current batch keeps its own. |
| `onGenerate` | `(request: ImageGenerationRequest, context: { signal: AbortSignal; onProgress(progress: number, preview?: string): void }) => Promise<ImageGenerationImage>` | `simulateImageGeneration` | Produces one image. Called once per variation, in parallel, for Generate, Vary (request.variationOf is set) and Retry. Report progress from 0 to 1, optionally with a preview URL: the dots sample their colours from it and dissolve into it over the last fifth of the run (without one, the dots stay neutral and the image resolves from soft to sharp when it arrives); without reports progress estimates. Reject to mark that variation failed; the signal aborts on Stop or Escape. |
| `onUpscale` | `(image: ImageGenerationImage, context: ImageGenerationContext) => Promise<ImageGenerationImage>` | `simulateImageUpscale` | Upscales the image on the canvas. Return the new image with its width and height; the size label updates to it. |
| `onDownload` | `(image: ImageGenerationImage) => void` | – | Replaces the built in download, which saves image.src with a file name built from the prompt, index and size. |
| `onSelect` | `(image: ImageGenerationImage \| null) => void` | – | Fires with the image on the canvas: when the person picks a finished variation, when the shown variation finishes, with the upscaled image once an upscale finishes, and with null when a new batch starts. |
| `suggestions` | `string[]` | `three sample prompts` | Prompts offered on the empty canvas before the first generation. |
| `autoGenerate` | `boolean` | `true with the simulation, false with onGenerate` | Generates once when the card first scrolls into view, unless someone has already touched it. |
| `placeholder` | `string` | `"Describe the image you want"` | Prompt placeholder. |
| `className` | `string` | – | Class on the card. |

### simulateImageGeneration

The built in generator, exported so you can wrap it in tests or demos. Picks sample photos that match the prompt, reports the photo as the preview and frame by frame progress over about four and a half to six seconds. Nothing is sent anywhere.

No props.

## Keyboard interactions

| Keys | Action |
| --- | --- |
| Cmd/Ctrl + Enter | Generate from the prompt field. |
| Arrow keys | Move between model chips or aspect chips, and between variations in the filmstrip (each one shows on the canvas as focus lands). |
| Escape | Stop a running generation; finished images are kept. |
| Tab | The chosen variation, Upscale, Vary, Download, then the prompt, model, aspect and Generate. |

## Accessibility

- Model and aspect chips and the filmstrip are radio groups with a roving tab stop; collapsed model chips keep their name as the accessible label and in a tooltip.
- The canvas is labelled with the image description once done, or with the variation's state while it generates, fails or stops; each thumbnail names its number and state.
- A polite live region reports starts, finishes, failures, picks, upscales and downloads, and says when results are simulated.
- Status is never color alone: failures pair a danger icon with "Failed" and the error, stops a square icon with "Stopped", the chosen thumbnail an accent ring with aria-checked, progress a spinner with a percentage.
- Icon only actions at narrow widths keep Upscale, Vary and Download as their accessible names.

## Motion

- Each image loads on a canvas of small neutral dots, drawn at device pixel ratio. A soft radial halftone wave breathes and wanders across the grid: dots under it grow and darken, and a blurred twin of them glows like a lens.
- From 20% the dots take the colour of the coming photo at their cell (the preview downscaled to the grid, cover fitted), showing first under the wave, and grow by the photo's darkness, so by 78% the image reads as a coloured halftone.
- Over the last fifth the dots blur and fade while the photo sharpens out of them from 12px blur and 4% zoom. The final frame is the photo, and the real <img> lands on it without a cut; an image that differs from the preview resolves from soft to sharp in 480ms.
- The filmstrip thumbnails run their own small dot fields, so all four variations show their progress at once. Picking another variation crossfades the canvas in 200ms.
- Upscale sweeps a vertical band of halftone dots in the photo's colours left to right: soft ahead of it, sharp behind it, the dots and their blurred twin in it, all from one motion value. The size label crossfades to the new size.
- The status pill carries a 3×3 dot spinner whose dots light in turn around the ring, with a mono percentage; pills crossfade by key so a label never resizes in a frame.
- The canvas springs to a new aspect ratio; a container resize cuts straight to the new size. Labels that change inside buttons (Generate and Stop, Upscale, Upscaling, Upscaled, Download and Saved) are stacked in one cell and crossfade, so no button changes width.
- Reduced motion draws a still dot grid with the halftone glow at rest, crossfades the photo in by progress, keeps the spinner still and drops the upscale sweep.

## Responsive behavior

- The card fills its container up to 600px. The canvas keeps the batch's ratio and caps its height at 440px, so portrait shapes stay compact.
- Below 500px of card width the actions drop their labels to icons, so the four thumbnails always fit beside them; thumbnails shrink and stay square.
- Below 440px the model chips and Generate share the first row of the prompt bar and the ratio chips move to a second.

## Performance

- Progress is written straight to motion values, the canvas and styles; React re-renders only on state changes (preview arrives, image finishes).
- The large canvas draws about four thousand dots per frame with one 2D context plus a blurred twin for the wave; thumbnails draw under two hundred.
- The preview is sampled once per grid size and cached; a cross origin image without CORS keeps the neutral dots.
- A loop runs only while its image generates and is on screen; finished, failed and stopped fields draw once and stop, and redraw on theme change.

## Notes for AI

- Wire onGenerate to your image API; it runs once per variation, so a provider that returns four images per call can be wrapped by caching one request and resolving each index from it.
- Use request.variationOf to pass a seed or reference image for Vary. Return width and height so the footer and file names show the real size.
- Keep model names to what your backend actually serves; the defaults are generic product names with provider marks.
- Pair with a gallery or asset picker by listening to onSelect; the component holds only the current batch.

## Related

- [Model picker](https://uiarc.dev/components/blocks/model-picker/markdown): A model picker in one quiet pill: open it to choose from featured models with a one line note each, set the reasoning effort, or browse every other model by provider, and the pill swaps to your choice in place.
- [AI composer](https://uiarc.dev/components/blocks/ai-composer/markdown): The prompt box at the bottom of an AI app: files upload in place, / opens commands, @ inserts mentions, a model and effort menu sits in the toolbar, and the send button turns into a stop control ringed by the reply's progress.
- [Text shimmer](https://uiarc.dev/components/text-shimmer/markdown): Show ongoing work with a calm light across the words.

## Also in ai

- [Agent status](https://uiarc.dev/components/agent-status/markdown): A compact live status pill for a running AI agent: the agent's mark in a live ring, the current activity and an elapsed timer, opening into the steps so far.
- [Tool call](https://uiarc.dev/components/tool-call/markdown): A tool call row for agent transcripts: the tool's mark and the call in plain words, a live state while it runs, and the input and output a click away, with approval and retry when needed.
- [Agent plan](https://uiarc.dev/components/agent-plan/markdown): The plan an agent writes before it acts: edit, reorder or add steps while it is a draft, then watch it work through them as a live checklist.
- [Agent timeline](https://uiarc.dev/components/agent-timeline/markdown): A compact timeline of one orchestrated agent run: the orchestrator and its subagents share a time axis, handoffs draw in between rows, and a playhead replays thinking, tool calls and waiting while the header counts time, tokens and cost. Hover a span for what it did, or click it to trace its handoff path.
- [Context window](https://uiarc.dev/components/context-window/markdown): An AI context window as a grid of 200 cells: the system prompt, tools, files, summary and messages fill it in order, a threshold row marks where compaction starts, and sending a message, attaching a file or compacting shows exactly how much still fits.
- [Reasoning block](https://uiarc.dev/components/reasoning-block/markdown): The collapsible thinking block of an AI reply. While the model thinks, a shimmering label counts the seconds and the latest reasoning streams underneath. When it finishes, it folds to "Thought for 7s" and opens to show the full reasoning as calm steps with headings.
- [Source cards](https://uiarc.dev/components/source-cards/markdown): A row of cited sources under an AI answer where cards stream in with real site marks while the model searches, the overflow collapses into a stack of favicons, hovering lifts a preview with the passage, and an inline [n] citation highlights its card.
- [Model card](https://uiarc.dev/components/model-card/markdown): A model details card where switching models rolls every price, limit and score in place, a token slider estimates monthly cost live, and benchmark bars show each model's rank on hover. Compare crossfades to a side-by-side table against any rival with the better values marked, and the card never changes size.
- [AI workflow](https://uiarc.dev/components/ai-workflow/markdown): A Linear-style AI workflow card where a Gmail trigger, a Claude step, a branch and Slack and Linear actions sit on one hairline rail, and a test run glides down it, opening each step's output inline. Steps are added from a compact command menu with real app marks.
- [Code suggestion](https://uiarc.dev/components/code-suggestion/markdown): An AI code edit suggestion where the model's proposed changes stream into a small editor panel as inline diff hunks, and you accept or reject each one, or all at once with Cmd+Enter. Accepted hunks fold into the file with a smooth height change.
- [Ghost text](https://uiarc.dev/components/ghost-text/markdown): An inline AI autocomplete where muted ghost text continues your sentence exactly at the caret and Tab turns it solid in place. Cmd+Right takes it one word at a time, Escape fades it away, and a calm chip shows the model behind it.
- [Dictation button](https://uiarc.dev/components/dictation-button/markdown): A chat composer with voice input, where the mic springs into a recording pill with a smooth live waveform, a timer, and cancel and insert buttons. Words stream into the field as you speak, muted until the recognizer settles them.
- [Speech player](https://uiarc.dev/components/speech-player/markdown): A read-aloud player for AI replies. The Read aloud button in the message's action row turns into a compact player with play, a scrubbable progress bar, speed and a voice picker, and a highlight follows the spoken word through the reply, karaoke style.
- [Meeting summary](https://uiarc.dev/components/meeting-summary/markdown): An AI meeting notes card: the header shows the Google Meet or Zoom mark, the attendees and the duration. Summary, Decisions and Action items stream in after a short summarizing pass. Hover any line to see the transcript quote it came from, then check off action items or send them to Linear or Notion.
- [Reply draft](https://uiarc.dev/components/reply-draft/markdown): An AI email reply drafter where Claude streams a reply under a received Gmail message. Quick replies steer a fresh draft, tone and length rewrite it with a single crossfade, and you can edit the finished draft before you insert it.
- [Agent handoff](https://uiarc.dev/components/agent-handoff/markdown): A support conversation where an AI assistant hands off to a person. When it transfers, a card shows the summary it passes to the team and the typical wait. The person then joins and takes over, and a thin timeline on the left marks each step.
- [PII redaction](https://uiarc.dev/components/pii-redaction/markdown): A guardrail card where personal data is redacted before the prompt reaches the model. Scan marks each name, email, phone number and card with its type and swaps it for a placeholder like [EMAIL_1]. The safe prompt travels to Claude, and the reply comes back with the original values put back for the person.
- [Response feedback](https://uiarc.dev/components/response-feedback/markdown): A feedback control for AI replies where thumbs down opens an inline panel with reason chips and an optional note, thumbs up fills and asks what was good, and a submit shows a short thank-you before folding back into the row.
- [LLM cost calculator](https://uiarc.dev/components/llm-cost-calculator/markdown): A pricing calculator for LLM workloads. Set tokens per request, requests per day and prompt caching, and eight current models re-rank by monthly cost. Bars glide and prices roll as you drag.
- [Provider keys](https://uiarc.dev/components/provider-keys/markdown): A settings card for bring-your-own-key AI products. Each provider row shows its real mark, the masked key, a status and when the key was last used. You can reveal a key for five seconds, copy, rotate or remove it with undo. Adding or rotating a key opens an inline form that checks the format as you type, then tests the connection before saving.
- [Generation stats](https://uiarc.dev/components/generation-stats/markdown): A live stats strip for a streaming LLM response where time to first token, speed with a sparkline, output tokens and cost count up in tabular numerals beside the model's real mark, then settle and open into a latency and token cost breakdown.
- [AI translate](https://uiarc.dev/components/ai-translate/markdown): A message card where picking a language streams the AI translation in place, sentence by sentence over the dimmed original, with a detected-language chip, a Show original toggle and a status line credited to the model's mark.
- [TL;DR toggle](https://uiarc.dev/components/tldr-toggle/markdown): An article card with a Full, Summary and Key points switch and a length slider. Switching streams an AI summary in place of the article as the card's height springs to fit, and each key point links back to the paragraph it came from, which gets scrolled to and highlighted.
- [Connector setup](https://uiarc.dev/components/connector-setup/markdown): A "Connect your tools" card for an AI assistant. Each app connects inline: it redirects, authorizes and runs a first sync with a progress hairline, then lists the scopes it was granted and offers Disconnect with an inline confirm.
- [Smart form fill](https://uiarc.dev/components/smart-form-fill/markdown): A paste-to-fill form card where AI reads an email signature or messy notes and fills a contact field by field. Each value flashes in with a confidence dot, its source lights up in the pasted text, low-confidence guesses ask for review, and Undo puts the old values back.
- [Enrich column](https://uiarc.dev/components/enrich-column/markdown): An AI enrichment column for a data table, where one prompt runs down every row and each cell shimmers while it works, then settles into a value with its source or a failure you can retry.
- [Ticket router](https://uiarc.dev/components/ticket-router/markdown): A support ticket router where messages from Gmail, Intercom, Slack and Zendesk come in one at a time. An AI classifier labels each one with intent, sentiment and confidence, and the ticket moves into a team lane with an assignee. Low confidence tickets wait in a review lane, and one click there routes them to the suggested team.
- [Ask your data](https://uiarc.dev/components/ask-your-data/markdown): A natural language to chart card: you ask a question, PostgreSQL streams into a collapsible, syntax highlighted panel, the query runs with a rolling row count, and the answer builds as stacked bars, lines or a table, with a one line insight streamed in underneath.
- [Agent cursor](https://uiarc.dev/components/agent-cursor/markdown): A live document where Claude edits like a collaborator. Its labeled cursor comes out of its avatar, selects a paragraph and streams in a rewrite, adds a heading and fixes a typo, while a teammate's cursor reads along. Changes stay tinted until someone accepts or undoes them from a floating review bar.
- [Provider status](https://uiarc.dev/components/provider-status/markdown): A status card for the AI providers your product depends on. Each row shows the provider's real mark, its health as an icon and label, p50 latency and a 30-day uptime bar with a tooltip for each day. An incident row expands into its timeline of updates, and the card checks again on a visible countdown.
- [Training run](https://uiarc.dev/components/training-run/markdown): A fine-tuning job card where a live train and validation loss curve draws across a fixed step axis that doubles as the epoch progress bar. It shows the learning rate, elapsed time, ETA and the latest evals and checkpoints, has Pause and Cancel while it runs, and ends in results with a Deploy button.
- [AI command](https://uiarc.dev/components/ai-command/markdown): A Cmd+K command palette with an AI mode. Search pages and actions, or press Tab to ask a question: the answer streams inside the palette with numbered sources, and the next steps it suggests, like filing a Linear issue or opening a Notion doc, run straight from the list.
- [Starter prompts](https://uiarc.dev/components/starter-prompts/markdown): A greeting and a grid of starter cards for the empty state of an AI app. The cards are grouped into Write, Code, Analyze and Plan tabs, and a shuffle swaps them with a short staggered crossfade. Picking a card fills the composer, and cards that use a connected app show its mark (Gmail, GitHub, Notion, Linear, Google Calendar).
- [AI mascot](https://uiarc.dev/components/ai-mascot/markdown): A small assistant character, a soft pebble with pill eyes and a companion dot, that shows what the AI is doing. It breathes and glances when idle, leans in to listen, looks up while the dot orbits its head, reads along the line it writes, squints with a sparkle when done and shakes once with worried brows on an error.
- [Image reveal](https://uiarc.dev/components/image-reveal/markdown): An image generation canvas where a soft, blurred preview made from the image's own colors sharpens top to bottom behind a soft-edged band. It works the way ChatGPT, Midjourney and Gemini show images forming, with fine film grain, a translucent progress pill and calm queued and error states.
- [AI spark](https://uiarc.dev/components/ai-spark/markdown): A brand-quality animated spark mark. Four tapered rays and four lighter diagonals breathe at rest, ripple while thinking, pulse like a heartbeat while writing, then gather and settle when done. Every status change blends from the pose the mark is already in.
- [Pixel mascot](https://uiarc.dev/components/pixel-mascot/markdown): A pixel-art robot that shows what an AI assistant is doing. It idles, thinks, types, celebrates and errors in frame-stepped sprite animations, and stays crisp at every integer size from 24px to 192px.
- [Ghost mascot](https://uiarc.dev/components/ghost-mascot/markdown): A floating ghost mascot whose soft sheet ripples at the hem while it hovers. It blinks when idle, turns toward you to listen, fades a little translucent while thinking, draws a tiny pen line while writing, smiles with a sparkle when done and wobbles once on an error.
- [Cube mascot](https://uiarc.dev/components/cube-mascot/markdown): An isometric cube mascot where three shaded faces and a painted-on face show what the assistant is doing. It turns a quarter turn in eased steps while thinking, prints lines onto the floor while writing, settles with a sparkle when done, and shakes once on error.
- [Tone tuner](https://uiarc.dev/components/tone-tuner/markdown): A brand voice card where two sliders (formality and detail) and Friendly, Confident and Empathetic chips rewrite a customer reply. Each changed sentence crossfades in place, new words can be highlighted against the original, and Copy takes the current version.
- [Upgrade prompt](https://uiarc.dev/components/upgrade-prompt/markdown): An upgrade nudge for the moment someone hits a limit. It shows a usage meter at 50 of 50 AI credits, a rolling price with a monthly and yearly toggle, three concrete unlocks with real model marks, and Upgrade or Maybe later. Upgrading leads into a success state with the new limits, and the card never changes size between states.
- [Referral card](https://uiarc.dev/components/referral-card/markdown): A give-and-get referral card where people copy or share their invite link, invite friends by email as chips, and watch invites move from invited to signed up to earned, with the credit total counting up and a milestone reward unlocking.
- [Trial banner](https://uiarc.dev/components/trial-banner/markdown): A trial status banner where a ring counts down the days left, the copy names what the workspace loses, and the upgrade path is one click away. It comes as a slim banner, a sidebar card or a header pill. It shifts to a warning tone in the last days, has expired and upgraded states, and folds into the pill when dismissed or snoozed.
- [Team switcher](https://uiarc.dev/components/team-switcher/markdown): A workspace switcher like Linear, Vercel or Slack. The trigger shows the current workspace's logo and plan. The menu has search, your role in each workspace and a Cmd+1 to 9 shortcut for each, and lets you create or join a workspace inline. A highlight glides between rows, and switching crossfades the trigger through a short loading state.
- [Live visitors](https://uiarc.dev/components/live-visitors/markdown): A realtime visitors card where the live count rolls digit by digit, new arrivals ping in on a dotted world map, the top pages reorder with bars, and signups and upgrades tick in with country flags.
- [Social proof toast](https://uiarc.dev/components/social-proof-toast/markdown): A stack of social proof notifications for landing and pricing pages, where recent trials, upgrades and verified purchases from people and companies arrive every few seconds. The stack pauses and fans out on hover, and visitors can dismiss any toast.
- [Install snippet](https://uiarc.dev/components/install-snippet/markdown): A "get started in 30 seconds" card where framework tabs, three numbered steps and highlighted snippets take a developer from install to first event. Generate key wipes a fresh API key into the placeholder in place.

## Guidance for AI tools

Image generation: An image studio where each image forms on a dot matrix: a soft halftone wave breathes across the grid, the dots take the colours of the coming photo and grow into a coloured halftone, then blur away into the sharp photo. One large canvas with a mono size label, a filmstrip of four variations, a prompt bar with model and ratio, and upscale with a sweeping dot band, vary or download, with real provider marks and a built-in simulation. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://uiarc.dev/llms.txt
