feat: enhance chat UI and add location component with images

This commit is contained in:
2025-09-02 18:21:48 +02:00
parent 3fa4f574d3
commit 01bbb6c00a
11 changed files with 49 additions and 24 deletions

View File

@@ -49,16 +49,16 @@ const commandPaletteUi = {
<UModal v-model:open="openMessageModal" :ui="modalUi"> <UModal v-model:open="openMessageModal" :ui="modalUi">
<UButton <UButton
:label="loading ? t('cmd.sending') : t('cmd.send')" :label="loading ? t('cmd.sending') : t('cmd.send')"
variant="solid" variant="outline"
color="neutral" color="neutral"
size="xl" size="xl"
icon="i-ph-paper-plane-tilt-duotone" icon="i-ph-paper-plane-tilt-duotone"
class="rounded-full" class="rounded-full cursor-pointer"
:disabled="loading" :disabled="loading"
> >
<template #trailing> <template #trailing>
<UKbd value="meta" /> <UKbd value="meta" color="neutral" />
<UKbd value="enter" /> <UKbd value="enter" color="neutral" />
</template> </template>
</UButton> </UButton>
@@ -106,7 +106,7 @@ const commandPaletteUi = {
> >
<UButton <UButton
:label="t('clear.button')" :label="t('clear.button')"
variant="solid" variant="subtle"
color="error" color="error"
leading-icon="i-ph-trash-duotone" leading-icon="i-ph-trash-duotone"
size="xl" size="xl"
@@ -114,8 +114,8 @@ const commandPaletteUi = {
:disabled="storeMessages.length === 0" :disabled="storeMessages.length === 0"
> >
<template #trailing> <template #trailing>
<UKbd value="meta" /> <UKbd value="meta" color="error" />
<UKbd value="D" /> <UKbd value="D" color="error" />
</template> </template>
</UButton> </UButton>

View File

@@ -32,7 +32,7 @@ const formatted = computed(() => useDateFormat(useNow(), 'D MMMM YYYY, HH:mm', {
{{ formatted }} {{ formatted }}
</div> </div>
</div> </div>
<div v-else> <div v-else class="group space-y-2">
<div class="flex flex-col-reverse gap-4 items-start md:flex-row-reverse"> <div class="flex flex-col-reverse gap-4 items-start md:flex-row-reverse">
<UCard <UCard
v-if="message.state === ChatState.LOADING && message.fetchStates && message.fetchStates.length > 0" v-if="message.state === ChatState.LOADING && message.fetchStates && message.fetchStates.length > 0"
@@ -69,6 +69,9 @@ const formatted = computed(() => useDateFormat(useNow(), 'D MMMM YYYY, HH:mm', {
<div v-else-if="message.type === ChatType.WEATHER"> <div v-else-if="message.type === ChatType.WEATHER">
<ToolWeather /> <ToolWeather />
</div> </div>
<div v-else-if="message.type === ChatType.LOCATION">
<ToolLocation />
</div>
<div v-else> <div v-else>
{{ message }} {{ message }}
</div> </div>

View File

@@ -93,7 +93,7 @@ const getActivity = computed(() => {
</UTooltip> </UTooltip>
</div> </div>
<ClientOnly> <ClientOnly>
<UCard variant="outline" class="md:max-w-1/2" :ui="{ body: 'flex gap-8 items-center' }"> <UCard v-if="getActivity" variant="outline" class="md:max-w-1/2 m-1 shadow-sm" :ui="{ body: 'flex gap-8 items-center' }">
<UIcon <UIcon
:name="IDEs.find(ide => ide.name === getActivity!.name)!.icon" :name="IDEs.find(ide => ide.name === getActivity!.name)!.icon"
size="64" size="64"
@@ -150,7 +150,7 @@ const getActivity = computed(() => {
{ {
"en": { "en": {
"offline": "I'm currently offline. Come back later to see what I'm working on. {maths}", "offline": "I'm currently offline. Come back later to see what I'm working on. {maths}",
"working": "I'm actually online!", "working": "I'm actually online! Check what I'm working on just below.",
"idling": "I'm idling on my computer with {editor} running in background.", "idling": "I'm idling on my computer with {editor} running in background.",
"maths": "I am probably doing some maths or sleeping.", "maths": "I am probably doing some maths or sleeping.",
"tooltip": { "tooltip": {
@@ -163,7 +163,7 @@ const getActivity = computed(() => {
}, },
"fr": { "fr": {
"offline": "Je suis actuellement hors ligne. Revenez plus tard pour voir sur quoi je travaille. {maths}", "offline": "Je suis actuellement hors ligne. Revenez plus tard pour voir sur quoi je travaille. {maths}",
"working": "Je travaille actuellement en ligne !", "working": "Je suis actuellement en ligne ! Découvrez ce sur quoi je travaille juste en dessous.",
"idling": "Je suis en veille sur mon ordinateur avec {editor} en arrière-plan.", "idling": "Je suis en veille sur mon ordinateur avec {editor} en arrière-plan.",
"maths": "Je suis probablement en train de faire des maths ou en train de dormir.", "maths": "Je suis probablement en train de faire des maths ou en train de dormir.",
"tooltip": { "tooltip": {
@@ -176,7 +176,7 @@ const getActivity = computed(() => {
}, },
"es": { "es": {
"offline": "Ahora mismo estoy desconectado. Vuelve más tarde para ver en lo que estoy trabajando. {maths}", "offline": "Ahora mismo estoy desconectado. Vuelve más tarde para ver en lo que estoy trabajando. {maths}",
"working": "Estoy trabajando en línea.", "working": "Estoy trabajando en línea. ¡Mira lo que estoy haciendo justo debajo!",
"idling": "Estoy en reposo en mi ordenador con {editor} en segundo plano.", "idling": "Estoy en reposo en mi ordenador con {editor} en segundo plano.",
"maths": "Estoy probablemente haciendo matemáticas o durmiendo.", "maths": "Estoy probablemente haciendo matemáticas o durmiendo.",
"tooltip": { "tooltip": {

View File

@@ -19,7 +19,7 @@ const { t } = useI18n({ useScope: 'local' })
variant="subtle" variant="subtle"
color="neutral" color="neutral"
target="_blank" target="_blank"
class="" class="m-1 shadow-sm"
:href="social.to" :href="social.to"
:aria-label="social.label" :aria-label="social.label"
/> />

View File

@@ -35,7 +35,7 @@ defineShortcuts({
</ul> </ul>
</div> </div>
<ClientOnly> <ClientOnly>
<UCard variant="outline" class="md:max-w-1/2" :ui="{ body: 'flex justify-between items-center gap-2' }"> <UCard variant="outline" class="md:max-w-1/2 m-1 shadow-sm" :ui="{ body: 'flex justify-between items-center gap-2' }">
<p class="block"> <p class="block">
{{ t('change') }} {{ t('change') }}
</p> </p>

View File

@@ -1,13 +1,35 @@
<script lang="ts" setup> <script lang="ts" setup>
useI18n({ useScope: 'local' })
</script> </script>
<template> <template>
<div> <section>
<!-- TODO: Implement location component --> <div class="prose dark:prose-invert mb-4">
</div> <i18n-t keypath="location" tag="p">
<template #location>
<strong>Paris, France 🇫🇷</strong>
</template>
</i18n-t>
</div>
<div class="md:max-w-2/3 shadow-lg rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden relative z-10">
<NuxtImg class="rounded-xl" src="/location.png" />
<div class="size-14 rounded-full border-2 border-black absolute z-50 top-2/5 -translate-y-1/2 left-1/5 -translate-x-1/2 animate-bounce">
<NuxtImg src="/arthur pro.webp" class="rounded-full" />
</div>
</div>
</section>
</template> </template>
<style lang="scss"> <i18n lang="json">
{
</style> "en": {
"location": "I'm currently based in {location}. See below for more details."
},
"fr": {
"location": "Je suis actuellement basé à {location}. Voir ci-dessous pour plus de détails."
},
"es": {
"location": "Actualmente estoy basado en {location}. Consulta más detalles a continuación."
}
}
</i18n>

View File

@@ -75,7 +75,7 @@ defineShortcuts({
</ul> </ul>
</div> </div>
<ClientOnly> <ClientOnly>
<UCard variant="outline" class="md:max-w-1/2" :ui="{ body: 'flex justify-between items-center' }"> <UCard variant="outline" class="md:max-w-1/2 m-1 shadow-sm" :ui="{ body: 'flex justify-between items-center' }">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<UIcon v-if="dark" name="i-ph-moon-duotone" size="24" /> <UIcon v-if="dark" name="i-ph-moon-duotone" size="24" />
<UIcon v-else name="i-ph-sun-duotone" size="24" /> <UIcon v-else name="i-ph-sun-duotone" size="24" />

View File

@@ -8,7 +8,7 @@ const { data: weather } = await useAsyncData<Weather>('weather', () =>
</script> </script>
<template> <template>
<UCard v-if="weather" variant="outline" class="md:max-w-2/3"> <UCard v-if="weather" variant="outline" class="md:max-w-2/3 m-1 shadow-sm">
<template #header> <template #header>
<div class="flex gap-4 items-center"> <div class="flex gap-4 items-center">
<UIcon name="i-ph-cloud-duotone" size="24" /> <UIcon name="i-ph-cloud-duotone" size="24" />

View File

@@ -60,7 +60,7 @@ export function useChat(t: any) {
icon: 'i-ph-warning-duotone', icon: 'i-ph-warning-duotone',
prompt: t('chat.status.prompt'), prompt: t('chat.status.prompt'),
type: ChatType.STATUS, type: ChatType.STATUS,
fetchStates: [ChatFetchState.FETCHING, ChatFetchState.GENERATING], fetchStates: [ChatFetchState.FETCHING],
}, },
].sort((a, b) => a.label.localeCompare(b.label)), ].sort((a, b) => a.label.localeCompare(b.label)),
}, },

BIN
public/arthur pro.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

BIN
public/location.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB