cosmetic changes

This commit is contained in:
Christian Beutel
2025-03-20 19:16:04 +01:00
parent b261ada15c
commit efcec77c95
6 changed files with 132 additions and 85 deletions

View File

@@ -14,7 +14,7 @@
<div <div
class="{primary class="{primary
? 'bg-primary text-white' ? 'bg-primary text-white'
: 'bg-background-inverse/10'} px-2 py-1 rounded-full flex items-center gap-1" : 'border border-input-border'} px-2 py-1 rounded-full flex items-center gap-1"
> >
<span class="text-sm">{text}</span> <span class="text-sm">{text}</span>
{#if closable} {#if closable}

View File

@@ -7,7 +7,7 @@
</script> </script>
<script lang="ts"> <script lang="ts">
import { type Snippet } from "svelte"; import { tick, type Snippet } from "svelte";
import { fly } from "svelte/transition"; import { fly } from "svelte/transition";
interface Props { interface Props {
@@ -21,10 +21,38 @@
let isOpen = $state(false); let isOpen = $state(false);
export function toggleMenu(e: MouseEvent) { let dropdownElement: HTMLUListElement;
let dropdownToggleElement: HTMLDivElement;
export async function toggleMenu(e: MouseEvent) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
isOpen = !isOpen; isOpen = !isOpen;
if (isOpen) {
await tick();
const toggleRect = dropdownToggleElement.getBoundingClientRect();
const dropdownRect = dropdownElement.getBoundingClientRect();
dropdownElement.style.visibility = "";
const viewportHeight = window.innerHeight;
const spaceBelow = viewportHeight - toggleRect.bottom;
const spaceAbove = toggleRect.top;
if (
spaceBelow < dropdownRect.height &&
spaceAbove > dropdownRect.height
) {
dropdownElement.classList.remove("rounded-b-xl");
dropdownElement.classList.add("rounded-t-xl");
dropdownElement.style.top = `${-8-dropdownRect.height}px`;
} else {
dropdownElement.classList.remove("rounded-t-xl");
dropdownElement.classList.add("rounded-b-xl");
dropdownElement.style.top = `${toggleRect.height +8}px`;
}
}
} }
function closeMenu() { function closeMenu() {
@@ -53,7 +81,7 @@
<svelte:window onmouseup={handleWindowClick} /> <svelte:window onmouseup={handleWindowClick} />
<div class="dropdown relative"> <div class="dropdown relative">
<div class="dropdown-toggle"> <div class="dropdown-toggle" bind:this={dropdownToggleElement}>
{#if children}{@render children({ toggleMenu })}{:else} {#if children}{@render children({ toggleMenu })}{:else}
<button <button
aria-label="Toggle menu" aria-label="Toggle menu"
@@ -68,11 +96,12 @@
{#if isOpen} {#if isOpen}
<ul <ul
class="menu absolute bg-menu-background border border-input-border rounded-l-xl rounded-b-xl shadow-md right-0 overflow-hidden mt-2" class="menu absolute bg-menu-background border border-input-border shadow-md rounded-l-xl rounded-b-xl right-0 overflow-hidden"
class:none={isOpen} class:none={isOpen}
style="z-index: 1001" style="z-index: 1001"
in:fly={{ y: -10, duration: 150 }} in:fly={{ y: -10, duration: 150 }}
out:fly={{ y: -10, duration: 150 }} out:fly={{ y: -10, duration: 150 }}
bind:this={dropdownElement}
> >
{#each items as item} {#each items as item}
<li <li

View File

@@ -76,7 +76,7 @@
? 'grid-cols-[8fr_5fr]' ? 'grid-cols-[8fr_5fr]'
: 'grid-cols-1'}" : 'grid-cols-1'}"
> >
{#each activity.photos as photo, i} {#each activity.photos.slice(0,3) as photo, i}
{#if isVideoURL(photo)} {#if isVideoURL(photo)}
<!-- svelte-ignore a11y_media_has_caption --> <!-- svelte-ignore a11y_media_has_caption -->
<video <video

View File

@@ -209,7 +209,7 @@
>{#snippet children({ toggleMenu: openDropdown })} >{#snippet children({ toggleMenu: openDropdown })}
<button <button
aria-label="Open dropdown" aria-label="Open dropdown"
class="rounded-full bg-white text-black hover:bg-gray-200 focus:ring-4 ring-gray-100/50 transition-colors h-12 w-12" class=" btn-primary !rounded-full h-12 w-12"
onclick={openDropdown} onclick={openDropdown}
> >
<i class="fa fa-ellipsis-vertical"></i> <i class="fa fa-ellipsis-vertical"></i>

View File

@@ -150,13 +150,19 @@
comments.set(newCommentList); comments.set(newCommentList);
commentDeleteLoading = false; commentDeleteLoading = false;
} }
let thumbnail = $derived(
trail.photos.length function getHeaderPhotos() {
? getFileURL(trail, trail.photos[trail.thumbnail ?? 0]) if (trail.photos.length) {
: $theme === "light" return trail.photos.slice(0, 3).map((p) => getFileURL(trail, p));
? emptyStateTrailLight } else {
: emptyStateTrailDark, return $theme === "light"
); ? [emptyStateTrailLight]
: [emptyStateTrailDark];
}
}
const headerPhotos = getHeaderPhotos();
$effect(() => { $effect(() => {
if (browser && activeTab == 2) { if (browser && activeTab == 2) {
fetchComments(); fetchComments();
@@ -172,33 +178,65 @@
style="max-width: min(100%, 76rem);" style="max-width: min(100%, 76rem);"
> >
<div class="trail-info-panel-header"> <div class="trail-info-panel-header">
<section class="relative h-80"> <section class="relative">
{#if isVideoURL(thumbnail)} <button
aria-label="Back"
class="bg-black/40 text-white text-lg rounded-full w-10 h-10 hover:bg-black/50 transition-colors focus:ring-4 focus:ring-primary/70 top-6 left-6 absolute"
onclick={() => history.back()}
>
<i class="fa fa-arrow-left"></i>
</button>
<div
class="grid gap-[1px] {headerPhotos.length > 1
? 'grid-cols-[8fr_5fr]'
: 'grid-cols-1'} h-80 rounded-t-3xl overflow-hidden cursor-pointer"
>
<PhotoGallery
photos={trail.photos.map((p) => getFileURL(trail, p))}
bind:this={gallery}
></PhotoGallery>
{#each headerPhotos as photo, i}
{#if isVideoURL(photo)}
<!-- svelte-ignore a11y_media_has_caption --> <!-- svelte-ignore a11y_media_has_caption -->
<video <video
class="w-full h-80 object-cover rounded-t-3xl" class="object-cover h-full w-full"
onclick={trail.photos.length
? () => gallery.openGallery(i)
: null}
autoplay autoplay
loop loop
src={thumbnail} src={photo}
></video> ></video>
{:else} {:else}
<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
<img <img
class="w-full h-80" class="object-cover h-full w-full"
class:rounded-t-3xl={mode !== "list"} onclick={trail.photos.length
src={thumbnail} ? () => gallery.openGallery(i)
: null}
class:row-span-2={i == 0 && headerPhotos.length > 2}
src={photo}
alt="" alt=""
/> />
{/if} {/if}
{/each}
<div </div>
class="absolute bottom-0 w-full h-full bg-gradient-to-b from-transparent to-black opacity-60" </section>
></div> <section class="border-b border-input-border p-8">
<div class="flex justify-between items-center gap-x-4">
{#if trail.expand?.tags && trail.expand.tags.length > 0}
<div class="flex flex-wrap gap-2 text-gray-600">
{#each trail.expand.tags as tag}
<Chip text={tag.name}></Chip>
{/each}
</div>
{/if}
{#if (trail.public || trailIsShared) && pb.authStore.record} {#if (trail.public || trailIsShared) && pb.authStore.record}
<div <div
class="flex absolute top-6 right-6 {trail.public && class="flex {trail.public && trailIsShared
trailIsShared
? 'w-16' ? 'w-16'
: 'w-8'} h-8 rounded-full items-center justify-center bg-white text-primary" : 'w-8'} h-8 rounded-full items-center justify-center"
> >
{#if trail.public && pb.authStore.record} {#if trail.public && pb.authStore.record}
<span <span
@@ -214,27 +252,20 @@
{/if} {/if}
</div> </div>
{/if} {/if}
{#if mode == "map"} </div>
<button <div class="flex justify-between items-end w-full gap-y-4">
aria-label="Back" <div class=" overflow-hidden">
class="btn-icon hover:bg-white hover:text-black ring-input-ring text-white absolute top-6 left-6"
onclick={() => history.back()}
>
<i class="fa fa-arrow-left"></i>
</button>
{/if}
<div
class="flex absolute justify-between items-end w-full bottom-8 left-0 px-8 gap-y-4"
>
<div class="text-white overflow-hidden">
<h4 <h4
title={trail.name} title={trail.name}
class="text-4xl font-bold line-clamp-3" class="{mode == 'map'
? 'text-4xl'
: 'text-5xl'} font-bold line-clamp-3 mb-1"
style="line-height: 1.18"
> >
{trail.name} {trail.name}
</h4> </h4>
{#if trail.date} {#if trail.date}
<h5 class="text-sm"> <h5 class="text-sm text-gray-500">
{new Date(trail.date).toLocaleDateString( {new Date(trail.date).toLocaleDateString(
undefined, undefined,
{ {
@@ -247,7 +278,7 @@
</h5> </h5>
{/if} {/if}
{#if trail.expand?.author} {#if trail.expand?.author}
<p class="mt-2 mb-3"> <p class="mt-3 mb-3">
{$_("by")} {$_("by")}
<img <img
class="rounded-full w-8 aspect-square mx-1 inline" class="rounded-full w-8 aspect-square mx-1 inline"
@@ -269,13 +300,6 @@
{/if} {/if}
</p> </p>
{/if} {/if}
{#if trail.expand?.tags && trail.expand.tags.length > 0}
<div class="flex flex-wrap gap-2 text-gray-600">
{#each trail.expand.tags as tag}
<Chip text={tag.name}></Chip>
{/each}
</div>
{/if}
<div class="flex flex-wrap gap-x-8 gap-y-2 mt-2 mr-8"> <div class="flex flex-wrap gap-x-8 gap-y-2 mt-2 mr-8">
{#if trail.location} {#if trail.location}
<h3 class="text-lg"> <h3 class="text-lg">
@@ -418,12 +442,6 @@
? 'sm:grid-cols-2 md:grid-cols-3' ? 'sm:grid-cols-2 md:grid-cols-3'
: ''} gap-4" : ''} gap-4"
> >
<PhotoGallery
photos={trail.photos.map((p) =>
getFileURL(trail, p),
)}
bind:this={gallery}
></PhotoGallery>
{#each trail.photos ?? [] as photo, i} {#each trail.photos ?? [] as photo, i}
<!-- svelte-ignore a11y_click_events_have_key_events --> <!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_noninteractive_element_interactions --> <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->

View File

@@ -51,7 +51,7 @@
? 'grid-cols-[8fr_5fr]' ? 'grid-cols-[8fr_5fr]'
: 'grid-cols-1'} cursor-pointer" : 'grid-cols-1'} cursor-pointer"
> >
{#each wp.photos as photo, j} {#each wp.photos.slice(0,3) as photo, j}
{#if isVideoURL(photo)} {#if isVideoURL(photo)}
<!-- svelte-ignore a11y_media_has_caption --> <!-- svelte-ignore a11y_media_has_caption -->
<video <video