GUI base navigation & home

This commit is contained in:
venashial
2022-03-06 10:55:51 -08:00
parent f3b5155274
commit e6329819c7
26 changed files with 2087 additions and 85 deletions

View File

@@ -0,0 +1,54 @@
<script lang="ts">
export let title: string;
</script>
<div class="card-row">
<div class="card-row__title">{title}</div>
<div class="card-row__items">
<slot />
</div>
</div>
<style lang="postcss">
.card-row {
display: flex;
flex-direction: column;
padding: 1rem 0;
grid-gap: 1rem;
&__title {
padding: 0 1rem;
display: flex;
grid-gap: 1rem;
align-items: center;
&::after {
flex: 1 1;
content: " ";
background-color: hsla(0,0%,100%,0.2);
height: 0.2rem;
border-radius: var(--rounded-max);
}
}
&__items {
display: flex;
grid-gap: 1rem;
align-items: flex-start;
overflow-x: auto;
padding: 0 1rem;
/* Hide scrollbar */
-ms-overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
&:nth-of-type(even) {
background-color: hsla(0,0%,0%,0.2);
}
}
</style>

View File

@@ -0,0 +1,78 @@
<script lang="ts">
import IconPlayFilled from "virtual:icons/carbon/play-filled-alt"
export let title: string;
export let id: string;
export let version: string;
export let modpack = false;
export let image: string;
</script>
<a class="instance" href="/library/instance/{id}"
style:background-image="linear-gradient(5deg, hsla(0,0%,0%,0.8) 0%, hsla(0,0%,0%,0) 100%), url('{image}')">
<div class="instance__version">{version}</div>
<div class="instance__title">{title}</div>
<button class="play-button">
<IconPlayFilled />
</button>
</a>
<style lang="postcss">
.instance {
--size: 8rem;
min-width: var(--size);
min-height: var(--size);
border-radius: var(--rounded);
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 0.5rem;
box-shadow: var(--shadow-raised) var(--shadow-inset);
position: relative;
background-size: cover;
&__title {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
&__version {
color: var(--color-text);
font-size: var(--font-size-sm);
}
&:hover .play-button {
visibility: visible;
opacity: 1;
transform: none;
}
.play-button {
position: absolute;
bottom: 0.5rem;
right: 0.5rem;
background-color: var(--color-brand);
width: 2.5rem;
aspect-ratio: 1 / 1;
border-radius: var(--rounded-max);
display: flex;
align-items: center;
justify-content: center;
visibility: hidden;
opacity: 0;
transition-property: opacity, visibility, transform;
transition-duration: 0.2s;
transition-timing-function: ease-in-out;
transform: translateY(1rem);
:global(svg) {
width: 1.25rem;
height: auto;
color: black;
}
}
}
</style>

View File

@@ -0,0 +1,36 @@
<script lang="ts">
import { SvelteComponent } from 'svelte'
import { page } from "$app/stores";
export let items: {
label: string,
/** Page href, without slash prefix */
href: string,
icon: SvelteComponent
}[];
/** Path level in URL, zero-indexed */
export let level = 0;
let path: string[];
$: path = $page.url.pathname
.substring(1)
.split('/')
</script>
<div class="vertical-nav">
{#each items as item (item.href)}
<a class="nav-item" href="/{item.href}" class:active={path[level] === item.href}>
<svelte:component this={item.icon} />
{item.label}
</a>
{/each}
</div>
<style lang="postcss">
.vertical-nav {
display: flex;
flex-direction: column;
grid-gap: 0.25rem;
}
</style>

View File

@@ -0,0 +1,51 @@
<script lang="ts">
import { Svrollbar } from 'svrollbar'
let viewport: Element
let contents: Element
</script>
<div class="page">
<div bind:this={viewport} class="viewport">
<div bind:this={contents} class="contents">
<slot />
</div>
</div>
<Svrollbar {viewport} {contents} />
</div>
<style>
.page {
position: relative;
width: 100%;
overflow: hidden;
--svrollbar-track-width: 20px;
--svrollbar-track-opacity: 0;
--svrollbar-thumb-width: 8px;
--svrollbar-thumb-background: hsla(216,5%,60%);
--svrollbar-thumb-opacity: 0.9;
}
.viewport {
position: relative;
width: 100%;
height: calc(100vh - 2.5rem);
overflow-y: scroll;
overflow-x: hidden;
/* hide scrollbar */
-ms-overflow-style: none;
scrollbar-width: none;
}
.viewport::-webkit-scrollbar {
/* hide scrollbar */
display: none;
}
:global(.v-thumb) {
margin: 4px auto 4px auto !important;
}
</style>

View File

@@ -0,0 +1,77 @@
<script lang="ts">
import VerticalNav from '../components/VerticalNav.svelte'
import IconHome from 'virtual:icons/lucide/home'
import IconSearch from 'virtual:icons/heroicons-outline/search'
import IconLibrary from 'virtual:icons/lucide/library';
import IconSettings from 'virtual:icons/lucide/settings'
import { page } from "$app/stores";
</script>
<div class="sidebar">
<div class="account">
<div class="account__heads">
<img src="https://mc-heads.net/avatar/venashial" alt="Minecraft head"/>
</div>
<a class="account__info" href="/settings/accounts">
<div>venashial</div>
<div class="account__info__manage">Manage accounts</div>
</a>
</div>
<VerticalNav items={[
{
label: 'Home',
href: '',
icon: IconHome,
},
{
label: 'Search',
href: 'search',
icon: IconSearch,
},
{
label: 'Library',
href: 'library',
icon: IconLibrary,
}
]}/>
<a class="nav-item" href="/settings" class:active={$page.url.pathname.startsWith('/settings')}>
<IconSettings />
Settings
</a>
</div>
<style lang="postcss">
.sidebar {
display: flex;
flex-direction: column;
padding: 1rem;
grid-gap: 2rem;
height: 100%;
background-color: var(--sidebar-bg);
.account {
display: flex;
grid-gap: 0.75rem;
&__heads {
img {
width: 2.5rem;
border-radius: var(--rounded-sm);
}
}
&__info {
&__manage {
color: var(--color-text-light)
}
}
}
*:last-child {
margin-top: auto;
}
}
</style>

View File

@@ -0,0 +1,70 @@
<script lang="ts">
import IconChevronLeft from 'virtual:icons/lucide/chevron-left';
import IconChevronRight from 'virtual:icons/lucide/chevron-right';
import IconCaretRight from 'virtual:icons/carbon/caret-right';
import { page } from '$app/stores'
let path: string[];
$: path = $page.url.pathname
.substring(1)
.split('/')
</script>
<div class="status-bar">
<div class="page-nav">
<button title="Back" on:click={() => window.history.back()}>
<IconChevronLeft />
</button>
<button title="Forward" on:click={() => window.history.forward()}>
<IconChevronRight />
</button>
</div>
<div class="breadcrumbs">
{#each path as crumb, index}
{#if index !== 0}
<div class="breadcrumbs__separator"><IconCaretRight /></div>
{/if}
<a class="breadcrumbs__crumb" href={crumb}>{crumb || 'home'}</a>
{/each}
</div>
<div class="statuses">
<div>Updating 12 mods...</div>
<div>236 mods installed</div>
</div>
</div>
<style lang="postcss">
.status-bar {
display: flex;
padding: 0.75rem;
grid-gap: 0.75rem;
background-color: var(--status-bg);
width: 100%;
height: 100%;
align-items: center;
box-shadow: var(--shadow-raised);
}
.breadcrumbs {
display: flex;
grid-gap: 0.25rem;
text-transform: capitalize;
&__crumb:hover {
text-decoration: underline;
}
&__separator {
color: var(--color-text-lightest)
}
}
.statuses {
margin-left: auto;
display: flex;
grid-gap: 1rem;
color: var(--color-text-lightest);
}
</style>