johnandersen777.bsky.social/knotless
git that lives in your Atmosphere account
Forked from chadtmiller.com/knotless
0
0
<script lang="ts">
import type { LanguageView } from '#lib/lexicons/dev/knotless/defs.ts';
/**
* What a directory is written in, as a coloured edge along the top of the
* panel it heads: a segment for each language's share of its bytes, which,
* hovered or tabbed to, names it and its share in a tip under it. Clicked
* or tapped, the edge opens to every language with its share, as a phone
* has no hover; a second tap, Escape or a tap elsewhere closes it.
*/
let { languages }: { languages: LanguageView[] } = $props();
const share = (l: LanguageView) => `${(l.permille / 10).toFixed(1)}%`;
const total = $derived(languages.reduce((n, l) => n + l.bytes, 0) || 1);
/** Where each segment's middle falls along the edge, from 0 to 1, so a tip near an end opens inward rather than past the page. */
const middles = $derived.by(() => {
let at = 0;
return languages.map((l) => {
const mid = (at + l.bytes / 2) / total;
at += l.bytes;
return mid;
});
});
const side = (mid: number) => (mid < 0.15 ? 'start' : mid > 0.85 ? 'end' : '');
let open = $state(false);
function outside(e: MouseEvent) {
if (open && !(e.target as Element).closest('.lang-wrap')) open = false;
}
</script>
<svelte:window onclick={outside} onkeydown={(e) => e.key === 'Escape' && (open = false)} />
<div class="lang-wrap" class:open>
<div class="lang-edge" role="group" aria-label="Languages">
{#each languages as l, i (l.name)}
<button
type="button"
class="seg {side(middles[i])}"
aria-label="{l.name} {share(l)}"
aria-expanded={open}
aria-controls="lang-key"
onclick={() => (open = !open)}
style="flex-grow:{l.bytes};--seg:{l.color}"
><span class="lang-tip" aria-hidden="true"
><i></i><b>{l.name}</b><span class="mute">{share(l)}</span></span
></button
>
{/each}
</div>
{#if open}
<button type="button" class="lang-scrim" aria-label="Close" onclick={() => (open = false)}
></button>
<div class="lang-key" id="lang-key">
<div class="menu-head">Languages</div>
<ul>
{#each languages as l (l.name)}
<li style="--seg:{l.color}">
<i></i><b>{l.name}</b><span class="mute">{share(l)}</span>
</li>
{/each}
</ul>
</div>
{/if}
</div>