Skip to content

Commit

Permalink
Restructure menu (#154)
Browse files Browse the repository at this point in the history
Fixes #150 
Fixes #153

---------

Co-authored-by: Anton Lilleby <[email protected]>
  • Loading branch information
an2n and Anton Lilleby authored Jan 21, 2025
1 parent bee5a3d commit dec31ea
Show file tree
Hide file tree
Showing 13 changed files with 248 additions and 64 deletions.
3 changes: 2 additions & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"kysely-postgres-js": "^2.0.0",
"nodemailer": "^6.9.14",
"postgres": "^3.4.4",
"svelte-icons": "^2.1.0",
"validator": "^13.12.0",
"zod": "^3.23.8"
},
Expand All @@ -56,9 +55,11 @@
"prettier-plugin-tailwindcss": "^0.6.5",
"svelte": "^4.2.18",
"svelte-eslint-parser": "^0.41.0",
"svelte-feather-icons": "^4.2.0",
"sveltekit-rate-limiter": "^0.5.1",
"sveltekit-superforms": "^2.16.1",
"tailwindcss": "^3.4.4",
"tailwind-merge": "^2.6.0",
"typescript": "^5.5.4",
"typescript-eslint": "^7.17.0",
"vite": "^5.3.1"
Expand Down
31 changes: 21 additions & 10 deletions app/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions app/src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
<html lang="en">
<head class="dark:bg-black">
<meta charset="utf-8" />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
<link rel="icon" href="%sveltekit.assets%/favicon.ico" />
<link rel="stylesheet" href="%sveltekit.assets%/global.css" />
<meta name="viewport" content="width=device-width" />
Expand Down
71 changes: 71 additions & 0 deletions app/src/components/shared/DarkMode.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<!--
@component
[Go to docs](https://flowbite-svelte.com/)
-->

<script lang="ts">
import { twMerge } from "tailwind-merge";
import type { HTMLButtonAttributes } from "svelte/elements";
import { Button } from "flowbite-svelte";
import { MoonIcon, SunIcon } from "svelte-feather-icons";
interface $$Props extends HTMLButtonAttributes {
btnClass?: string;
size?: "sm" | "md" | "lg";
ariaLabel?: string;
value?: string;
}
export let btnClass: $$Props["btnClass"] = "";
export let size: NonNullable<$$Props["size"]> = "md";
export let ariaLabel: $$Props["ariaLabel"] = "Dark mode";
export let value: $$Props["value"] = "";
const sizes = {
sm: "w-4 h-4",
md: "w-5 h-5",
lg: "w-6 h-6",
};
const toggleTheme = (ev: MouseEvent) => {
const target = ev.target as HTMLElement;
const isDark = target.ownerDocument.documentElement.classList.toggle("dark");
if (target.ownerDocument === document)
// we are NOT in the iFrame
localStorage.setItem("color-theme", isDark ? "dark" : "light");
};
</script>

<svelte:head>
<script>
if ("color-theme" in localStorage) {
// explicit preference - overrides author's choice
localStorage.getItem("color-theme") === "dark"
? window.document.documentElement.classList.add("dark")
: window.document.documentElement.classList.remove("dark");
} else {
// browser preference - does not overrides
if (window.matchMedia("(prefers-color-scheme: dark)").matches)
window.document.documentElement.classList.add("dark");
}
</script>
</svelte:head>

<Button
on:click={toggleTheme}
aria-label={ariaLabel}
role="button"
{...$$restProps}
class={twMerge(btnClass, $$props.class)}
color="alternative"
>
{#if value}
<span class="mr-1.5">{value}</span>
{/if}
<span class="hidden dark:block">
<SunIcon class={sizes[size]} strokeWidth={1.5} />
</span>
<span class="block dark:hidden">
<MoonIcon class={sizes[size]} strokeWidth={1.5} />
</span>
</Button>
6 changes: 3 additions & 3 deletions app/src/components/shared/EventCategoryFilter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
};
</script>

<ButtonGroup class="pb-7 flex-row md:self-end gap-2 shadow-none">
<ButtonGroup class="flex-row flex-wrap gap-2 pb-7 shadow-none md:self-end">
{#each categories as { title, keyword }}
<Button
on:click={() => handleCategoryChange(keyword)}
class={`${
selectedCategory === keyword
? "h-7 !rounded-lg !border-zinc-800 bg-zinc-800 text-white hover:bg-zinc-800 dark:bg-zinc-600 dark:hover:bg-zinc-600"
: "h-7 !rounded-lg border border-black hover:bg-zinc-800 hover:text-white dark:border-zinc-800 dark:bg-zinc-800 dark:hover:border-zinc-700 dark:hover:bg-zinc-700"
? "h-8 !rounded-lg !border-zinc-800 bg-zinc-800 text-white hover:bg-zinc-800 dark:bg-zinc-600 dark:hover:bg-zinc-600"
: "h-8 !rounded-lg border border-[#999] hover:border-black hover:bg-white dark:border-zinc-800 dark:bg-zinc-800 dark:hover:border-zinc-700 dark:hover:bg-zinc-700"
}`}
>
{title}
Expand Down
6 changes: 2 additions & 4 deletions app/src/components/shared/Header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
import logoDark from "$lib/assets/logo-dark.webp";
import logoDarkSm from "$lib/assets/logo-dark-sm.webp";
import logoLightSm from "$lib/assets/logo-light-sm.webp";
import SignInOrOut from "$components/shared/SignInOrOut.svelte";
import { page } from "$app/stores";
import { DarkMode } from "flowbite-svelte";
import { isSafariOrIOS } from "$lib/utils/device.util";
import HeaderActions from "$components/shared/HeaderActions.svelte";
export let auth;
$: isRoot = $page.url.pathname === "/";
Expand Down Expand Up @@ -35,7 +34,6 @@
</a>

<div class="flex flex-row items-center justify-end gap-2">
<SignInOrOut {auth} />
<DarkMode />
<HeaderActions {auth} />
</div>
</header>
32 changes: 32 additions & 0 deletions app/src/components/shared/HeaderActions.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script>
import { PUBLIC_SANITY_STUDIO_URL } from "$env/static/public";
import { signIn, signOut } from "@auth/sveltekit/client";
import SignedOutMenu from "./SignedOutMenu.svelte";
import SignedInDesktopMenu from "./SignedInDesktopMenu.svelte";
import SignedInMobileMenu from "./SignedInMobileMenu.svelte";
export let auth;
let isSigningOut = false;
let isSigningIn = false;
const openSanityStudio = () => {
window.open(PUBLIC_SANITY_STUDIO_URL, "_blank");
};
const signOutHandler = async () => {
isSigningOut = true;
await signOut({ callbackUrl: "/" });
};
const signInHandler = async () => {
isSigningIn = true;
await signIn("google");
};
</script>

{#if auth}
<SignedInDesktopMenu {auth} {isSigningOut} {openSanityStudio} {signOutHandler} />
<SignedInMobileMenu {auth} {isSigningOut} {openSanityStudio} {signOutHandler} />
{:else}
<SignedOutMenu {isSigningIn} {signInHandler} />
{/if}
36 changes: 0 additions & 36 deletions app/src/components/shared/SignInOrOut.svelte

This file was deleted.

32 changes: 32 additions & 0 deletions app/src/components/shared/SignedInDesktopMenu.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script>
import { Button } from "flowbite-svelte";
import { LogOutIcon, PlusIcon } from "svelte-feather-icons";
import DarkMode from "./DarkMode.svelte";
export let auth;
export let isSigningOut;
export let openSanityStudio;
export let signOutHandler;
</script>

<div class="hidden flex-row items-center gap-3 md:flex">
<span class="text-sm font-semibold">{auth.user.name}</span>
<img class="h-8 rounded-2xl" alt="Profilbilde" src={auth.user.image} />

<Button color="dark" class="h-9" pill on:click={openSanityStudio}>
<span class="mr-1.5">Opprett</span>
<PlusIcon strokeWidth={1.5} class="w-[16px]" />
</Button>

<Button
color="alternative"
class="h-9 border-[#999]"
pill
on:click={signOutHandler}
disabled={isSigningOut}
>
<span class="mr-1.5">Logg ut</span>
<LogOutIcon strokeWidth={1.5} class="w-[16px]" />
</Button>
<DarkMode size="sm" btnClass="h-9 border-[#999] rounded-2xl p-2.5" />
</div>
48 changes: 48 additions & 0 deletions app/src/components/shared/SignedInMobileMenu.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<script>
import { Button } from "flowbite-svelte";
import { LogOutIcon, PlusIcon } from "svelte-feather-icons";
import DarkMode from "./DarkMode.svelte";
export let auth;
export let openSanityStudio;
export let isSigningOut;
export let signOutHandler;
let isMenuOpen = false;
const toggleMenu = () => {
isMenuOpen = !isMenuOpen;
};
</script>

<div class="flex items-center gap-3 md:hidden">
<Button color="alternative" class="border-[#CCC] px-2 py-1 text-black" pill on:click={toggleMenu}>
<span class="mr-1.5 max-w-[150px] truncate text-sm font-semibold" title={auth.user.name}
>{auth.user.name}</span
>
<img class="h-8 rounded-2xl" alt="Profilbilde" src={auth.user.image} />
</Button>

{#if isMenuOpen}
<div
class="absolute right-4 top-20 flex w-40 flex-col items-center gap-3 rounded-md border bg-white p-4 shadow-lg dark:border-[#4B5563] dark:bg-black"
>
<Button color="dark" class="w-32 px-4 py-2 text-left" pill on:click={openSanityStudio}>
<span class="mr-1.5">Opprett</span>
<PlusIcon strokeWidth={1.5} class="w-[16px]" />
</Button>

<Button
color="alternative"
class="h-9 w-32 border-[#999]"
pill
on:click={signOutHandler}
disabled={isSigningOut}
>
<span class="mr-1.5">Logg ut</span>
<LogOutIcon strokeWidth={1.5} class="w-[16px]" />
</Button>
<DarkMode size="sm" value="Modus" btnClass="h-9 border-[#999] w-32 rounded-2xl" />
</div>
{/if}
</div>
Loading

1 comment on commit dec31ea

@vercel
Copy link

@vercel vercel bot commented on dec31ea Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.