@dropby/vue

Vue bindings for DropBy: a provider, composables and components for chat, ideas and asks.
477
Install
npm install @dropby/vue
Latest Version:0.5.0
Vue:3
License:MIT
Last Updated:Sep 29, 2026
Links: npm
Maintainer: pras-simpllyf

@dropby/vue

DropBy for Vue 3: a provider, composables for support chat, ideas, pending asks and feature flags, and optional unstyled components. It supports Vue 3.4 and later 3.x releases.

Installation

pnpm add @dropby/vue @dropby/browser

@dropby/browser holds the options and data types, and its README explains sessions, context and flags in full. Keep the two packages on the same version; every release publishes them together.

Provider and composables

With options, DropByProvider creates the DropBy instance, starts it once mounted, and destroys it with its scope. Your auth callback calls your own backend, which knows who is signed in and creates the session; see @dropby/server.

<script setup lang="ts">
import { onMounted, ref } from "vue";
import type { DropByOptions } from "@dropby/browser";
import { DropByProvider } from "@dropby/vue";
import Inbox from "./Inbox.vue";

const options: DropByOptions = {
  publicKey: "YOUR_PUBLIC_KEY",
  auth: async ({ refresh }) => {
    const response = await fetch("/api/dropby/session", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ refresh }),
    });
    if (!response.ok) throw new Error("could not create a DropBy session");
    return response.json();
  },
};

const mounted = ref(false);
onMounted(() => {
  mounted.value = true;
});
</script>

<template>
  <DropByProvider v-if="mounted" :options="options">
    <Inbox />
  </DropByProvider>
</template>

Inbox.vue lists the unread conversations. useChatThread(id) and useFeatureFlag(name) also take a ref or a getter, and follow it when it changes.

<script setup lang="ts">
import { onMounted } from "vue";
import { useChatThreads } from "@dropby/vue";

const { data, actions } = useChatThreads();
onMounted(() => void actions.listThreads({ filter: "unread" }));
</script>

<template>
  <p>{{ data.items.length }} unread threads</p>
</template>
  • useChatThreads, useChatThread(id), useChatUnread, useIdeas and usePendingAsks return data as a read-only ref and a stable actions object.
  • useDropBy() returns the instance. useDropByState() returns its live bootstrap, capabilities and connection refs.
  • An instance passed as the provider's dropby prop stays yours to start and destroy.
  • The v-if above mounts DropBy only in the browser. Never share an instance across server requests.
  • The provider reads options once. When a user logs out, or another user or account signs in, mount a new provider (give it a :key of the user's and account's ids) so the old instance is destroyed.
  • Use the full pk_live_... or pk_test_... value from the dashboard's API keys page for YOUR_PUBLIC_KEY.

Feature flags

useFeatureFlag(name) returns one flag's value as a ref, and useFeatureConfig() all of them. <Feature> renders its default slot when a flag is on (truthy, or equal to equals), and its fallback slot otherwise. Before the instance starts, and for a flag that does not exist, the value is undefined. How flags are resolved, and when they change, is in the @dropby/browser README.

<script setup lang="ts">
import { useFeatureFlag } from "@dropby/vue";
import { Feature } from "@dropby/vue/components";

const format = useFeatureFlag("export_format");
</script>

<template>
  <Feature name="new_exports">
    <button type="button">export as {{ format === "csv" ? "csv" : "pdf" }}</button>
    <template #fallback><span>exports are coming soon</span></template>
  </Feature>
</template>

Components and styling

Optional components live in @dropby/vue/components: ChatThread, ChatThreadList, ChatComposer, IdeaList, Idea, IdeaVoteButton, Ask, AskForm, PendingAsks and Feature. They render plain, accessible HTML with state attributes such as data-status, data-unread and data-busy, so your own CSS styles them; they load no theme. Each, except Feature, also takes a default scoped slot when you want your own markup with its state, and the slot props are typed:

<script setup lang="ts">
import { ChatThreadList } from "@dropby/vue/components";

const emit = defineEmits<{ open: [threadId: `thr_${string}`] }>();
</script>

<template>
  <ChatThreadList v-slot="{ threads }">
    <button
      v-for="thread in threads.items"
      :key="thread.threadId"
      type="button"
      @click="emit('open', thread.threadId)"
    >
      {{ thread.lastMessagePreview }}
    </button>
    <p v-if="threads.status === 'error'">couldn't load your conversations.</p>
  </ChatThreadList>
</template>

The default chat components behave like the hosted widget:

  • ChatThread marks a reply seen once its end is on screen (the page visible, the viewer allowed). Pass :acknowledge="false" to do that yourself with actions.markSeen. A slot body is never observed.
  • ChatThread follows new messages inside its own scroll container: to the newest when it opens, when the reader sends, and when a message arrives while they are at the end. It scrolls only its own scroll container (itself or the nearest ancestor with overflow-y: auto), never the document.
  • ChatThreadList rows become buttons with @select="(threadId) => ..."; selected-id marks the open one with aria-current.
  • Failed loads, sends and downloads show as role="alert" messages in plain words. A slot's state carries the DropByError behind a failed load or send.
  • ChatComposer keeps a failed message in the box. Sending it again unchanged cannot post it twice.

Optional attachments

Import useChatAttachments only when the composer needs uploads, so other pages never load the upload code:

<script setup lang="ts">
import { ChatComposer } from "@dropby/vue/components";
import { useChatAttachments } from "@dropby/vue/components/chat-attachments";

defineProps<{ threadId: `thr_${string}` }>();
const attachments = useChatAttachments();
</script>

<template>
  <ChatComposer :thread-id="threadId" :attachments="attachments" />
</template>

The composable returns drafts, add, remove, clear, references, pending, notice and accept. ChatComposer waits for uploads in progress and sends only the ready ones. Disposing the component's scope releases the composable's previews and subscriptions; destroying the instance cancels its uploads.

Related Packages

@mtchat/vue

MultitenancyChat Vue.js SDK - embeddable chat component

15,338 0
a2a-ai-chat-sdk

AI聊天SDK - 完整的原版功能

8,009
xxai-agent

AI Agent JS SDK

2,483 0
wildfire-im-sdk

野火IM SDK for Vue3 projects

2,237
@buni.ai/chatbot-vue

Vue 3 composables for BuniAI chat widget

4,699

Version History

Version Released Vue License
0.5.0 ^3.4 MIT
0.4.1 ^3.4 MIT
0.4.0 ^3.4 MIT