Add header dropdown and replace icon library
This commit is contained in:
parent
64dbe4a91b
commit
7eb58bfa90
|
@ -20,6 +20,7 @@
|
|||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^1.0.2",
|
||||
"@tsconfig/svelte": "^3.0.0",
|
||||
"lucide-svelte": "^0.102.0",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier-plugin-svelte": "^2.8.0",
|
||||
"sass": "^1.55.0",
|
||||
|
@ -30,5 +31,6 @@
|
|||
"tslib": "^2.4.0",
|
||||
"typescript": "^4.6.4",
|
||||
"vite": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
<script lang="ts">
|
||||
import {Router, Route, navigate, link} from "svelte-navigator";
|
||||
import {getUser} from "./api/login";
|
||||
import Dropdown from "./lib/Dropdown.svelte";
|
||||
import HeaderDropdown from "./lib/HeaderDropdown.svelte";
|
||||
import LazyComponent from "./lib/LazyComponent.svelte";
|
||||
import {loginStore, profileStore, type LoginStore, type ProfileData} from "./stores/login";
|
||||
|
||||
function logoutAction() {
|
||||
loginStore.set(null);
|
||||
navigate("/");
|
||||
}
|
||||
|
||||
let profile: ProfileData;
|
||||
|
||||
loginStore.subscribe((value: LoginStore) => {
|
||||
|
@ -44,23 +39,7 @@
|
|||
|
||||
<nav>
|
||||
{#if profile !== undefined}
|
||||
<Dropdown>
|
||||
<div slot="header" class="dropdown-header">
|
||||
{#if profile.icon == "0"}
|
||||
<img
|
||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
|
||||
alt="Profile Icon"
|
||||
class="header-icon"
|
||||
/>
|
||||
{:else}
|
||||
<img src={profile.icon} alt="Profile Icon" class="header-icon" />
|
||||
{/if}
|
||||
<span>{profile.display_name}</span>
|
||||
</div>
|
||||
<div slot="body" class="dropdown-body">
|
||||
<a href="/logout" on:click|preventDefault={logoutAction}>Logout</a>
|
||||
</div>
|
||||
</Dropdown>
|
||||
<HeaderDropdown {profile} />
|
||||
{:else}
|
||||
<a href="/register" use:link>Register</a>
|
||||
<a href="/login" use:link>Login</a>
|
||||
|
@ -115,23 +94,6 @@
|
|||
background-color: var(--primary-main);
|
||||
border-radius: 0 0 var(--large-curve) var(--large-curve);
|
||||
|
||||
> nav {
|
||||
.dropdown-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> .header-icon {
|
||||
> img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-body {
|
||||
}
|
||||
}
|
||||
|
||||
> .central-header {
|
||||
padding: 0 32px;
|
||||
height: 50px;
|
||||
|
@ -144,6 +106,12 @@
|
|||
max-width: min(100%, 1000px);
|
||||
margin: auto;
|
||||
|
||||
> nav {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #eeeeee;
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@import "./assets/material-symbols.scss";
|
||||
|
||||
:root {
|
||||
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
/* fallback */
|
||||
@font-face {
|
||||
font-family: "Material Symbols Outlined";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(~/assets/material-symbols.woff2) format("woff2");
|
||||
}
|
||||
|
||||
@mixin mso {
|
||||
font-family: "Material Symbols Outlined";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-moz-font-feature-settings: "liga";
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
Binary file not shown.
|
@ -1,60 +0,0 @@
|
|||
<script lang="ts">
|
||||
export let align = "left";
|
||||
|
||||
let open = false;
|
||||
</script>
|
||||
|
||||
<div class="dropdown align-{align}">
|
||||
<div class="dropdown-header">
|
||||
<div>
|
||||
<slot name="header" />
|
||||
</div>
|
||||
<div class="flex-gap" />
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 32 32"
|
||||
fill="currentColor"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
width="16"
|
||||
height="16"
|
||||
role="img"
|
||||
aria-label="Open menu"
|
||||
style="--darkreader-inline-fill: currentColor;"
|
||||
data-darkreader-inline-fill=""><path d="M16 22L6 12 7.4 10.6 16 19.2 24.6 10.6 26 12z" /></svg
|
||||
>
|
||||
</div>
|
||||
{#if open}
|
||||
<div class="dropdown-body">
|
||||
<slot name="body" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.dropdown {
|
||||
position: relative;
|
||||
|
||||
> .dropdown-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
> .dropdown-body {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
background: var(--bg-panel);
|
||||
}
|
||||
|
||||
&.align-left > .dropdown-body {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&.align-right > .dropdown-body {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.flex-gap {
|
||||
flex-grow: 1;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,134 @@
|
|||
<script lang="ts">
|
||||
import {loginStore, type ProfileData} from "~/stores/login";
|
||||
import {User, Settings, LogOut, ChevronUp, ChevronDown} from "lucide-svelte";
|
||||
import {link, navigate} from "svelte-navigator";
|
||||
|
||||
export let profile: ProfileData;
|
||||
|
||||
let open = false;
|
||||
|
||||
function handleClick() {
|
||||
open = !open;
|
||||
}
|
||||
|
||||
function logoutAction() {
|
||||
loginStore.set(null);
|
||||
navigate("/");
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="dropdown {open ? 'dropdown-open' : ''}">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="dropdown-header" on:click={handleClick}>
|
||||
<div class="dropdown-title">
|
||||
{#if profile.icon == "0"}
|
||||
<img
|
||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
|
||||
alt="Profile Icon"
|
||||
class="header-icon"
|
||||
/>
|
||||
{:else}
|
||||
<img src={profile.icon} alt="Profile Icon" class="header-icon" />
|
||||
{/if}
|
||||
<span>{profile.display_name}</span>
|
||||
</div>
|
||||
{#if open}
|
||||
<ChevronUp />
|
||||
{:else}
|
||||
<ChevronDown />
|
||||
{/if}
|
||||
</div>
|
||||
{#if open}
|
||||
<div class="dropdown-floating">
|
||||
<div class="dropdown-body">
|
||||
<a href="/profile" use:link>
|
||||
<User />
|
||||
<span>Profile</span>
|
||||
</a>
|
||||
<a href="/settings" use:link>
|
||||
<Settings />
|
||||
<span>Settings</span>
|
||||
</a>
|
||||
<a href="/logout" on:click|preventDefault={logoutAction}>
|
||||
<LogOut />
|
||||
<span>Logout</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.dropdown {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
|
||||
&.dropdown-open {
|
||||
background-color: var(--bg-panel-action);
|
||||
}
|
||||
|
||||
> .dropdown-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
height: 100%;
|
||||
padding: 0 16px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--bg-panel);
|
||||
}
|
||||
|
||||
> .dropdown-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 4px;
|
||||
|
||||
> .header-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .dropdown-floating {
|
||||
z-index: 9998;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
background: var(--bg-panel-action);
|
||||
width: 100%;
|
||||
border-radius: 0 0 8px 8px;
|
||||
|
||||
-webkit-box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
-moz-box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
clip-path: inset(0px -10px -10px -10px);
|
||||
|
||||
> .dropdown-body {
|
||||
border-radius: 0 0 8px 8px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
|
||||
> a {
|
||||
display: flex;
|
||||
padding: 8px 16px 8px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--bg-panel);
|
||||
}
|
||||
|
||||
> span {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -34,7 +34,7 @@
|
|||
}
|
||||
|
||||
onMount(async function () {
|
||||
updatePage(postLogin({}, ""));
|
||||
updatePage(postLogin({}));
|
||||
});
|
||||
|
||||
let loading = false;
|
||||
|
|
|
@ -442,6 +442,11 @@ lower-case@^2.0.2:
|
|||
dependencies:
|
||||
tslib "^2.0.3"
|
||||
|
||||
lucide-svelte@^0.102.0:
|
||||
version "0.102.0"
|
||||
resolved "https://registry.yarnpkg.com/lucide-svelte/-/lucide-svelte-0.102.0.tgz#4a8bca665e6f01d21d60bb057996c35a6e878eb5"
|
||||
integrity sha512-r8Nmz3XnRiesT3BxTaQvJnkbvutJMDv7HHADfDVZ1VLo3tWInfSBzWQya1V12dFfdBoz/bMwBX0abpccw77v4A==
|
||||
|
||||
magic-string@^0.25.7:
|
||||
version "0.25.9"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
|
||||
|
|
Reference in New Issue