Skip to content
Agent UI
Provider composesCopy-paste blockzai-composeLive stage

GLM Chat Compose

A copy-paste block that recreates the GLM Chat prompt stage with Z.ai's rail, brand mark, prompt surface, model menu, and tool toggles. The block is not a package component: copy the file, or install it with the shadcn CLI, then edit the layout like any other file in your project. It is assembled entirely from Agent UI compose primitives, and every control is keyboard accessible.

Source you own: install the block with the shadcn CLI or copy components/blocks/composes/zai-compose.tsx. The preview below is the real file, and the code tab is the exact source.

components/blocks/composes/zai-compose.tsx
ZCode ↗API ↗Sign in

Create anything you can imagine

Full-Stack

Writing

Data Insight

Generated by AI. For reference only. · Terms of Service · Privacy Policy

The code tab contains the full block, ready to copy.

Installation

Add the block with the shadcn CLI. It writes components/blocks/composes/zai-compose.tsx and installs its dependencies.

bash
npx shadcn@latest add https://agent-ui-27t.pages.dev/r/zai-compose.json

Prefer to own the file manually? Install the dependencies, then copy the source from the Files section.

bash
pnpm add @agent-ui/react lucide-react

Tailwind CSS v4 users: add @source "../node_modules/@agent-ui/react/src" to the global stylesheet so the library utilities are generated.

Usage

Import the copied file and render it anywhere. The block accepts onSend, disabled, and className; wire onSend to any backend.

tsx
import { ZaiCompose } from "@/components/blocks/composes/zai-compose";
 
<ZaiCompose onSend={(text) => console.log(text)} />

Files

One file. The same source is served by the shadcn registry endpoint, so the CLI and the docs can never drift.

components/blocks/composes/zai-compose.tsxtsx
tsx
"use client";
 
import * as React from "react";
import { ArrowUp, Home, PanelLeft, Plus, Search } from "lucide-react";
import {
ComposeSendButton,
ComposeTextarea,
ModelChip,
createCompose,
useCompose,
type ComposeProps,
} from "@agent-ui/react";
 
const Root = createCompose({
id: "zai",
maxWidth: "max-w-none",
placeholder: "Send a Message",
models: [
{ id: "glm-5-3-flash", name: "GLM-5.3-Flash", hint: "Fast" },
{ id: "glm-5-3", name: "GLM-5.3", hint: "Flagship" },
{ id: "glm-4-6", name: "GLM-4.6", hint: "Previous" },
],
initialToggles: { search: false },
});
 
const GALLERY = [
{ label: "Full-Stack", tone: "from-[#f6f6f4] to-[#ececea]" },
{ label: "Writing", tone: "from-[#f7f7f5] to-[#eeeeec]" },
{ label: "Data Insight", tone: "from-[#f5f7fa] to-[#e9edf5]" },
];
 
