CopilotThreadsDrawer

Vue 3 threads drawer that lists and manages conversations next to CopilotChat

Open your coding agent in your project's folder, or in an empty folder for a new app.This runs in a coding agent on your computer.

Overview

CopilotThreadsDrawer renders the prebuilt conversation drawer beside CopilotChat. It is a thin Vue wrapper around the framework-agnostic <copilotkit-threads-drawer> custom element and stays SSR-safe by loading that element only on mount. The drawer reads from useThreads, follows the surrounding chat configuration when one is present, and lets the user switch, start, archive, unarchive, delete, and filter threads.

When onThreadSelect and onNewThread are omitted, the wrapper drives the surrounding chat configuration directly: selecting a row calls setActiveThreadId(threadId, { explicit: true }), and the "New Conversation" action resets the chat with startNewThread(). Provide those callbacks only if you want to control the active thread yourself.

Thread rename is not exposed in the drawer row menu. Use useThreads for headless rename support.

The threads drawer requires a license. When it is not licensed, the component renders the locked state and keeps the thread store disabled. Visit copilotkit.ai/pricing for details.

Import

<script setup lang="ts">
import { CopilotThreadsDrawer } from "@copilotkit/vue/v2";
import "@copilotkit/vue/styles.css";
</script>

Props

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Events

The Vue wrapper emits the following events.

EventPayloadFired when
collapse-changecollapsed: booleanThe desktop collapse state changes

Slots

Vue uses named slots in place of React render props. CopilotThreadsDrawer only defines one scoped Vue slot; everything else is projected into the underlying custom element with a slot attribute.

Prop

Type

Light-DOM children with these slot names are projected into the drawer:

SlotReplaces
headerThe drawer header region
emptyThe empty-state body
footerA footer region
memoriesThe reserved memories surface
launcher-iconThe icon inside the mobile launcher
licensedThe licensed upsell content

Style the shadow DOM with ::part(). The drawer exposes the usual structural and action parts, including the root, header, list, row, menu, new-thread button, section heading, filter controls, collapse controls, launcher, load-more, fetch-more-error, and licensed surfaces.

Usage

Basic usage

Wrap the drawer and CopilotChat in a shared CopilotChatConfigurationProvider so they operate on the same active thread. This example includes the surrounding CopilotKitProvider, so it is runnable as shown.

<script setup lang="ts">
import {
  CopilotChat,
  CopilotChatConfigurationProvider,
  CopilotKitProvider,
  CopilotThreadsDrawer,
} from "@copilotkit/vue/v2";
import "@copilotkit/vue/styles.css";
</script>

<template>
  <CopilotKitProvider runtime-url="http://localhost:8200/api/copilotkit">
    <CopilotChatConfigurationProvider agent-id="support">
      <div class="flex h-full">
        <CopilotThreadsDrawer agent-id="support" />
        <CopilotChat agent-id="support" />
      </div>
    </CopilotChatConfigurationProvider>
  </CopilotKitProvider>
</template>

Custom row and projected chrome

<script setup lang="ts">
import { CopilotThreadsDrawer } from "@copilotkit/vue/v2";
</script>

<template>
  <CopilotThreadsDrawer label="History">
    <span slot="header">My conversations</span>
    <span slot="empty">No threads yet.</span>

    <template #row="{ thread }">
      <strong>{{ thread.name ?? "New conversation" }}</strong>
    </template>
  </CopilotThreadsDrawer>
</template>

Observing collapse state

<script setup lang="ts">
import { CopilotThreadsDrawer } from "@copilotkit/vue/v2";

function onCollapseChange(collapsed: boolean) {
  console.log("drawer collapsed:", collapsed);
}
</script>

<template>
  <CopilotThreadsDrawer @collapse-change="onCollapseChange" />
</template>

Behavior

  • The drawer registers itself with the surrounding chat configuration so the mobile launcher can appear.
  • When callbacks are omitted, selecting a row calls setActiveThreadId and "New Conversation" calls startNewThread.
  • Archive, unarchive, delete, and pagination all flow through useThreads.
  • The drawer stays inert while unlicensed, which keeps the thread store from fetching until licensing resolves.
  • Rename is headless only; use useThreads().renameThread() if you need that action.
  • The wrapper is SSR-safe because the custom element is imported lazily on the client.

Related