Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169<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 Logo from "../ui/Logo.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 "/");</script>
{#snippet divider(classes = "")} <div class={["hidden h-6 w-px self-center rounded-md bg-background-inset md:block", classes]} ></div>{/snippet}
<nav class={`h-11 w-full px-5 ${variant === "marketing" ? "" : "border-b border-border-default bg-background-default shadow-[0_1px_1px_0_rgba(0,0,0,0.05)]"} `} aria-label="main"> <div class="flex h-full items-center justify-between gap-4"> <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"> <Logo wordmark alpha class="h-6.5" /> </span> <span class="inline-flex sm:hidden"> <img src="/logos/dolly.svg" alt="tangled" class="size-8" /> </span> </a> </div>
<div class={variant === "marketing" ? "flex items-center gap-3.5" : "flex items-center gap-4"}> {#if variant === "marketing"} <TopbarSearch />
{@render divider()}
<Button variant="ghost" href={resolve("/login")}>Login</Button>
<span class="text-sm text-foreground-muted">or</span>
<Button variant="primary" href={resolve("/signup")} insetShadow={true}> <span>Join now</span> <ArrowRight class="size-3" 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" align="right"> {#snippet trigger()} <Plus class="size-3.5" 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-foreground-default transition-colors hover:text-foreground-muted" aria-label="Notifications" > <Bell class="size-4" aria-hidden="true" /> </a> </div>
<div class="order-3 md:hidden"> <a href={appPath("/search")} class="text-foreground-subtle" aria-label="Search"> <Search class="size-5" aria-hidden="true" /> </a> </div>
{@render divider("md:order-2")} {/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-default bg-background-inset text-foreground-placeholder md:size-5" > <Spinner class="size-4" /> </span> <span class="hidden h-4 w-24 rounded bg-background-inset md:block" aria-hidden="true" ></span> </div> {:else if user} <Dropdown id="profile-menu" group="topbar" align="right"> {#snippet trigger()} {#if user.avatar} <img src={user.avatar} alt={user.handle} class="size-8 rounded-full border border-border-default object-cover md:size-5" /> {:else} <span class="flex size-8 items-center justify-center rounded-full border border-border-default bg-background-inset md:size-5" > <UserRound class="size-5 text-foreground-placeholder 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-background-inset md:size-5"></span> <span class="hidden h-4 w-24 rounded bg-background-inset md:block"></span> </div> {/if} </div> {/if} </div> </div></nav>