/** Z.ai: framed app shell, icon rail, smoky serif hero, capability gallery. */
function ZaiComposeLayout() {
const { toggles, toggle } = useCompose();
return (
<div className="flex min-h-[400px] w-full bg-[#fbfbfa] p-2.5 text-[13px] text-[#1f2329]">
<div className="flex min-w-0 flex-1 overflow-hidden rounded-xl border border-black/[0.08] bg-white">
<aside className="flex w-10 shrink-0 flex-col items-center border-r border-black/[0.06] py-2.5">
<PanelLeft className="h-4 w-4 text-black/45" aria-hidden="true" />
<span className="mt-2 grid h-6 w-6 place-items-center rounded-md bg-[#ececea]">
<Home className="h-3.5 w-3.5" aria-hidden="true" />
</span>
<span className="mt-auto grid h-6 w-6 place-items-center rounded-full bg-[#e8e8e5] text-[10px] font-medium text-black/50">
G
</span>
</aside>
 
<div className="relative flex min-w-0 flex-1 flex-col">
<div className="flex items-center justify-end gap-3 px-4 py-2.5 text-[10.5px]">
<span className="text-black/60">ZCode ↗</span>
<span className="text-black/60">API ↗</span>
<span className="rounded-full bg-[#141414] px-3 py-1.5 text-[10.5px] font-medium text-white">
Sign in
</span>
</div>
 
<div className="relative flex flex-1 flex-col items-center px-5">
<div
aria-hidden="true"
className="pointer-events-none absolute left-1/2 top-0 h-16 w-[300px] -translate-x-1/2 rounded-full bg-[radial-gradient(ellipse_at_center,#9ca3af_0%,#d1d5db_45%,rgba(255,255,255,0)_75%)] opacity-50 blur-xl"
/>
<h1 className="relative mt-2 text-center font-serif text-[22px] font-medium tracking-[-0.01em]">
Create anything you can imagine
</h1>
 
<div className="relative mt-3 grid w-full max-w-[420px] grid-cols-3 gap-2">
{GALLERY.map(({ label, tone }) => (
<div key={label}>
<div
className={`relative h-[62px] overflow-hidden rounded-lg border border-black/[0.05] bg-gradient-to-br ${tone}`}
>
<span className="absolute inset-x-2 top-2 h-1.5 rounded-sm bg-[#e04a3a]/70" />
<span className="absolute inset-x-2 top-4 h-1 rounded-sm bg-black/10" />
<span className="absolute inset-x-2 top-6 h-1 w-3/4 rounded-sm bg-black/10" />
<span className="absolute bottom-2 left-2 h-2.5 w-8 rounded-sm bg-[#141414]/85" />
</div>
<p className="mt-1 text-center text-[9.5px] text-black/60">{label}</p>
</div>
))}
</div>
 
<div
data-agent-id="compose-card"
className="mt-auto mb-2 flex w-full max-w-[470px] flex-col rounded-xl border border-black/[0.09] bg-white p-2.5 shadow-[0_2px_8px_rgba(0,0,0,0.03)] transition-[border-color,box-shadow] duration-200 focus-within:border-black/25 focus-within:shadow-[0_4px_16px_rgba(0,0,0,0.08)]"
>
<ComposeTextarea
aria-label="Send a message to GLM"
placeholder="Send a Message"
rows={1}
className="min-h-[34px] px-0.5 py-1 text-[13.5px] leading-5 placeholder:text-black/35"
/>
<div className="mt-1 flex items-center justify-between">
<div className="flex items-center gap-1">
<button
type="button"
aria-label="Attach"
className="grid h-6 w-6 place-items-center rounded-full border border-black/10 text-black/60 hover:bg-black/5"
>
<Plus className="h-3.5 w-3.5" aria-hidden="true" />
</button>
<button
type="button"
aria-label="Toggle web search"
aria-pressed={toggles.search}
onClick={() => toggle("search")}
className="flex items-center gap-1 rounded-full px-2 py-1 text-[10.5px] text-black/45 hover:bg-black/5 aria-pressed:bg-black/[0.06] aria-pressed:text-black"
>
<Search className="h-3 w-3" aria-hidden="true" /> Web search
</button>
</div>
<div className="flex items-center gap-1.5">
<ModelChip
tone="light"
className="[&>button]:h-7 [&>button]:px-1 [&>button]:text-[11px] [&>button]:text-black/55 [&>button]:hover:bg-black/5"
/>
<ComposeSendButton
aria-label="Send message"
className="h-7 w-7 bg-[#e9e9e6] text-black/45 hover:bg-[#dededa] disabled:bg-[#e9e9e6] disabled:text-black/45 disabled:opacity-100"
icon={<ArrowUp className="h-3.5 w-3.5" strokeWidth={2.2} />}
/>
</div>
</div>
</div>
</div>
 
<p className="px-4 pb-2 text-center text-[8.5px] text-black/35">
Generated by AI. For reference only. ·{" "}
<a href="#" className="underline">
Terms of Service
</a>{" "}
·{" "}
<a href="#" className="underline">
Privacy Policy
</a>
</p>
</div>
</div>
</div>
);
}
 
export function ZaiCompose(props: ComposeProps) {
return (
<Root {...props}>
<ZaiComposeLayout />
</Root>
);
}
 

Built with

The block imports these Agent UI primitives. Each one is a package export with its own docs page, so you can change the layout without giving up the behaviour.

Accessibility

All controls expose accessible names; the textarea supports Enter to send and Shift+Enter for a new line.

GLM Chat also has a full product page.

Metadata, model list, and the same block in a dedicated route.

Open GLM Chat
Use it with the rest of the library

ZaiCompose composes with MessageList, ChatShell, useChat, and the provider compose blocks. Browse the full reference or see all components in the gallery.

149 lines · copy-ready