feat: implement ChatCommandPalette with dynamic mode handling; enhance localization for tooltips and post footer; add new project pages and content

This commit is contained in:
2025-09-04 15:06:17 +02:00
parent 334bd93099
commit 83631c378a
16 changed files with 279 additions and 116 deletions

View File

@@ -2,11 +2,13 @@
import type { CommandPaletteItem } from '@nuxt/ui'
import { ChatState } from '~~/types'
defineProps({
active: {
type: Boolean,
default: false,
},
interface Props {
mode?: 'chat' | 'work'
active: boolean
}
withDefaults(defineProps<Props>(), {
mode: 'chat',
})
const searchTerm = ref('')
@@ -54,63 +56,26 @@ const commandPaletteUi = {
content: 'flex-1 overflow-y-auto',
}
function up() {
window.scrollTo({ top: 0, behavior: 'smooth' })
}
function down() {
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' })
}
const toolTipContent = {
align: 'center',
side: 'top',
sideOffset: 0,
}
const router = useRouter()
function goHome() {
clearMessages()
router.push('/')
}
</script>
<template>
<nav
class="fixed z-50 pb-8 duration-700 mx-auto px-8 sm:px-0"
:class="active ? 'bottom-0 left-1/2 -translate-x-1/2' : 'max-w-[40rem] w-full md:bottom-1/5 left-1/2 -translate-x-1/2 bottom-0'"
class="fixed z-50 mb-4 md:pb-8 duration-700 mx-auto px-8 sm:px-0 flex gap-2"
:class="active || mode === 'work' ? 'bottom-0 left-1/2 -translate-x-1/2' : 'max-w-[40rem] w-full md:bottom-1/5 left-1/2 -translate-x-1/2 bottom-0'"
>
<UCard variant="outline" class="rounded-xl shadow-lg w-full" :ui="{ body: 'p-2 sm:p-2 flex gap-2 w-full' }">
<ClientOnly>
<UFieldGroup v-if="active" class="flex items-center justify-center">
<UTooltip
:text="t('palette.tooltip.up')"
arrow
:content="toolTipContent"
:delay-duration="0"
>
<UButton
icon="i-ph-arrow-fat-up-duotone"
color="neutral"
variant="outline"
class="cursor-pointer"
size="xl"
@click.prevent="up"
/>
</UTooltip>
<UTooltip
:text="t('palette.tooltip.down')"
arrow
:content="toolTipContent"
:delay-duration="0"
>
<UButton
icon="i-ph-arrow-fat-down-duotone"
color="neutral"
variant="outline"
class="cursor-pointer"
size="xl"
@click.prevent="down"
/>
</UTooltip>
</UFieldGroup>
</ClientOnly>
<UFieldGroup class="w-full">
<UFieldGroup v-if="mode === 'chat'" class="w-full">
<UModal v-model:open="openMessageModal" :ui="modalUi" title="Hey" description="Hey">
<UTooltip
:text="t('palette.tooltip.send')"
@@ -211,6 +176,40 @@ const toolTipContent = {
</template>
</UModal>
</UFieldGroup>
<UFieldGroup v-else>
<UTooltip
:text="t('palette.tooltip.chat')"
arrow
:content="toolTipContent"
:delay-duration="0"
>
<UButton
:label="t('palette.cmd.chat')"
variant="outline"
color="neutral"
size="xl"
icon="i-ph-house-duotone"
class="rounded-lg cursor-pointer p-2 w-full justify-center"
@click.prevent="goHome"
/>
</UTooltip>
<UTooltip
:text="t('palette.tooltip.canva')"
arrow
:content="toolTipContent"
:delay-duration="0"
>
<UButton
:label="t('palette.cmd.canva')"
variant="outline"
color="neutral"
size="xl"
icon="i-ph-presentation-duotone"
href="/canva"
class="rounded-lg cursor-pointer p-2 w-full justify-center"
/>
</UTooltip>
</UFieldGroup>
<ClientOnly>
<UFieldGroup class="flex items-center justify-center">
<UTooltip

View File

@@ -3,7 +3,7 @@ const { t } = useI18n()
</script>
<template>
<div class="flex flex-col my-16 md:my-32">
<div class="flex flex-col my-8 md:my-32">
<h1
v-motion
:initial="{

View File

@@ -1,23 +1,21 @@
<script lang="ts" setup>
const { t } = useI18n({
useScope: 'local',
})
const { t } = useI18n()
</script>
<template>
<div class="p-8 border bg-white/70 dark:bg-black/70 border-gray-200 dark:border-neutral-700 rounded-md">
<div class="mt-8 p-8 border bg-white/70 dark:bg-black/70 border-gray-200 dark:border-neutral-700 rounded-md">
<NuxtImg
src="/arthur.webp"
src="/arthur pro.webp"
alt="Arthur Danjou"
class="w-24 h-24 rounded-full float-left mr-4 mb-4"
/>
<i18n-t
keypath="thanks"
keypath="post.footer.thanks"
tag="p"
class="text-neutral-600 dark:text-neutral-400 text-justify"
>
<template #linkedin>
<HomeLink
<PostLink
href="https://www.linkedin.com/in/arthurdanjou/"
icon="i-ph-linkedin-logo-duotone"
label="LinkedIn"
@@ -26,7 +24,7 @@ const { t } = useI18n({
/>
</template>
<template #github>
<HomeLink
<PostLink
href="https://github.com/arthurdanjou"
icon="i-ph-github-logo-duotone"
label="GitHub"
@@ -35,10 +33,10 @@ const { t } = useI18n({
/>
</template>
<template #comment>
<strong class="text-neutral-800 dark:text-neutral-200">{{ t('comment') }}</strong>
<strong class="text-neutral-800 dark:text-neutral-200">{{ t('post.footer.comment') }}</strong>
</template>
<template #name>
<strong class="text-neutral-800 dark:text-neutral-200">{{ t('name') }}</strong>
<strong class="text-neutral-800 dark:text-neutral-200">Arthur</strong>
</template>
<template #jump>
<br> <br>
@@ -46,23 +44,3 @@ const { t } = useI18n({
</i18n-t>
</div>
</template>
<i18n lang="json">
{
"en": {
"thanks": "Thanks for reading! My name is {name}, and I love writing about AI, data science, and the intersection between mathematics and programming. {jump} I've been coding and exploring math for years, and I'm always learning something new—whether it's self-hosting tools in my homelab, experimenting with machine learning models, or diving into statistical methods. {jump} I share my knowledge here because I know how valuable clear, hands-on resources can be, especially when you're just getting started or exploring something deeply technical. {jump} If you have any questions or just want to chat, feel free to reach out to me on {linkedin} or {github }. {jump} I hope you enjoyed this post and learned something useful. If you did, {comment}—it really helps and means a lot!",
"comment": "consider sharing it",
"name": "Arthur"
},
"es": {
"thanks": "¡Gracias por leer! Me llamo {name} y me encanta escribir sobre inteligencia artificial, ciencia de datos y todo lo que se encuentra en la intersección entre las matemáticas y la programación. {jump} Llevo años programando y explorando las matemáticas, y cada día aprendo algo nuevo — ya sea autoalojando herramientas en mi homelab, experimentando con modelos de aprendizaje automático o profundizando en métodos estadísticos. {jump} Comparto mis conocimientos aquí porque sé lo valiosos que pueden ser los recursos claros, prácticos y accesibles, especialmente cuando uno está empezando o explorando temas técnicos en profundidad. {jump} Si tienes alguna pregunta o simplemente quieres charlar, no dudes en dejar un comentario abajo o contactarme por {linkedin} o {github}. {jump} Espero que este artículo te haya gustado y que hayas aprendido algo útil. Si es así, {comment} — ¡me ayuda mucho y significa mucho para mí!",
"comment": "considera compartirlo",
"name": "Arthur"
},
"fr": {
"thanks": "Merci de votre lecture ! Je m'appelle {name}, et j'adore écrire sur l'intelligence artificielle, la data science, et tout ce qui se situe à l'intersection entre les mathématiques et la programmation. {jump} Je code et j'explore les maths depuis des années, et j'apprends encore de nouvelles choses chaque jour — que ce soit en auto-hébergeant des outils dans mon homelab, en expérimentant des modèles de machine learning ou en approfondissant des méthodes statistiques. {jump} Je partage mes connaissances ici parce que je sais à quel point des ressources claires, pratiques et accessibles peuvent être précieuses, surtout quand on débute ou qu'on explore un sujet technique en profondeur. {jump} Si vous avez des questions ou simplement envie d'échanger, n'hésitez pas à laisser un commentaire ci-dessous ou à me contacter sur {linkedin} ou {github}. {jump} J'espère que cet article vous a plu et qu'il vous a appris quelque chose d'utile. Si c'est le cas, {comment} — ça m'aide beaucoup et ça me fait vraiment plaisir !",
"comment": "pensez à le partager",
"name": "Arthur"
}
}
</i18n>

View File

@@ -0,0 +1,38 @@
<script setup lang="ts">
defineProps({
label: {
type: String,
required: true,
},
href: {
type: String,
required: true,
},
icon: {
type: String,
},
blanked: {
type: Boolean,
default: false,
},
})
</script>
<template>
<NuxtLink
:href="href"
:target="blanked ? '_blank' : '_self'"
class="sofia flex gap-1 items-center group"
>
<Icon
v-if="icon"
:name="icon"
size="20"
/>
<span
class="duration-300 underline-offset-2 font-semibold text-md text-black dark:text-white underline decoration-gray-300 dark:decoration-neutral-700 group-hover:decoration-black dark:group-hover:decoration-white"
>
{{ label }}
</span>
</NuxtLink>
</template>

View File

@@ -10,7 +10,7 @@
<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-12 rounded-full border-2 border-sky-500 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" />
<NuxtImg src="/arthur pro.webp" class="rounded-full" alt="Location of Arthur" />
</div>
</div>
</section>