parent
a2f1cf8316
commit
58e7bb85a0
@ -0,0 +1,190 @@ |
|||||||
|
<!-- |
||||||
|
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||||
|
// All rights reserved. |
||||||
|
// Licensed under the Apache License, Version 2.0 |
||||||
|
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0> |
||||||
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>, |
||||||
|
// at your option. All files in the project carrying such |
||||||
|
// notice may not be copied, modified, or distributed except |
||||||
|
// according to those terms. |
||||||
|
--> |
||||||
|
|
||||||
|
<script lang="ts"> |
||||||
|
import { |
||||||
|
Sidebar, |
||||||
|
SidebarGroup, |
||||||
|
SidebarItem, |
||||||
|
SidebarWrapper, |
||||||
|
} from "flowbite-svelte"; |
||||||
|
import { link, location } from "svelte-spa-router"; |
||||||
|
import MobileBottomBarItem from "./MobileBottomBarItem.svelte"; |
||||||
|
import MobileBottomBar from "./MobileBottomBar.svelte"; |
||||||
|
// @ts-ignore |
||||||
|
import Logo from "../assets/nextgraph.svg?component"; |
||||||
|
// @ts-ignore |
||||||
|
import LogoGray from "../assets/nextgraph-gray.svg?component"; |
||||||
|
import { online } from "../store"; |
||||||
|
|
||||||
|
import { onMount, tick } from "svelte"; |
||||||
|
|
||||||
|
import { |
||||||
|
Home, |
||||||
|
Bolt, |
||||||
|
MagnifyingGlass, |
||||||
|
PlusCircle, |
||||||
|
PaperAirplane, |
||||||
|
Bell, |
||||||
|
User, |
||||||
|
} from "svelte-heros-v2"; |
||||||
|
|
||||||
|
let width: number; |
||||||
|
let breakPoint: number = 662; |
||||||
|
let mobile = false; |
||||||
|
|
||||||
|
$: if (width >= breakPoint) { |
||||||
|
mobile = false; |
||||||
|
} else { |
||||||
|
mobile = true; |
||||||
|
} |
||||||
|
|
||||||
|
async function scrollToTop() { |
||||||
|
await tick(); |
||||||
|
console.log("scrollToTop"); |
||||||
|
top.scrollIntoView(); |
||||||
|
} |
||||||
|
onMount(async () => await scrollToTop()); |
||||||
|
|
||||||
|
$: activeUrl = "#" + $location; |
||||||
|
|
||||||
|
let top; |
||||||
|
|
||||||
|
let asideClass = "w-48"; |
||||||
|
let spanClass = "flex-1 ml-3 whitespace-nowrap"; |
||||||
|
let nonActiveClass = |
||||||
|
"flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white hover:bg-gray-200 dark:hover:bg-gray-700"; |
||||||
|
</script> |
||||||
|
|
||||||
|
{#if mobile} |
||||||
|
<div class="full-layout"> |
||||||
|
<main class="pb-14" bind:this={top}> |
||||||
|
<slot /> |
||||||
|
</main> |
||||||
|
<MobileBottomBar {activeUrl}> |
||||||
|
<MobileBottomBarItem href="#/" icon={Home} on:click={scrollToTop} /> |
||||||
|
<MobileBottomBarItem href="#/stream" icon={Bolt} on:click={scrollToTop} /> |
||||||
|
<MobileBottomBarItem |
||||||
|
href="#/search" |
||||||
|
icon={MagnifyingGlass} |
||||||
|
on:click={scrollToTop} |
||||||
|
/> |
||||||
|
<MobileBottomBarItem href="#/create" icon={PlusCircle} /> |
||||||
|
<MobileBottomBarItem href="#/site" icon={User} on:click={scrollToTop} /> |
||||||
|
</MobileBottomBar> |
||||||
|
</div> |
||||||
|
{:else} |
||||||
|
<div class="full-layout"> |
||||||
|
<Sidebar {activeUrl} {asideClass} {nonActiveClass} class="fixed"> |
||||||
|
<SidebarWrapper |
||||||
|
divClass="bg-gray-60 overflow-y-auto tall:py-4 px-3 rounded dark:bg-gray-800" |
||||||
|
> |
||||||
|
<SidebarGroup ulClass="space-y-1 tall:space-y-2"> |
||||||
|
<SidebarItem label="NextGraph" href="#/user" class="mt-1"> |
||||||
|
<svelte:fragment slot="icon"> |
||||||
|
{#if $online} |
||||||
|
<Logo class="w-7 h-7 tall:w-10 tall:h-10" /> |
||||||
|
{:else} |
||||||
|
<LogoGray class="w-7 h-7 tall:w-10 tall:h-10" /> |
||||||
|
{/if} |
||||||
|
</svelte:fragment> |
||||||
|
</SidebarItem> |
||||||
|
<SidebarItem |
||||||
|
label="Home" |
||||||
|
href="#/" |
||||||
|
on:click={scrollToTop} |
||||||
|
class="py-1 tall:p-2" |
||||||
|
> |
||||||
|
<svelte:fragment slot="icon"> |
||||||
|
<Home |
||||||
|
tabindex="-1" |
||||||
|
class="w-7 h-7 text-black transition duration-75 dark:text-white group-hover:text-gray-900 dark:group-hover:text-white" |
||||||
|
/> |
||||||
|
</svelte:fragment> |
||||||
|
</SidebarItem> |
||||||
|
<SidebarItem label="Stream" href="#/stream" class="py-1 tall:p-2"> |
||||||
|
<svelte:fragment slot="icon"> |
||||||
|
<Bolt |
||||||
|
tabindex="-1" |
||||||
|
class="w-7 h-7 text-black transition duration-75 dark:text-white group-hover:text-gray-900 dark:group-hover:text-white" |
||||||
|
/> |
||||||
|
</svelte:fragment> |
||||||
|
</SidebarItem> |
||||||
|
<SidebarItem label="Search" href="#/search" class="py-1 tall:p-2"> |
||||||
|
<svelte:fragment slot="icon"> |
||||||
|
<MagnifyingGlass |
||||||
|
tabindex="-1" |
||||||
|
class="w-7 h-7 text-black transition duration-75 dark:text-white group-hover:text-gray-900 dark:group-hover:text-white" |
||||||
|
/> |
||||||
|
</svelte:fragment> |
||||||
|
</SidebarItem> |
||||||
|
<SidebarItem label="Create" href="#/create" class="py-1 tall:p-2"> |
||||||
|
<svelte:fragment slot="icon"> |
||||||
|
<PlusCircle |
||||||
|
tabindex="-1" |
||||||
|
class="w-7 h-7 text-black transition duration-75 dark:text-white group-hover:text-gray-900 dark:group-hover:text-white" |
||||||
|
/> |
||||||
|
</svelte:fragment> |
||||||
|
</SidebarItem> |
||||||
|
<SidebarItem label="Site" href="#/site" class="py-1 tall:p-2"> |
||||||
|
<svelte:fragment slot="icon"> |
||||||
|
<User |
||||||
|
tabindex="-1" |
||||||
|
class="w-7 h-7 text-black transition duration-75 dark:text-white group-hover:text-gray-900 dark:group-hover:text-white" |
||||||
|
/> |
||||||
|
</svelte:fragment> |
||||||
|
</SidebarItem> |
||||||
|
<SidebarItem label="Messages" href="#/messages" class="py-1 tall:p-2"> |
||||||
|
<svelte:fragment slot="icon"> |
||||||
|
<PaperAirplane |
||||||
|
tabindex="-1" |
||||||
|
class="-rotate-45 w-7 h-7 text-black transition duration-75 dark:text-white group-hover:text-gray-900 dark:group-hover:text-white" |
||||||
|
/> |
||||||
|
<span |
||||||
|
class="inline-flex justify-center items-center p-3 mt-1 -ml-3 w-3 h-3 text-sm font-medium text-primary-600 bg-primary-200 rounded-full dark:bg-primary-900 dark:text-primary-200" |
||||||
|
> |
||||||
|
3 |
||||||
|
</span> |
||||||
|
</svelte:fragment> |
||||||
|
</SidebarItem> |
||||||
|
<SidebarItem |
||||||
|
label="Notifications" |
||||||
|
href="#/notifications" |
||||||
|
class="mt-1 py-1 tall:p-2" |
||||||
|
> |
||||||
|
<svelte:fragment slot="icon"> |
||||||
|
<Bell |
||||||
|
tabindex="-1" |
||||||
|
class="w-7 h-7 text-black transition duration-75 dark:text-white group-hover:text-gray-900 dark:group-hover:text-white" |
||||||
|
/> |
||||||
|
<span |
||||||
|
class="inline-flex justify-center items-center p-3 mt-1 -ml-3 w-3 h-3 text-sm font-medium text-primary-600 bg-primary-200 rounded-full dark:bg-primary-900 dark:text-primary-200" |
||||||
|
> |
||||||
|
10 |
||||||
|
</span> |
||||||
|
</svelte:fragment> |
||||||
|
</SidebarItem> |
||||||
|
</SidebarGroup> |
||||||
|
</SidebarWrapper> |
||||||
|
</Sidebar> |
||||||
|
|
||||||
|
<main class="ml-48" bind:this={top}> |
||||||
|
<slot /> |
||||||
|
</main> |
||||||
|
</div> |
||||||
|
{/if} |
||||||
|
<svelte:window bind:innerWidth={width} /> |
||||||
|
|
||||||
|
<style> |
||||||
|
.full-layout { |
||||||
|
height: 100vh; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,23 @@ |
|||||||
|
<script lang="ts"> |
||||||
|
import { setContext } from "svelte"; |
||||||
|
import { writable } from "svelte/store"; |
||||||
|
|
||||||
|
export let activeUrl: string = ""; |
||||||
|
|
||||||
|
const activeUrlStore = writable(""); |
||||||
|
|
||||||
|
$: { |
||||||
|
activeUrlStore.set(activeUrl); |
||||||
|
} |
||||||
|
setContext("activeUrl", activeUrlStore); |
||||||
|
</script> |
||||||
|
|
||||||
|
<nav |
||||||
|
class="border-t border-solid border-gray-200 bg-white dark:bg-gray-900 text-gray-700 dark:text-gray-200 dark:border-gray-700 divide-gray-100 dark:divide-gray-700 px-2 sm:px-4 py-2.5 w-full fixed bottom-0 left-0 z-20" |
||||||
|
> |
||||||
|
<div |
||||||
|
class="mx-auto flex flex-wrap justify-between items-center w-full px-2 xxs:px-8 xs:px-10" |
||||||
|
> |
||||||
|
<slot /> |
||||||
|
</div> |
||||||
|
</nav> |
@ -0,0 +1,32 @@ |
|||||||
|
<script lang="ts"> |
||||||
|
import { getContext } from "svelte"; |
||||||
|
import type { ComponentType } from "svelte"; |
||||||
|
import { Icon } from "svelte-heros-v2"; |
||||||
|
|
||||||
|
export let href: string = ""; |
||||||
|
export let icon: ComponentType; |
||||||
|
|
||||||
|
const activeUrlStore = getContext("activeUrl") as { |
||||||
|
subscribe: (callback: (value: string) => void) => void; |
||||||
|
}; |
||||||
|
|
||||||
|
let sidebarUrl = ""; |
||||||
|
activeUrlStore.subscribe((value) => { |
||||||
|
// console.log('value: ', value) |
||||||
|
sidebarUrl = value; |
||||||
|
}); |
||||||
|
// console.log('sidbarUrl: ', sidebarUrl) |
||||||
|
// console.log('href: ', href) |
||||||
|
$: active = sidebarUrl ? href === sidebarUrl : false; |
||||||
|
// console.log('active: ', active) |
||||||
|
</script> |
||||||
|
|
||||||
|
<a {href} class="flex items-center" on:click> |
||||||
|
<Icon |
||||||
|
tabindex="-1" |
||||||
|
color="black" |
||||||
|
variation={active ? "solid" : "outline"} |
||||||
|
class="w-7 h-7 text-black transition duration-75 dark:text-white group-hover:text-gray-900 dark:group-hover:text-white focus:outline-none" |
||||||
|
{icon} |
||||||
|
/> |
||||||
|
</a> |
Loading…
Reference in new issue