johnandersen777.bsky.social/knotless
git that lives in your Atmosphere account
Forked from chadtmiller.com/knotless
0
0
<script lang="ts" module>
import type { IconName } from '#lib/icons.ts';
/** One section of settings, as the side lists it: a page, or with `pages`, a group of them, as GitHub's are, the first the section's own. */
export type SettingsSection = {
href: string;
label: string;
icon: IconName;
pages?: { href: string; label: string }[];
};
</script>
<script lang="ts">
import type { Snippet } from 'svelte';
import Meta from '#lib/atoms/Meta.svelte';
import Icon from '#lib/atoms/Icon.svelte';
import { scrollRow } from '#lib/rows.ts';
/**
* Settings, as GitHub lays them out: what they are of, `heading`, over
* the `sections` down the side, the page at `current` marked, a group's
* pages under it, open while one of them is, and beside
* them that section's page, called `title`, which moving between them
* leaves where it was scrolled.
*/
let {
heading,
title,
sections,
current,
children
}: {
heading: Snippet;
title: string;
sections: SettingsSection[];
current: string;
children: Snippet;
} = $props();
</script>
<Meta {title} />
<div class="settings-page">
<div class="settings-head">{@render heading()}</div>
<nav
class="account-nav"
aria-label="Settings"
data-sveltekit-reset="false"
{@attach scrollRow(current)}
>
{#each sections as s (s.href)}
{@const within = !!s.pages?.some((p) => p.href === current)}
{#if s.pages}
<!-- On a phone, where the sections are a row, a group is its first page's tab. -->
<a class="account-group-tab" href={s.href} aria-current={within ? 'page' : undefined}
><Icon name={s.icon} />{s.label}</a
>
<details class="account-group" open={within}>
<summary
><Icon name={s.icon} />{s.label}<span class="account-group-mark"
><Icon name="chevron" /></span
></summary
>
{#each s.pages as p (p.href)}<a
href={p.href}
aria-current={p.href === current ? 'page' : undefined}>{p.label}</a
>{/each}
</details>
{:else}
<a href={s.href} aria-current={s.href === current ? 'page' : undefined}
><Icon name={s.icon} />{s.label}</a
>
{/if}
{/each}
</nav>
<div class="settings-main">{@render children()}</div>
</div>