Components
Code Block
A plain code display with a copy button. Purely presentational — no Morphos equivalent.
Installation
npx kosmesis add code-blockpnpm dlx kosmesis add code-blockyarn dlx kosmesis add code-blockbunx kosmesis add code-blockCopy 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 CodeBlockProps { code: string; language?: string; filename?: string; class?: string;}// Deliberately avoids a heavy syntax-highlighter dependency like shiki — bring your own// highlighted HTML via `children` if you need real highlighting.@Component()export class CodeBlock extends StatefulComponent { @Prop() code = ""; @Prop() language?: string; @Prop() filename?: string; @Prop() class?: string; @State() _copied = false; private _timeout?: ReturnType<typeof setTimeout>; async copy(): Promise<void> { try { await navigator.clipboard.writeText(this.code); this._copied = true; clearTimeout(this._timeout); this._timeout = setTimeout(() => { this._copied = false; }, 1500); } catch { // clipboard unavailable (insecure context, permission denied, ...) — no-op } } onUnmount(): void { clearTimeout(this._timeout); } render() { return ( <div data-slot="code-block" class={cn("overflow-hidden rounded-lg border bg-muted/30", this.class)}> {(this.filename ?? this.language) !== undefined && ( <div class="flex items-center justify-between border-b bg-muted/50 px-4 py-2 text-xs text-muted-foreground"> <span>{this.filename ?? this.language}</span> </div> )} <div class="relative"> <pre class="overflow-x-auto p-4 text-sm"> <code>{this.code}</code> </pre> <button type="button" aria-label="Copy code" class="absolute top-2 right-2 rounded-md border bg-background px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground" onClick={() => { void this.copy(); }} > {() => (this._copied ? "Copied!" : "Copy")} </button> </div> </div> ); }}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 CodeBlockStyles extends Stylesheet { $root = this.css({ overflow: "hidden", borderRadius: "0.5rem", border: `1px solid ${t.border}`, backgroundColor: `color-mix(in oklab, ${t.muted} 30%, transparent)`, }); $header = this.css({ display: "flex", alignItems: "center", justifyContent: "space-between", borderBottom: `1px solid ${t.border}`, backgroundColor: `color-mix(in oklab, ${t.muted} 50%, transparent)`, padding: "0.5rem 1rem", fontSize: "0.75rem", color: t.mutedForeground, }); $body = this.css({ position: "relative" }); $pre = this.css({ overflowX: "auto", padding: "1rem", fontSize: "0.875rem" }); $copy = this.css({ position: "absolute", top: "0.5rem", right: "0.5rem", borderRadius: "0.375rem", border: `1px solid ${t.border}`, backgroundColor: t.background, padding: "0.25rem 0.5rem", fontSize: "0.75rem", color: t.mutedForeground, cursor: "pointer", }).on("&:hover", { backgroundColor: t.accent, color: t.accentForeground });}export interface CodeBlockProps { code: string; language?: string; filename?: string; class?: string;}// Deliberately avoids a heavy syntax-highlighter dependency like shiki — bring your own// highlighted HTML via `children` if you need real highlighting.@Component()export class CodeBlock extends StatefulComponent { @Styled(CodeBlockStyles) $s!: CodeBlockStyles; @Prop() code = ""; @Prop() language?: string; @Prop() filename?: string; @Prop() class?: string; @State() _copied = false; private _timeout?: ReturnType<typeof setTimeout>; async copy(): Promise<void> { try { await navigator.clipboard.writeText(this.code); this._copied = true; clearTimeout(this._timeout); this._timeout = setTimeout(() => { this._copied = false; }, 1500); } catch { // clipboard unavailable (insecure context, permission denied, ...) — no-op } } onUnmount(): void { clearTimeout(this._timeout); } render() { return ( <div data-slot="code-block" class={cx(this.$s.$root, this.class)}> {(this.filename ?? this.language) !== undefined && <div class={this.$s.$header}>{this.filename ?? this.language}</div>} <div class={this.$s.$body}> <pre class={this.$s.$pre}> <code>{this.code}</code> </pre> <button type="button" aria-label="Copy code" class={this.$s.$copy} onClick={() => { void this.copy(); }}> {() => (this._copied ? "Copied!" : "Copy")} </button> </div> </div> ); }}Examples
About
Purely presentational — no Morphos equivalent, and deliberately avoids a heavy
syntax-highlighter dependency like shiki (same reasoning Carousel avoids Embla): plain
<pre><code> with a copy button, no highlighting.
Usage
import { CodeBlock } from "@/components/ui/code-block";
<CodeBlock code={source} language="ts" filename="greet.ts" />Props
| Prop | Type | Default |
|---|---|---|
code | string | — |
language | string | — |
filename | string | — |
class | string | — |