~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
62 lines · 2.2 KB Raw History
<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>