forked from yvv/decision
Sous l'article, une version retenue montre « Contre » et le retrait, avec la phrase qui dit pourquoi. Dans le panier, elle se choisit en « contre » ou en retrait ; « Tout pour » la saute et le dit, « Tout contre » la prend ; un « pour » gardé d'avant l'objection quitte le panier (basket.kept). Les phrases qui disaient « ne se vote plus » disent la règle d'Yvv, en fr, en et es. C28 ajusté. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
86 lines
2.3 KiB
Svelte
86 lines
2.3 KiB
Svelte
<script lang="ts">
|
|
// One choice of the basket: for, against, or withdraw one's vote (when there is
|
|
// one). Pressing the chosen one again takes the version out of the basket. A
|
|
// version held back by an objection offers no « for » (Yvv, 2026-11-01).
|
|
import { t } from '$lib/i18n/index.svelte';
|
|
import type { Choice } from '$lib/types';
|
|
|
|
let {
|
|
value,
|
|
voted,
|
|
label,
|
|
held = false,
|
|
disabled = false,
|
|
onpick,
|
|
}: {
|
|
value: Choice | undefined;
|
|
voted: boolean;
|
|
label: string;
|
|
/** Held back by an objection: against or a withdrawal only. */
|
|
held?: boolean;
|
|
disabled?: boolean;
|
|
onpick: (c: Choice) => void;
|
|
} = $props();
|
|
</script>
|
|
|
|
<span class="picker" role="group" aria-label={label}>
|
|
{#if !held}
|
|
<button type="button" class="for" aria-pressed={value === 'for'} {disabled} onclick={() => onpick('for')}>{t('vote.for')}</button>
|
|
{/if}
|
|
<button type="button" class="against" aria-pressed={value === 'against'} {disabled} onclick={() => onpick('against')}>{t('vote.against')}</button>
|
|
{#if voted || value === 'none'}
|
|
<button type="button" class="none" aria-pressed={value === 'none'} {disabled} onclick={() => onpick('none')}>{t('basket.pick.retract')}</button>
|
|
{/if}
|
|
</span>
|
|
|
|
<style>
|
|
.picker {
|
|
display: inline-flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.25rem;
|
|
background: var(--surface-2);
|
|
padding: 3px;
|
|
border-radius: var(--r-pill);
|
|
}
|
|
button {
|
|
border: 0;
|
|
background: transparent;
|
|
border-radius: var(--r-pill);
|
|
padding: 0.3rem 0.75rem;
|
|
min-height: 2.25rem;
|
|
min-width: 2.75rem;
|
|
font-weight: 750;
|
|
font-size: 0.84rem;
|
|
color: var(--ink-soft);
|
|
transition: background-color 0.15s var(--ease), color 0.15s var(--ease);
|
|
}
|
|
button:hover:not(:disabled) {
|
|
color: var(--ink);
|
|
background: var(--surface);
|
|
}
|
|
.for[aria-pressed='true'],
|
|
.for[aria-pressed='true']:hover {
|
|
background: var(--moss);
|
|
color: var(--on-water);
|
|
}
|
|
.against[aria-pressed='true'],
|
|
.against[aria-pressed='true']:hover {
|
|
background: var(--ochre);
|
|
color: var(--on-water);
|
|
}
|
|
.none[aria-pressed='true'],
|
|
.none[aria-pressed='true']:hover {
|
|
background: var(--ink-soft);
|
|
color: var(--surface);
|
|
}
|
|
button:disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
@media (prefers-reduced-motion: reduce) {
|
|
button {
|
|
transition: none;
|
|
}
|
|
}
|
|
</style>
|