Components
Web Preview
A link-preview card for a web page an AI response references. Purely presentational — no Morphos equivalent.
Installation
npx kosmesis add web-previewpnpm dlx kosmesis add web-previewyarn dlx kosmesis add web-previewbunx kosmesis add web-previewCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import { cn } from "@/lib/utils";export interface WebPreviewProps { url: string; title: string; description?: string; image?: string; class?: string;}@Component()export class WebPreview extends StatelessComponent<WebPreviewProps> { render() { const { url, title, description, image, class: cls } = this.props; let hostname = url; try { hostname = new URL(url).hostname; } catch { // not a fully-qualified URL — fall back to showing it as-is } return ( <a href={url} target="_blank" rel="noopener noreferrer" data-slot="web-preview" class={cn("flex gap-3 rounded-lg border bg-card p-3 text-card-foreground hover:bg-accent/50", cls)} > {image && <img src={image} alt="" class="size-14 shrink-0 rounded-md object-cover" />} <div class="min-w-0 flex-1"> <p class="truncate text-sm font-medium">{title}</p> {description && <p class="mt-0.5 line-clamp-2 text-xs text-muted-foreground">{description}</p>} <p class="mt-1 truncate text-xs text-muted-foreground">{hostname}</p> </div> </a> ); }}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 { StatelessComponent } from "@praxisjs/core";import { cx, Stylesheet, Styled, tokenVars } from "@praxisjs/css";import { Component } from "@praxisjs/decorators";import { KosmesisTokens } from "@/lib/kosmesis-theme";const t = tokenVars(KosmesisTokens);class WebPreviewStyles extends Stylesheet { $root = this.css({ display: "flex", gap: "0.75rem", borderRadius: "0.5rem", border: `1px solid ${t.border}`, backgroundColor: t.card, color: t.cardForeground, padding: "0.75rem", }).on("&:hover", { backgroundColor: `color-mix(in oklab, ${t.accent} 50%, transparent)` }); $image = this.css({ height: "3.5rem", width: "3.5rem", flexShrink: 0, borderRadius: "0.375rem", objectFit: "cover" }); $body = this.css({ minWidth: 0, flex: "1 1 0%" }); $title = this.css({ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: "0.875rem", fontWeight: 500 }); $description = this.css({ marginTop: "0.125rem", display: "-webkit-box", WebkitLineClamp: "2", WebkitBoxOrient: "vertical", overflow: "hidden", fontSize: "0.75rem", color: t.mutedForeground, }); $host = this.css({ marginTop: "0.25rem", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: "0.75rem", color: t.mutedForeground, });}export interface WebPreviewProps { url: string; title: string; description?: string; image?: string; class?: string;}@Component()export class WebPreview extends StatelessComponent<WebPreviewProps> { @Styled(WebPreviewStyles) $s!: WebPreviewStyles; render() { const { url, title, description, image, class: cls } = this.props; let hostname = url; try { hostname = new URL(url).hostname; } catch { // not a fully-qualified URL — fall back to showing it as-is } return ( <a href={url} target="_blank" rel="noopener noreferrer" data-slot="web-preview" class={cx(this.$s.$root, cls)}> {image && <img src={image} alt="" class={this.$s.$image} />} <div class={this.$s.$body}> <p class={this.$s.$title}>{title}</p> {description && <p class={this.$s.$description}>{description}</p>} <p class={this.$s.$host}>{hostname}</p> </div> </a> ); }}Examples
About
Purely presentational — no Morphos equivalent. The hostname is derived from url via the URL
constructor (falling back to the raw string if it isn't fully-qualified). image is optional —
without it, the card is just title/description/hostname.
Usage
import { WebPreview } from "@/components/ui/web-preview";
<WebPreview
url="https://example.com/docs"
title="Example Docs"
description="Everything you need to get started."
/>Props
| Prop | Type | Default |
|---|---|---|
url | string | — |
title | string | — |
description | string | — |
image | string | — |
class | string | — |