forked from yvv/decision
73 lines
1.8 KiB
Svelte
73 lines
1.8 KiB
Svelte
<script lang="ts">
|
|
// The signature of this tool: a proposal rises toward the surface as its
|
|
// « for » votes approach the threshold; reached, it stands full, in moss.
|
|
import { t } from '$lib/i18n/index.svelte';
|
|
import type { Evaluation, Tally } from '$lib/types';
|
|
|
|
let {
|
|
tally,
|
|
evaluation,
|
|
blocked = false,
|
|
size = 'row',
|
|
}: { tally: Tally; evaluation: Evaluation | null; blocked?: boolean; size?: 'mini' | 'row' | 'large' } = $props();
|
|
|
|
const ratio = $derived(
|
|
evaluation && evaluation.required > 0 ? Math.min(1, tally.for / evaluation.required) : 0,
|
|
);
|
|
const pct = $derived(Math.round(ratio * 100));
|
|
</script>
|
|
|
|
<span
|
|
class="level {size}"
|
|
class:reached={evaluation?.reached}
|
|
class:blocked
|
|
role="img"
|
|
aria-label={t('tally.level', { pct })}
|
|
title={t('tally.level', { pct })}
|
|
>
|
|
<span class="water" style:height="{Math.max(pct, tally.for > 0 ? 6 : 0)}%"></span>
|
|
</span>
|
|
|
|
<style>
|
|
.level {
|
|
position: relative;
|
|
display: inline-block;
|
|
flex: none;
|
|
width: 8px;
|
|
height: 2.4rem;
|
|
border-radius: 6px;
|
|
background: var(--surface-2);
|
|
box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.08);
|
|
overflow: hidden;
|
|
}
|
|
/* A section folded: one small bar per article, where the support rises. */
|
|
.level.mini {
|
|
width: 5px;
|
|
height: 1.1rem;
|
|
border-radius: 3px;
|
|
}
|
|
.level.large {
|
|
width: 14px;
|
|
height: 5.5rem;
|
|
border-radius: 8px;
|
|
}
|
|
.water {
|
|
position: absolute;
|
|
inset: auto 0 0 0;
|
|
background: linear-gradient(to top, var(--water), color-mix(in srgb, var(--water) 55%, var(--water-light)));
|
|
transition: height 0.7s var(--ease);
|
|
}
|
|
.reached .water {
|
|
height: 100% !important;
|
|
background: var(--moss);
|
|
}
|
|
.blocked {
|
|
box-shadow: inset 0 0 0 2px var(--ochre);
|
|
}
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.water {
|
|
transition: none;
|
|
}
|
|
}
|
|
</style>
|