Skip to content

Commit ab0c742

Browse files
committed
docs(search): move ai assistant at the top
1 parent d8a313b commit ab0c742

File tree

4 files changed

+86
-45
lines changed

4 files changed

+86
-45
lines changed

docs/app/components/search/Search.vue

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<script setup lang="ts">
2-
import type { UIMessage } from 'ai'
32
import type { ContentNavigationItem } from '@nuxt/content'
43
54
interface ContentSearchFile {
@@ -15,46 +14,11 @@ defineProps<{
1514
navigation?: ContentNavigationItem[]
1615
}>()
1716
18-
const chat = ref(false)
19-
const fullscreen = ref(false)
20-
const searchTerm = ref('')
21-
const messages = ref<UIMessage[]>([])
22-
23-
const { frameworks } = useFrameworks()
24-
const { links } = useSearch()
25-
26-
const groups = computed(() => [{
27-
id: 'ai',
28-
label: 'Assistant',
29-
ignoreFilter: true,
30-
items: [{
31-
label: 'Ask Nuxt AI',
32-
icon: 'i-lucide-bot',
33-
ui: {
34-
itemLeadingIcon: 'group-data-highlighted:not-group-data-disabled:text-primary'
35-
},
36-
onSelect: (e: any) => {
37-
e.preventDefault()
38-
39-
messages.value = searchTerm.value
40-
? [{
41-
id: '1',
42-
role: 'user',
43-
parts: [{ type: 'text', text: searchTerm.value }]
44-
}]
45-
: []
46-
47-
chat.value = true
48-
}
49-
}]
50-
}, {
51-
id: 'framework',
52-
label: 'Framework',
53-
items: frameworks.value
54-
}])
17+
const { links, groups, fullscreen, chat, searchTerm, messages } = useSearch()
5518
5619
function onClose() {
5720
chat.value = false
21+
5822
fullscreen.value = false
5923
}
6024
</script>

docs/app/components/search/SearchChat.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,14 @@ const getCachedToolMessage = useMemoize((state: State, toolName: string, input:
9898
<template>
9999
<UChatPalette>
100100
<UChatMessages
101+
should-auto-scroll
101102
:messages="chat.messages"
102103
:status="chat.status"
103104
:user="{ side: 'left', variant: 'naked', icon: 'i-lucide-user' }"
104105
:assistant="{ icon: 'i-lucide-bot' }"
105106
>
106107
<template #content="{ message }">
107-
<template v-for="(part, index) in message.parts" :key="`${message.id}-${index}`">
108+
<template v-for="(part, index) in message.parts" :key="`${message.id}-${part.type}-${index}${'state' in part ? `-${part.state}` : ''}`">
108109
<MDCCached
109110
v-if="part.type === 'text'"
110111
:value="part.text"

docs/app/composables/useSearch.ts

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,41 @@
1+
import type { UIMessage } from 'ai'
2+
13
export function useSearch() {
24
const route = useRoute()
5+
const { frameworks } = useFrameworks()
6+
7+
const chat = ref(false)
8+
const fullscreen = ref(false)
9+
const searchTerm = ref('')
10+
const messages = ref<UIMessage[]>([])
11+
12+
function onSelect(e: any) {
13+
e.preventDefault()
314

4-
const links = computed(() => [{
15+
messages.value = searchTerm.value
16+
? [{
17+
id: '1',
18+
role: 'user',
19+
parts: [{ type: 'text', text: searchTerm.value }]
20+
}]
21+
: [{
22+
id: '1',
23+
role: 'assistant',
24+
parts: [{ type: 'text', text: 'Hello, how can I help you today?' }]
25+
}]
26+
27+
chat.value = true
28+
}
29+
30+
const links = computed(() => [!searchTerm.value && {
31+
label: 'Ask AI',
32+
description: 'Ask the AI assistant powered by our custom MCP server for help.',
33+
icon: 'i-lucide-bot',
34+
ui: {
35+
itemLeadingIcon: 'group-data-highlighted:not-group-data-disabled:text-primary'
36+
},
37+
onSelect
38+
}, {
539
label: 'Get Started',
640
description: 'Learn how to get started with Nuxt UI.',
741
icon: 'i-lucide-square-play',
@@ -61,9 +95,34 @@ export function useSearch() {
6195
icon: 'i-simple-icons-github',
6296
to: 'https://github.com/nuxt/ui/releases',
6397
target: '_blank'
98+
}].filter(link => !!link))
99+
100+
const groups = computed(() => [{
101+
id: 'ai',
102+
label: 'AI',
103+
ignoreFilter: true,
104+
items: searchTerm.value
105+
? [{
106+
label: `Ask AI for “${searchTerm.value}”`,
107+
icon: 'i-lucide-bot',
108+
ui: {
109+
itemLeadingIcon: 'group-data-highlighted:not-group-data-disabled:text-primary'
110+
},
111+
onSelect
112+
}]
113+
: []
114+
}, {
115+
id: 'framework',
116+
label: 'Framework',
117+
items: frameworks.value
64118
}])
65119

66120
return {
67-
links
121+
links,
122+
groups,
123+
chat,
124+
fullscreen,
125+
searchTerm,
126+
messages
68127
}
69128
}

playgrounds/nuxt/app/pages/chat.vue

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,33 @@ function onSubmit() {
4747
:spacing-offset="48"
4848
>
4949
<template #content="{ message }">
50-
<template v-for="(part, index) in message.parts" :key="`${message.id}-${index}`">
51-
<MDC v-if="part.type === 'text'" :value="part.text" :cache-key="`${message.id}-${index}`" class="*:first:mt-0 *:last:mb-0" />
52-
<p v-else-if="part.type === 'reasoning'" class="text-sm text-muted my-5">
50+
<template
51+
v-for="(part, index) in message.parts"
52+
:key="`${message.id}-${part.type}-${index}${'state' in part ? `-${part.state}` : ''}`"
53+
>
54+
<MDC
55+
v-if="part.type === 'text'"
56+
:value="part.text"
57+
:cache-key="`${message.id}-${index}`"
58+
class="*:first:mt-0 *:last:mb-0"
59+
/>
60+
<p
61+
v-else-if="part.type === 'reasoning'"
62+
class="text-sm text-muted my-5"
63+
>
5364
{{ part.state === 'done' ? 'Thoughts' : 'Thinking...' }}
5465
</p>
5566
</template>
5667
</template>
5768
</UChatMessages>
5869

59-
<UChatPrompt v-model="input" :error="chat.error" variant="subtle" class="sticky bottom-0" @submit="onSubmit">
70+
<UChatPrompt
71+
v-model="input"
72+
:error="chat.error"
73+
variant="subtle"
74+
class="sticky bottom-0"
75+
@submit="onSubmit"
76+
>
6077
<UChatPromptSubmit :status="chat.status" @stop="chat.stop" @reload="chat.regenerate" />
6178
</UChatPrompt>
6279
</div>

0 commit comments

Comments
 (0)