feat(chatbot): composant ChatModeToggle (radiogroup) et état partagé du mode
Toggle sobre 2 options (role radiogroup, flèches/Home/End, focus visible, reduced-motion), étiquette de mode sur les réponses approfondies, et useChatProfondeur (état par clé, desktop et mobile synchronisés). Libellés lus dans utils/chatProfondeur.ts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015vcVGz8i4WpZm2dixKUiSD
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
80f69565aa
commit
4c57f30f6a
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<span v-if="profondeur === 'approfondi'" class="chat-mode-badge">{{ CHAT_PROFONDEUR_LIBELLES.approfondi }}</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Étiquette sobre sur une réponse donnée en mode approfondi (rien en mode rapide).
|
||||
defineProps<{ profondeur?: string }>()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chat-mode-badge {
|
||||
display: inline-block;
|
||||
margin-bottom: 6px;
|
||||
padding: 1px 8px;
|
||||
border-radius: 9999px;
|
||||
border: 1px solid var(--nav-bg-alt);
|
||||
font-size: 0.66rem;
|
||||
font-family: var(--nav-font);
|
||||
color: var(--nav-text-muted);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div class="chat-mode" role="radiogroup" aria-label="Mode de réponse">
|
||||
<button
|
||||
v-for="(p, i) in CHAT_PROFONDEURS"
|
||||
:key="p"
|
||||
:ref="(el) => (boutons[i] = el as HTMLButtonElement | null)"
|
||||
type="button"
|
||||
role="radio"
|
||||
class="chat-mode-option"
|
||||
:class="{ active: modelValue === p }"
|
||||
:aria-checked="modelValue === p"
|
||||
:tabindex="modelValue === p ? 0 : -1"
|
||||
:title="CHAT_PROFONDEUR_AIDES[p]"
|
||||
:disabled="disabled"
|
||||
@click="choisir(p)"
|
||||
@keydown="onKey($event, i)"
|
||||
>{{ CHAT_PROFONDEUR_LIBELLES[p] }}</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Toggle 2 options partagé par les 5 chatbots. Libellés : utils/chatProfondeur.ts.
|
||||
// radiogroup : flèches déplacent la sélection, Tab entre/sort du groupe (roving tabindex).
|
||||
const props = defineProps<{ modelValue: 'rapide' | 'approfondi'; disabled?: boolean }>()
|
||||
const emit = defineEmits<{ 'update:modelValue': [value: 'rapide' | 'approfondi'] }>()
|
||||
|
||||
const boutons = ref<(HTMLButtonElement | null)[]>([])
|
||||
|
||||
function choisir(p: ChatProfondeur) {
|
||||
if (!props.disabled) emit('update:modelValue', p)
|
||||
}
|
||||
|
||||
function onKey(e: KeyboardEvent, i: number) {
|
||||
const n = CHAT_PROFONDEURS.length
|
||||
let j = -1
|
||||
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') j = (i + 1) % n
|
||||
else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') j = (i - 1 + n) % n
|
||||
else if (e.key === 'Home') j = 0
|
||||
else if (e.key === 'End') j = n - 1
|
||||
if (j < 0) return
|
||||
e.preventDefault()
|
||||
choisir(CHAT_PROFONDEURS[j])
|
||||
nextTick(() => boutons.value[j]?.focus())
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chat-mode {
|
||||
display: inline-flex;
|
||||
gap: 2px;
|
||||
padding: 2px;
|
||||
border-radius: 9999px;
|
||||
background: var(--nav-bg-alt);
|
||||
align-self: flex-start;
|
||||
}
|
||||
.chat-mode-option {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--nav-text-muted);
|
||||
font-family: var(--nav-font);
|
||||
font-size: 0.72rem;
|
||||
line-height: 1.2;
|
||||
padding: 4px 10px;
|
||||
border-radius: 9999px;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
.chat-mode-option:hover:not(.active):not(:disabled) { color: var(--nav-text); }
|
||||
.chat-mode-option.active {
|
||||
background: var(--nav-primary);
|
||||
color: var(--nav-text-on-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.chat-mode-option:focus-visible { outline: 2px solid var(--nav-primary); outline-offset: 2px; }
|
||||
.chat-mode-option:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.chat-mode-option { transition: none; }
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user