You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
5.8 KiB
161 lines
5.8 KiB
<script lang="ts">
|
|
import { createActiveUix, Uix } from '$active-uix';
|
|
import { page } from '$app/state';
|
|
import '@/uix/eidos/index.css';
|
|
import './layout.css';
|
|
|
|
let { children } = $props();
|
|
|
|
const uix = createActiveUix({
|
|
lang: { schema: {}, defaultLocale: 'es' as const },
|
|
// Enable the SoundChannel. Sema's perceptual signals (press, commit,
|
|
// announce, etc.) play synthesized earcons via Web Audio. Opt-in
|
|
// because audio is a side-effect on the user; we want it on for the
|
|
// docs site so the doctrine is audible, not just visible.
|
|
semantic: { sound: true }
|
|
});
|
|
|
|
type NavItem = {
|
|
slug: string;
|
|
label: string;
|
|
group: 'controls' | 'overlays' | 'media';
|
|
};
|
|
|
|
const components: NavItem[] = [
|
|
{ slug: 'toggle', label: 'Toggle', group: 'controls' },
|
|
{ slug: 'switch', label: 'Switch', group: 'controls' },
|
|
{ slug: 'collapsible', label: 'Collapsible', group: 'controls' },
|
|
{ slug: 'avatar', label: 'Avatar', group: 'media' },
|
|
{ slug: 'dialog', label: 'Dialog', group: 'overlays' },
|
|
{ slug: 'drawer', label: 'Drawer', group: 'overlays' },
|
|
{ slug: 'popover', label: 'Popover', group: 'overlays' },
|
|
{ slug: 'toast', label: 'Toast', group: 'overlays' }
|
|
];
|
|
|
|
const groups: { id: NavItem['group']; heading: string }[] = [
|
|
{ id: 'controls', heading: 'Controls' },
|
|
{ id: 'overlays', heading: 'Overlays' },
|
|
{ id: 'media', heading: 'Media' }
|
|
];
|
|
|
|
const current = $derived(page.url.pathname);
|
|
|
|
// ── Theme ─────────────────────────────────────────────────────────────
|
|
let theme = $state<'light' | 'dark'>('light');
|
|
let soundOn = $state(true);
|
|
|
|
$effect(() => {
|
|
if (typeof document === 'undefined') return;
|
|
document.documentElement.dataset.theme = theme;
|
|
});
|
|
|
|
// Persist across reloads
|
|
$effect(() => {
|
|
if (typeof localStorage === 'undefined') return;
|
|
const stored = localStorage.getItem('uix-theme');
|
|
if (stored === 'dark' || stored === 'light') theme = stored;
|
|
});
|
|
$effect(() => {
|
|
if (typeof localStorage === 'undefined') return;
|
|
localStorage.setItem('uix-theme', theme);
|
|
});
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous" />
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=Geist:wght@300..700&family=Geist+Mono:wght@400..600&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
</svelte:head>
|
|
|
|
<Uix {uix}>
|
|
<header class="topbar">
|
|
<div class="topbar-left">
|
|
<a href="/" class="brand">
|
|
<span class="brand-mark">U</span>
|
|
<span class="brand-name">UIX</span>
|
|
<span class="brand-version">v0.1</span>
|
|
</a>
|
|
<nav class="topbar-nav" aria-label="Primary">
|
|
<a href="/" class:active={current === '/'}>Components</a>
|
|
<a href="/docs" class:active={current.startsWith('/docs')}>Docs</a>
|
|
<a href="/playground" class:active={current.startsWith('/playground')}>Playground</a>
|
|
</nav>
|
|
</div>
|
|
<div class="topbar-right">
|
|
<button
|
|
type="button"
|
|
class="iconbtn"
|
|
title={soundOn ? 'Mute sema sounds' : 'Unmute sema sounds'}
|
|
aria-label={soundOn ? 'Mute sema sounds' : 'Unmute sema sounds'}
|
|
onclick={() => (soundOn = !soundOn)}
|
|
aria-pressed={soundOn}
|
|
>
|
|
{#if soundOn}
|
|
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 5L6 9H2v6h4l5 4V5z"/><path d="M15.5 8.5a5 5 0 010 7"/><path d="M19 5a9 9 0 010 14"/></svg>
|
|
{:else}
|
|
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 5L6 9H2v6h4l5 4V5z"/><line x1="22" y1="9" x2="16" y2="15"/><line x1="16" y1="9" x2="22" y2="15"/></svg>
|
|
{/if}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="iconbtn"
|
|
title="Toggle theme"
|
|
aria-label="Toggle theme"
|
|
onclick={() => (theme = theme === 'light' ? 'dark' : 'light')}
|
|
>
|
|
{#if theme === 'light'}
|
|
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/></svg>
|
|
{:else}
|
|
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>
|
|
{/if}
|
|
</button>
|
|
<a
|
|
class="iconbtn"
|
|
href="https://github.com/"
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
title="GitHub"
|
|
aria-label="GitHub"
|
|
>
|
|
<svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.57.1.78-.25.78-.55v-2.06c-3.2.7-3.87-1.36-3.87-1.36-.52-1.32-1.27-1.67-1.27-1.67-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.18 1.76 1.18 1.02 1.75 2.69 1.24 3.34.95.1-.74.4-1.24.72-1.53-2.55-.29-5.24-1.28-5.24-5.69 0-1.26.45-2.29 1.18-3.1-.12-.29-.51-1.46.11-3.04 0 0 .97-.31 3.18 1.18a11.04 11.04 0 015.79 0c2.21-1.49 3.18-1.18 3.18-1.18.62 1.58.23 2.75.11 3.04.74.81 1.18 1.84 1.18 3.1 0 4.42-2.69 5.4-5.25 5.68.41.36.78 1.06.78 2.14v3.18c0 .31.21.66.79.55C20.21 21.39 23.5 17.07 23.5 12 23.5 5.65 18.35.5 12 .5z"/></svg>
|
|
</a>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="shell">
|
|
<aside class="rail">
|
|
<nav class="nav">
|
|
{#each groups as group}
|
|
{@const items = components.filter((c) => c.group === group.id)}
|
|
<div>
|
|
<div class="nav-group-head">{group.heading}</div>
|
|
<ul>
|
|
{#each items as comp}
|
|
<li>
|
|
<a
|
|
href="/{comp.slug}"
|
|
class:active={current === `/${comp.slug}`}
|
|
>
|
|
{comp.label}
|
|
</a>
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
</div>
|
|
{/each}
|
|
</nav>
|
|
|
|
<footer class="rail-foot">
|
|
soma · morfo · sema · eidos
|
|
</footer>
|
|
</aside>
|
|
|
|
<div class="canvas-wrap">
|
|
{@render children?.()}
|
|
</div>
|
|
</div>
|
|
</Uix>
|