Events
How vu-* events map across React, Vue, and HTML/Lit — always read e.detail.
Overview
Components emit custom events with a vu- prefix (vu-change, vu-open, vu-close, and others). Read the payload from e.detail — never e.target.value.
Across frameworks
| React | Vue | HTML / Lit | |
|---|---|---|---|
| Value change | onVuChange | v-model:value or @vu-change | @vu-change / addEventListener("vu-change") |
| Overlay open / close | onVuOpen / onVuClose | v-model:open or @vu-open / @vu-close | @vu-open / @vu-close, or addEventListener |
| Payload | Always e.detail (typed *Detail types on React wrappers) | ||
Examples
import { useState } from "react";
import { VuInput } from "@velkin/react/input";
import type { VuInputChangeDetail } from "@velkin/react/input";
export function EmailField() {
const [email, setEmail] = useState("");
return (
<VuInput
label="Email"
value={email}
onVuChange={(e: CustomEvent<VuInputChangeDetail>) => {
setEmail(String(e.detail.value ?? ""));
}}
/>
);
}In Next.js App Router, any file with onVu* or React state plus Velkin needs a client boundary.
import { VuDialog } from "@velkin/react/dialog";
<VuDialog open={open} onVuClose={() => setOpen(false)}>
{/* slots… */}
</VuDialog>Edge cases
- Do not read
e.target.value— usee.detailfields from the component docs. - Do not wire native
onChange/@changeon wrappers — useonVuChange/@vu-change, or Vuev-model:*. - In Lit, set values with property bindings when required —
.value=${…}, not only attributes. - In HTML, listen after the module import finishes.
- Do not invent event names — call MCP
get_velkin_component_docsor open the component Events table.
Next steps
- Slots — named regions and host + item composition
- Methods — imperative
show/hide/focus - Appearance —
variant,color,tone,size,radius - AGENTS.md — consumer contract for agents