npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@chai-ui/vue

v1.4.1

Published

Chai UI Vue components — smart, drop-in UI for AI apps: Composer, Media Analyzer, Result Card, Edit Card, Side Panel, and the useComposer composable.

Readme

@chai-ui/vue

Chai UI for Vue: drop-in components for the input and output surfaces of generative-media apps: a prompt composer, a media-to-prompt analyzer, a result card and an edit card, with the AI work built in and wired to Fal.ai, OpenRouter, Vercel AI Gateway or your own engine. Everything is controlled: you own the state with v-model, and the components render it.

These are the same components as @chai-ui/react and @chai-ui/svelte, with the same behavior. All three are thin layers over @chai-ui/core and run one shared test suite, including the WCAG 2.2 AA checks (axe, keyboard and focus).

Building with it, or pointing a coding agent at it? Read DESIGN.md (shipped in the package) for the usage rules, and the docs site's llms.txt for the API. The code boxes on chai-ui.com/docs switch between React, Vue and Svelte.

Install

pnpm add @chai-ui/vue @chai-ui/core @chai-ui/tokens

Vue 3.5 or later, Nuxt included. No Chai-specific build setup.

// main.ts: tokens first, then the component styles that read them
import "@chai-ui/tokens/css";
import "@chai-ui/vue/style.css";

Your own font

style.css loads Roboto, Material Design 3's typeface. If your app has its own font, import @chai-ui/vue/style-without-fonts.css in its place (the same styles, without Roboto) and point the components at your font:

:root { --chai-type-family-material: "Your Font", system-ui, sans-serif; }

Dark theme

The components have a dark theme. It's opt-in: set data-chai-theme="dark" on <html>, or on any element, and every component inside it switches.

<html data-chai-theme="dark">

Chai doesn't follow the system setting on its own, because your app decides its theme. Following it, overriding a single color, and the dark values themselves are in the @chai-ui/tokens README.

Quick start

<!-- App.vue -->
<template>
  <ChaiProvider><Create /></ChaiProvider>
</template>

<!-- Create.vue -->
<script setup lang="ts">
import { computed, ref } from "vue";
import { Composer, ResultCard, createFalEngine, useComposer } from "@chai-ui/vue";

const engine = createFalEngine();
const value = ref("");
const { run, submit, cancel, enhance, enhancing } = useComposer({ engine });
const busy = computed(() => run.value?.results.some((r) => r.status === "queued" || r.status === "running") ?? false);

async function onEnhance(prompt: string) {
  value.value = await enhance.value!(prompt);
}
</script>

<template>
  <Composer v-model="value" :submitting="busy" :enhancing="enhancing" @submit="submit" @abort="cancel" @enhance="onEnhance" />
  <ResultCard v-if="run" :results="run.results" :prompt="run.request.prompt" @action="() => {}" />
</template>

To try it before setting up a provider, leave out engine and ChaiProvider: everything then runs on built-in mocks, with no network calls and no keys.

The Vue names

The props are React's, with Vue's conventions:

| React | Vue | |---|---| | value + onChange | v-model | | x + onXChange | v-model:x, e.g. v-model:attachments, v-model:model-id, v-model:regions | | onSubmit, onAction, onEnhance, onAbort | @submit, @action, @enhance, @abort | | useComposer / useMediaAnalyzer hooks | composables returning refs; pass a getter for options that change | | <EditCard {...edit} /> | edit's fields one by one, with @update:active-version and @update:regions | | SidePanel's open + onOpenChange, logo and footer | v-model:open, and the #logo and #footer slots (footer also takes text) | | A Composer chip or menu item's icon | A component |

Some controls show only with a listener, as in React: the optimize button with @enhance, stop with @abort, the Model menu with @update:model-id.

Docked the bar? Set menu-placement="above" for a bar fixed to the bottom of the screen, or "below" for one fixed to the top, so every menu opens into the page. Left out, it's "auto": each menu goes where it fits.

What's in the package

  • Composer: prompt, attachments, use cases, model and aspect-ratio menus with suggested models, prompt optimization, auto-select routing, stop and retry.
  • MediaAnalyzer + useMediaAnalyzer: media in, a generation-ready prompt out.
  • ResultCard: one prompt's results, paged, with votes, retry, download, share, details, streaming text and quality-check tags (from your backend, or the opt-in judge: useComposer({ judgeModel, judgeChecks })).
  • Analytics: @event on every component reports what the person does and sees, one ChaiEvent each, for any analytics tool: @event="(e) => posthog.capture(e.name, e.properties)".
  • EditCard: marked regions with their own instructions, and each edit as a new version.
  • SidePanel: a panel beside your page with a Composer and its answers, for questions about the page (opt-in page-context, shown as a removable chip) or anything else, with prompt tips, push or overlay, and either side. Same props as React's, with v-model:open; #logo and #footer slots. See the React README's "A side panel" for the details.
  • useComposer, ChaiProvider, and the Toggle, SearchMenu and Pagination building blocks.
  • The engines and types from @chai-ui/core, re-exported.

Your API keys stay on your server

The engines call one route on your server, which adds the key. In Nuxt:

// server/api/chai/[...path].ts
import { createChaiHandler } from "@chai-ui/core/server";

const chai = createChaiHandler();
export default defineEventHandler((event) => chai.handle(toWebRequest(event)));

Then set FAL_KEY, OPENROUTER_API_KEY or AI_GATEWAY_API_KEY on your server. Other servers, and authorize and allowedModels for production, are in the @chai-ui/core README.

Without a server route

In a desktop app (Tauri, Electron) with no server route, write an engine that hands each run to your app's backend. Pass it to useComposer({ engine: desktopEngine }) and to <ChaiProvider :reasoning-engine="desktopEngine">. The @chai-ui/core README has a Tauri example, voice input, and what Stop does there.