---
title: "shadcn-vue"
description: "Render GistUI answers with your shadcn-vue components in Vue and Nuxt, with form validation and bind:$var still working."
---

> Documentation Index
> Fetch the complete documentation index at: https://gistui.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# shadcn-vue

For Vue and Nuxt apps built with [shadcn-vue](https://www.shadcn-vue.com) and Tailwind.

```sh
npm i @gistui/vue @gistui/styles @gistui/catalog
yarn add @gistui/vue @gistui/styles @gistui/catalog
pnpm add @gistui/vue @gistui/styles @gistui/catalog
bun add @gistui/vue @gistui/styles @gistui/catalog
```

## 1. Order the CSS

GistUI's stylesheet must come **before** Tailwind, so the cascade layers are `theme, base, gistui, components, utilities`: above Tailwind's reset, below its utilities.

```ts title="main.ts"
import "@gistui/styles/styles.css";
import "./assets/index.css"; // @import "tailwindcss"; and the shadcn-vue theme
```

## 2. Match the theme with tokens

shadcn-vue uses the same CSS variables as shadcn/ui.

```ts
export const tokens = {
  font: "inherit",
  radius: 10,
  bg: "var(--background)",
  surface: "var(--card)",
  surfaceSunk: "var(--muted)",
  surfaceHover: "var(--accent)",
  fg: "var(--foreground)",
  fgMuted: "var(--muted-foreground)",
  border: "var(--border)",
  borderStrong: "var(--input)",
  primary: "var(--primary)",
  primaryFg: "var(--primary-foreground)",
  accent: "var(--primary)",
  accentFg: "var(--primary-foreground)",
  danger: "var(--destructive)",
  chart: ["var(--chart-1)", "var(--chart-2)", "var(--chart-3)", "var(--chart-4)", "var(--chart-5)"],
};
```

## 3. Wrap components

A wrapper receives `props` (what the model wrote, validated), `node` and `ctx`. `<GistChildren />` places the children.

```vue title="GistCard.vue"
<script setup lang="ts">
import { GistChildren, type GistUIComponentProps } from "@gistui/vue";
import { Card, CardContent } from "@/components/ui/card";

defineProps<GistUIComponentProps>();
</script>

<template>
  <Card data-gistui="Card">
    <CardContent class="flex flex-col gap-4 p-6"><GistChildren /></CardContent>
  </Card>
</template>
```

```vue title="GistInput.vue"
<script setup lang="ts">
import { useId } from "vue";
import { useGistField, type GistUIComponentProps } from "@gistui/vue";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";

const p = defineProps<GistUIComponentProps>();
const id = useId();
const field = useGistField(p); // validation, error, bind:$var
</script>

<template>
  <div class="grid gap-2">
    <Label v-if="field.label" :for="id">{{ field.label }}</Label>
    <Input
      :id="id"
      :name="field.name"
      :type="(p.props.type as string) ?? 'text'"
      :placeholder="p.props.placeholder as string"
      :disabled="field.locked"
      :aria-invalid="field.error ? true : undefined"
      :model-value="field.bound ? String(field.value ?? '') : undefined"
      :default-value="field.bound ? undefined : (p.props.value as string)"
      @update:model-value="(v) => field.bound && field.setValue(v)"
    />
    <p v-if="field.error" role="alert" class="text-sm text-destructive">{{ field.error }}</p>
  </div>
</template>
```

## 4. Render with them

```vue
<script setup lang="ts">
import { GistUI } from "@gistui/vue";
import GistCard from "./GistCard.vue";
import GistInput from "./GistInput.vue";
import { tokens } from "./tokens";
</script>

<template>
  <GistUI :source="answer" :streaming="loading" :components="{ Card: GistCard, Input: GistInput }" :tokens="tokens" @action="onAction" />
</template>
```

## Notes

- Keep GistUI's built-in `Button`. With the tokens above it takes your primary colour and radius, and every action, form submit and dialog keeps working.
- For a checkbox or switch, call `useGistField(p, "bool")`.
- Your wrappers see the app's plugins and whatever the components around `<GistUI>` provide.
- shadcn-vue is built on Reka UI: for the primitives directly, see [Reka UI](/docs/ui-libraries/reka-ui/).

Source: https://gistui.com/docs/ui-libraries/shadcn-vue/index.mdx
