Improved navigation and navbar

This commit is contained in:
Aleksi Lassila
2024-01-07 16:57:41 +02:00
parent 75775b2f25
commit ff96da28e3
10 changed files with 176 additions and 19 deletions

View File

@@ -1,36 +1,84 @@
<script lang="ts">
import I18n from './lib/components/Lang/I18n.svelte';
import { Link, Route, Router } from 'svelte-navigator';
import { fade } from 'svelte/transition';
import { Link, navigate, Route, Router } from 'svelte-navigator';
import { Container, handleKeyboardNavigation } from './lib/actions/focusAction';
import HomePage from './lib/pages/HomePage.svelte';
import SeriesPage from './lib/pages/SeriesPage.svelte';
import MoviesPage from './lib/pages/MoviesPage.svelte';
import LibraryPage from './lib/pages/LibraryPage.svelte';
import ManagePage from './lib/pages/ManagePage.svelte';
import SearchPage from './lib/pages/SearchPage.svelte';
import { onMount } from 'svelte';
import classNames from 'classnames';
import { Bookmark, CardStack, Gear, Laptop, MagnifyingGlass } from 'radix-icons-svelte';
import NavbarItem from './lib/components-new/NavbarItem.svelte';
const mainContainer = new Container('main').setDirection('horizontal').setFocusByDefault(true);
const navBarContainer = mainContainer.createChild('nav').setDirection('vertical');
const isNavBarOpen = navBarContainer.hasFocusWithin;
const contentContainer = mainContainer.createChild('content').setDirection('vertical');
const navBarRegisterer = navBarContainer.getRegisterer();
onMount(() => navigate('series'));
</script>
<I18n />
<main class="bg-stone-950 text-white flex flex-1 w-screen">
<Router>
<nav class="border">
<Link to="/">
<div use:navBarRegisterer tabindex="0">Home</div>
</Link>
<nav
class={classNames('flex flex-col', 'p-4', {
border: $isNavBarOpen
})}
>
<div>
<Link to="series" class="rounded-sm flex items-center">
<div class="rounded-full bg-amber-300 h-4 w-4 mr-2" />
<h1 class="font-display uppercase font-semibold tracking-wider text-xl">Reiverr</h1>
</Link>
</div>
<Link to="library">
<div use:navBarRegisterer tabindex="0">Library</div>
</Link>
<div class="flex flex-col flex-1 justify-center">
<NavbarItem parentContainer={navBarContainer} to="series">
<Laptop class="w-8 h-8 mr-3" slot="icon" />
<span class="text-xl" slot="text"> Series</span>
</NavbarItem>
<NavbarItem parentContainer={navBarContainer} to="movies">
<CardStack class="w-8 h-8 mr-3" slot="icon" />
<span class="text-xl" slot="text"> Movies</span>
</NavbarItem>
<NavbarItem parentContainer={navBarContainer} to="library">
<Bookmark class="w-8 h-8 mr-3" slot="icon" />
<span class="text-xl" slot="text"> Library</span>
</NavbarItem>
<NavbarItem parentContainer={navBarContainer} to="search">
<MagnifyingGlass class="w-8 h-8 mr-3" slot="icon" />
<span class="text-xl" slot="text"> Search</span>
</NavbarItem>
</div>
<div>
<NavbarItem parentContainer={navBarContainer} to="manage">
<Gear class="w-8 h-8 mr-3" slot="icon" />
<span class="text-xl" slot="text"> Manage</span>
</NavbarItem>
</div>
</nav>
<div class="flex-1 flex flex-col min-w-0">
<Route path="/">
<HomePage container={contentContainer} />
<Route path="series">
<SeriesPage container={contentContainer} />
</Route>
<Route path="movies">
<MoviesPage container={contentContainer} />
</Route>
<Route path="library">
<div transition:fade|global>about path</div>
<LibraryPage container={contentContainer} />
</Route>
<Route path="manage">
<ManagePage container={contentContainer} />
</Route>
<Route path="search">
<SearchPage container={contentContainer} />
</Route>
</div>
</Router>

View File

@@ -142,7 +142,7 @@ export class Container {
}
}
getRegisterer(): Registerer {
getChildRegisterer(): Registerer {
return (htmlElement: HTMLElement) => {
if (this.htmlElement) console.warn('Registering to a container that has an element.');
@@ -160,6 +160,35 @@ export class Container {
};
}
getHtmlElementRegisterer(): Registerer {
return (htmlElement: HTMLElement) => {
if (this.children.length > 0) {
console.warn('Registering an html element to a container that has children.');
for (const child of this.children) {
this.removeChild(child);
}
}
this.addHtmlElement(htmlElement);
return {
destroy: () => {
this.removeHtmlElement();
}
};
};
}
getStores(): {
container: Container;
hasFocus: Readable<boolean>;
hasFocusWithin: Readable<boolean>;
} {
return {
container: this,
hasFocus: this.hasFocus,
hasFocusWithin: this.hasFocusWithin
};
}
private addChild(child: Container) {
this.children.push(child);
child.parent = this;
@@ -214,3 +243,5 @@ export function handleKeyboardNavigation(event: KeyboardEvent) {
if (currentlyFocusedObject.giveFocus('right')) event.preventDefault();
}
}
export const focusedObject = Container.focusedObject;

View File

@@ -0,0 +1,31 @@
<script lang="ts">
import Selectable from '../components/Selectable.svelte';
import classNames from 'classnames';
import { useNavigate } from 'svelte-navigator';
import { get } from 'svelte/store';
import { Container } from '../actions/focusAction';
export let to: string;
export let parentContainer: Container;
const { container, hasFocus } = parentContainer.createChild('navBarItem').getStores();
const navigate = useNavigate();
function handleClick() {
navigate(to);
get(Container.focusedObject)?.giveFocus('right');
}
</script>
<button on:click={handleClick}>
<Selectable {container}>
<div
class={classNames('flex items-center my-2', {
'text-amber-200': $hasFocus
})}
>
<slot name="icon" />
<slot name="text" />
</div>
</Selectable>
</button>

View File

@@ -13,7 +13,7 @@
Container.focusedObject.subscribe((fo) => console.log('focusedObject', fo));
carousel.hasFocus.subscribe((hf) => console.log('hasFocus', hf));
let registerer = carousel.getRegisterer();
let registerer = carousel.getChildRegisterer();
</script>
<p

View File

@@ -1,7 +1,14 @@
<script lang="ts">
export let;
import { Container } from '../actions/focusAction';
export let container: Container;
const registerer = container.getHtmlElementRegisterer();
export let handleClick = () => {
container.focus();
};
</script>
<div>
<button use:registerer tabindex="0" on:click={handleClick} class="outline-none ring-0">
<slot />
</div>
</button>

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import type { Container } from '../actions/focusAction';
export let container: Container;
let registerer = container.getChildRegisterer();
</script>
<div use:registerer>LibraryPage</div>

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import type { Container } from '../actions/focusAction';
export let container: Container;
let registerer = container.getChildRegisterer();
</script>
<div use:registerer>ManagePage</div>

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import type { Container } from '../actions/focusAction';
export let container: Container;
let registerer = container.getChildRegisterer();
</script>
<div use:registerer>MoviesPage</div>

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import type { Container } from '../actions/focusAction';
export let container: Container;
let registerer = container.getChildRegisterer();
</script>
<div use:registerer>SearchPage</div>

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import type { Container } from '../actions/focusAction';
export let container: Container;
let registerer = container.getChildRegisterer();
</script>
<div use:registerer>SeriesPage</div>