feat: choice conditions with variables, demo updates, roadmap update

This commit is contained in:
2026-06-09 16:46:06 +08:00
parent beb1e5cfd5
commit bf4b85f727
4 changed files with 155 additions and 59 deletions

View File

@@ -16,6 +16,8 @@ const emit = defineEmits<{
const { t } = useI18n()
const focusIndex = ref(0)
const btnRefs = ref<(HTMLButtonElement | null)[]>([])
const toastText = ref('')
const toastVisible = ref(false)
function timerPercent(): number {
if (props.timerTotal <= 0) return 0
@@ -49,9 +51,19 @@ function onKeydown(e: KeyboardEvent, index: number) {
}
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
emit('choose', index)
handleChoose(index)
}
}
function handleChoose(index: number) {
const choice = props.choices[index]
if (choice?.prompt) {
toastText.value = choice.prompt
toastVisible.value = true
setTimeout(() => { toastVisible.value = false }, 2200)
}
emit('choose', index)
}
</script>
<template>
@@ -70,14 +82,18 @@ function onKeydown(e: KeyboardEvent, index: number) {
v-for="(choice, index) in choices"
:key="index"
:ref="(el: any) => setRef(el, index)"
class="choice-btn"
:class="['choice-btn', { 'has-prompt': !!choice.prompt }]"
tabindex="0"
@click="emit('choose', index)"
@click="handleChoose(index)"
@keydown="onKeydown($event, index)"
>
{{ t(choice.textKey || choice.text) }}
</button>
</div>
<Transition name="toast-fade">
<div class="prompt-toast" v-if="toastVisible">{{ toastText }}</div>
</Transition>
</div>
</template>
@@ -137,6 +153,7 @@ function onKeydown(e: KeyboardEvent, index: number) {
}
.choice-btn {
position: relative;
padding: 14px 24px;
font-size: 16px;
color: #fff;
@@ -144,7 +161,7 @@ function onKeydown(e: KeyboardEvent, index: number) {
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 4px;
cursor: pointer;
transition: background 0.2s, border-color 0.2s;
transition: background 0.2s, border-color 0.2s, box-shadow 0.2s;
outline: none;
}
@@ -158,4 +175,42 @@ function onKeydown(e: KeyboardEvent, index: number) {
border-color: rgba(255, 255, 255, 0.6);
box-shadow: 0 0 8px rgba(255, 255, 255, 0.3);
}
.choice-btn.has-prompt {
border-left: 3px solid #ffc107;
border-color: rgba(255, 193, 7, 0.4);
border-left-color: #ffc107;
}
.choice-btn.has-prompt:hover {
border-color: rgba(255, 193, 7, 0.7);
box-shadow: 0 0 12px rgba(255, 193, 7, 0.25);
}
.choice-btn.has-prompt:focus-visible {
border-color: rgba(255, 193, 7, 0.7);
box-shadow: 0 0 12px rgba(255, 193, 7, 0.3);
}
.prompt-toast {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 14px 32px;
font-size: 18px;
color: #ffc107;
background: rgba(0, 0, 0, 0.85);
border: 1px solid rgba(255, 193, 7, 0.4);
border-radius: 6px;
letter-spacing: 2px;
text-align: center;
white-space: nowrap;
pointer-events: none;
}
.toast-fade-enter-active { transition: opacity 0.3s ease; }
.toast-fade-leave-active { transition: opacity 0.6s ease; }
.toast-fade-enter-from,
.toast-fade-leave-to { opacity: 0; }
</style>