feat: choice conditions with variables, demo updates, roadmap update
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user