Components
AI Image
An image the AI generated or referenced, with a fade-in once loaded. Purely presentational — no Morphos equivalent.
Installation
npx kosmesis add ai-imagepnpm dlx kosmesis add ai-imageyarn dlx kosmesis add ai-imagebunx kosmesis add ai-imageCopy and paste the following code into your project.
import { StatefulComponent } from "@praxisjs/core";import { Component, Prop, State } from "@praxisjs/decorators";import { cn } from "@/lib/utils";export interface AiImageProps { src: string; alt: string; caption?: string; class?: string;}@Component()export class AiImage extends StatefulComponent { @Prop() src = ""; @Prop() alt = ""; @Prop() caption?: string; @Prop() class?: string; @State() _loaded = false; render() { return ( <figure data-slot="ai-image" class={cn("overflow-hidden rounded-lg border bg-muted", this.class)}> <img src={this.src} alt={this.alt} data-loaded={() => (this._loaded ? "" : undefined)} class="block w-full object-cover opacity-0 transition-opacity duration-300 data-[loaded]:opacity-100" onLoad={() => { this._loaded = true; }} /> {this.caption && <figcaption class="border-t px-3 py-2 text-xs text-muted-foreground">{this.caption}</figcaption>} </figure> ); }}Install the following dependencies:
npm install @praxisjs/csspnpm add @praxisjs/cssyarn add @praxisjs/cssbun add @praxisjs/cssCopy and paste the following code into your project.
import { StatefulComponent } from "@praxisjs/core";import { cx, Stylesheet, Styled, tokenVars } from "@praxisjs/css";import { Component, Prop, State } from "@praxisjs/decorators";import { KosmesisTokens } from "@/lib/kosmesis-theme";const t = tokenVars(KosmesisTokens);class AiImageStyles extends Stylesheet { $root = this.css({ overflow: "hidden", borderRadius: "0.5rem", border: `1px solid ${t.border}`, backgroundColor: t.muted }); $image = this.css({ display: "block", width: "100%", objectFit: "cover", opacity: 0, transition: "opacity 300ms ease" }).on( "&[data-loaded]", { opacity: 1 }, ); $caption = this.css({ borderTop: `1px solid ${t.border}`, padding: "0.5rem 0.75rem", fontSize: "0.75rem", color: t.mutedForeground, });}export interface AiImageProps { src: string; alt: string; caption?: string; class?: string;}@Component()export class AiImage extends StatefulComponent { @Styled(AiImageStyles) $s!: AiImageStyles; @Prop() src = ""; @Prop() alt = ""; @Prop() caption?: string; @Prop() class?: string; @State() _loaded = false; render() { return ( <figure data-slot="ai-image" class={cx(this.$s.$root, this.class)}> <img src={this.src} alt={this.alt} data-loaded={() => (this._loaded ? "" : undefined)} class={this.$s.$image} onLoad={() => { this._loaded = true; }} /> {this.caption && <figcaption class={this.$s.$caption}>{this.caption}</figcaption>} </figure> ); }}Examples
About
Purely presentational — no Morphos equivalent. The <img> starts at opacity-0 and fades in on
its native load event, so a slow/generated image doesn't pop in abruptly.
Usage
import { AiImage } from "@/components/ui/ai-image";
<AiImage src={generatedUrl} alt="Generated preview" caption="Generated with your prompt" />Props
| Prop | Type | Default |
|---|---|---|
src | string | — |
alt | string | — |
caption | string | — |
class | string | — |