Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
Svelte
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156<script lang="ts"> import { resolve } from '$app/paths'; import Button from '../ui/Button.svelte'; import Dropdown from '../ui/Dropdown.svelte'; import DropdownItem from '../ui/DropdownItem.svelte'; import ArrowRight from '$icon/arrow-right'; import Bell from '$icon/bell'; import BookMarked from '$icon/book-marked'; import BookPlus from '$icon/book-plus'; import Cog from '$icon/cog'; import LineSquiggle from '$icon/line-squiggle'; import LogOut from '$icon/log-out'; import Plus from '$icon/plus'; import Search from '$icon/search'; import User from '$icon/user'; import UserRound from '$icon/user-round'; import Spinner from '../ui/Spinner.svelte'; import LogotypeSmall from '../ui/LogotypeSmall.svelte'; import TopbarSearch from './TopbarSearch.svelte';
interface User { handle: string; did: string; avatar?: string; }
interface Props { variant: 'marketing' | 'app'; onSignOut?: () => void | Promise<void>; user: User | null; loading?: boolean; }
let { variant, onSignOut, user, loading = false }: Props = $props();
const appPath = (path: string) => resolve(path as '/'); const navClass = $derived( variant === 'marketing' ? 'mx-auto w-full max-w-screen-xl space-x-4 px-4 py-2 sm:px-6' : 'mx-auto w-full space-x-4 px-6 py-2' );</script>
<nav class={navClass} aria-label="main"> <div class="flex items-center justify-between gap-4 p-0"> <div class="flex shrink-0 items-center gap-2"> <a href={resolve('/')} class="flex shrink-0 items-center gap-2 no-underline hover:no-underline" > <span class="hidden sm:inline-flex"> <LogotypeSmall /> </span> <span class="inline-flex sm:hidden"> <img src="/logos/dolly.svg" alt="tangled" class="size-8" /> </span> </a> </div>
<div class="flex items-center gap-4"> {#if variant === 'marketing'} <a href={appPath('/login')} class="text-fg transition-colors hover:text-fg-muted"> Login </a> <span class="text-fg-subtle">or</span> <Button variant="success" size="sm" href="/signup" class="!py-0"> <span>Join now</span> <ArrowRight class="size-4" aria-hidden="true" /> </Button> {:else} {#if user || loading} <div class="order-3 flex items-center md:order-1"> <TopbarSearch /> </div>
<div class="order-1 flex items-center md:order-3"> <Dropdown id="new-menu" group="topbar" variant="button"> {#snippet trigger()} <Plus class="size-4" aria-hidden="true" /> <span class="hidden md:inline">New</span> {/snippet} <DropdownItem href="/repo/new" icon={BookPlus}>New repository</DropdownItem> <DropdownItem href="/strings/new" icon={LineSquiggle}>New string</DropdownItem> </Dropdown> </div>
<div class="order-2 flex items-center md:order-4"> <a href={appPath('/notifications')} class="flex items-center text-fg-subtle transition-colors hover:text-fg" aria-label="Notifications" > <Bell class="size-5" aria-hidden="true" /> </a> </div>
<div class="order-3 md:hidden"> <a href={appPath('/search')} class="text-fg-subtle" aria-label="Search"> <Search class="size-5" aria-hidden="true" /> </a> </div>
<div class="hidden h-6 w-px self-center bg-border md:order-2 md:block"></div> {/if}
<div class="order-4 flex items-center md:order-5"> {#if loading} <div class="flex items-center gap-1" role="status" aria-label="Signing in"> <span class="flex size-8 items-center justify-center rounded-full border border-border bg-surface-muted text-fg-faint md:size-6" > <Spinner class="size-4" /> </span> <span class="hidden h-4 w-24 rounded bg-surface-muted md:block" aria-hidden="true" ></span> </div> {:else if user} <Dropdown id="profile-menu" group="topbar"> {#snippet trigger()} {#if user.avatar} <img src={user.avatar} alt={user.handle} class="size-8 rounded-full border border-border object-cover md:size-6" /> {:else} <span class="flex size-8 items-center justify-center rounded-full border border-border bg-surface-muted md:size-6" > <UserRound class="size-5 text-fg-faint md:size-4" aria-hidden="true" /> </span> {/if} <span class="hidden max-w-48 truncate md:inline">{user.handle}</span> {/snippet} <DropdownItem href={`/${user.handle}`} icon={User}>Profile</DropdownItem> <DropdownItem href={`/${user.handle}?tab=repos`} icon={BookMarked}> Repositories </DropdownItem> <DropdownItem href={`/${user.handle}?tab=strings`} icon={LineSquiggle}> Strings </DropdownItem> <DropdownItem href="/settings" icon={Cog}>Settings</DropdownItem> <DropdownItem danger icon={LogOut} onclick={onSignOut}>Logout</DropdownItem> </Dropdown> {:else} <div class="flex items-center gap-2" aria-hidden="true"> <span class="size-8 rounded-full bg-surface-muted md:size-6"></span> <span class="hidden h-4 w-24 rounded bg-surface-muted md:block"></span> </div> {/if} </div> {/if} </div> </div></nav>