Api

Components API Reference

Last updated by
Harlan Wilton
in chore: sync.

Overview

Nuxt UI reference implementation components built on useAISearch() composable. Provides drop-in ASK ai and chat interfaces using Nuxt UI primitives.

Requirements:

  • @nuxt/ui installed in your project
  • Components auto-registered when module is installed

AISearchContainer

Drop-in container component providing full ASK ai and chat experience.

Usage

<template>
  <!-- One line, fully featured -->
  <AISearchContainer />
</template>

Features

  • Mode toggle (search/chat)
  • Search mode with results
  • Chat mode with streaming
  • Session persistence
  • Error handling
  • Loading states
  • Responsive design

Props

None - self-contained with internal useAISearch() instance.

Events

None - all interactions handled internally.

Example

<template>
  <div>
    <h1>Documentation Search</h1>
    <AISearchContainer />
  </div>
</template>

ModeToggle

Toggle between search and chat modes.

Props

modelValue

  • Type: 'search' | 'chat'
  • Required: Yes
  • Description: Current mode

Events

update:modelValue

  • Type: (value: 'search' | 'chat') => void
  • Description: Emitted when mode changes

Usage

<script setup lang="ts">
const ai = useAISearch()
</script>

<template>
  <ModeToggle
    :model-value="ai.mode.value"
    @update:model-value="ai.switchMode"
  />
</template>

SearchMode

Search interface component (list mode).

Props

query

  • Type: string
  • Required: Yes
  • Description: Current search query

results

  • Type: SearchResult[]
  • Required: Yes
  • Description: Search results array

loading

  • Type: boolean
  • Required: Yes
  • Description: Loading state

error

  • Type: Error | null
  • Required: Yes
  • Description: Error state

Events

update:query

  • Type: (value: string) => void
  • Description: Emitted when query changes
  • Type: () => void
  • Description: Emitted when search is triggered

Usage

<script setup lang="ts">
const ai = useAISearch({ mode: 'search' })
</script>

<template>
  <SearchMode
    v-model:query="ai.query.value"
    :results="ai.searchResults.value"
    :loading="ai.isLoading.value"
    :error="ai.error.value"
    @search="ai.search"
  />
</template>

ChatMode

Chat interface component (generate mode with streaming).

Props

query

  • Type: string
  • Required: Yes
  • Description: Current input text

messages

  • Type: Message[]
  • Required: Yes
  • Description: Chat messages array

loading

  • Type: boolean
  • Required: Yes
  • Description: Loading/streaming state

error

  • Type: Error | null
  • Required: Yes
  • Description: Error state

Events

update:query

  • Type: (value: string) => void
  • Description: Emitted when query changes

send

  • Type: () => void
  • Description: Emitted when message is sent

copy

  • Type: () => void
  • Description: Emitted when copy all is clicked

export

  • Type: () => void
  • Description: Emitted when export is clicked

abort

  • Type: () => void
  • Description: Emitted when abort/stop is clicked

Usage

<script setup lang="ts">
const ai = useAISearch({ mode: 'chat' })
</script>

<template>
  <ChatMode
    v-model:query="ai.query.value"
    :messages="ai.messages.value"
    :loading="ai.isLoading.value"
    :error="ai.error.value"
    @send="ai.sendMessage"
    @copy="ai.copyAllMessages"
    @export="ai.exportAsMarkdown"
    @abort="ai.abort"
  />
</template>

SessionBanner

Warning banner for ephemeral chat sessions.

Props

None

Events

copy

  • Type: () => void
  • Description: Emitted when copy all is clicked

export

  • Type: () => void
  • Description: Emitted when export is clicked

Usage

<script setup lang="ts">
const ai = useAISearch({ mode: 'chat' })
</script>

<template>
  <SessionBanner
    v-if="ai.messages.value.length"
    @copy="ai.copyAllMessages"
    @export="ai.exportAsMarkdown"
  />
</template>

SearchResults

Results list for search mode.

Props

results

  • Type: SearchResult[]
  • Required: Yes
  • Description: Search results array

Events

None

Usage

<script setup lang="ts">
const ai = useAISearch({ mode: 'search' })
</script>

<template>
  <SearchResults
    v-if="ai.searchResults.value.length"
    :results="ai.searchResults.value"
  />
</template>

ChatMessages

Message list for chat mode.

Props

messages

  • Type: Message[]
  • Required: Yes
  • Description: Chat messages array

isStreaming

  • Type: boolean
  • Required: Yes
  • Description: Whether AI is currently streaming

Events

None

Usage

<script setup lang="ts">
const ai = useAISearch({ mode: 'chat' })
</script>

<template>
  <ChatMessages
    :messages="ai.messages.value"
    :is-streaming="ai.isLoading.value"
  />
</template>

Complete Example

Custom Implementation

<script setup lang="ts">
const ai = useAISearch({ mode: 'search' })
</script>

<template>
  <UContainer class="py-8">
    <div class="space-y-6">
      <!-- Mode Toggle -->
      <div class="flex justify-center">
        <ModeToggle
          :model-value="ai.mode.value"
          @update:model-value="ai.switchMode"
        />
      </div>

      <!-- Search Mode -->
      <SearchMode
        v-if="ai.mode.value === 'search'"
        v-model:query="ai.query.value"
        :results="ai.searchResults.value"
        :loading="ai.isLoading.value"
        :error="ai.error.value"
        @search="ai.search"
      />

      <!-- Chat Mode -->
      <ChatMode
        v-else
        v-model:query="ai.query.value"
        :messages="ai.messages.value"
        :loading="ai.isLoading.value"
        :error="ai.error.value"
        @send="ai.sendMessage"
        @copy="ai.copyAllMessages"
        @export="ai.exportAsMarkdown"
        @abort="ai.abort"
      />
    </div>
  </UContainer>
</template>

Drop-in Component

<template>
  <UContainer class="py-8">
    <h1>Documentation Search</h1>
    <AISearchContainer />
  </UContainer>
</template>

TypeScript Types

All components are fully typed. Import types from composables:

import type {
  Message,
  SearchResult,
  UseAISearchOptions
} from '#ai-search/composables/useAISearch'

Styling & Customization

Components use Nuxt UI primitives and inherit your Nuxt UI theme configuration.

Custom Colors

nuxt.config.ts
export default defineNuxtConfig({
  ui: {
    primary: 'green',
    gray: 'slate'
  }
})

Custom Component UI

<template>
  <UContainer>
    <SearchMode
      v-model:query="query"
      :results="results"
      :loading="loading"
      :error="error"
      @search="search"
      :ui="{
        input: { size: '2xl' },
        button: { color: 'primary' }
      }"
    />
  </UContainer>
</template>

Accessibility

All components follow Nuxt UI accessibility standards:

  • Keyboard navigation (Tab, Enter, Escape)
  • ARIA labels and roles
  • Focus indicators
  • Screen reader support
  • Color contrast (WCAG AA)

Performance

Bundle Size

  • AISearchContainer: ~8KB (gzipped)
  • Individual components: ~2KB each (gzipped)

Runtime Performance

  • Rendering: <16ms (60fps)
  • Mode switch: <1ms
  • Message append: <5ms

Browser Support

Same as Nuxt UI:

  • Chrome/Edge (last 2 versions)
  • Firefox (last 2 versions)
  • Safari (last 2 versions)

Next Steps

Did this page help you?