Add a scroll to top button, reorder the home dashboard on narrow screens, and paint cards further ahead
This commit is contained in:
parent
ff3461a020
commit
0d1e60bf1d
8 changed files with 64 additions and 13 deletions
|
|
@ -8,10 +8,12 @@
|
|||
import {displayContentCount} from "@app/content"
|
||||
import {inboxSpaceContent} from "@app/inbox"
|
||||
import {makeSpacePath} from "@app/routes"
|
||||
|
||||
const {class: className = ""}: {class?: string} = $props()
|
||||
</script>
|
||||
|
||||
{#if $inboxSpaceContent.length > 0}
|
||||
<HomeSection title="Activity" icon={Feed}>
|
||||
<HomeSection title="Activity" icon={Feed} class={className}>
|
||||
<div class="scroll-container flex items-stretch gap-3 overflow-x-auto px-4 pb-4">
|
||||
{#each $inboxSpaceContent as { url, timestamp, countsByKind } (url)}
|
||||
<Link
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
import {pushModal} from "@app/modal"
|
||||
import {HostingError, listTenantRelays, type HostedRelay} from "@app/hosting"
|
||||
|
||||
const {class: className = ""}: {class?: string} = $props()
|
||||
|
||||
let relays = $state<HostedRelay[]>([])
|
||||
let loading = $state(true)
|
||||
|
||||
|
|
@ -33,7 +35,7 @@
|
|||
})
|
||||
</script>
|
||||
|
||||
<HomeSection title="Hosting" icon={Server}>
|
||||
<HomeSection title="Hosting" icon={Server} class={className}>
|
||||
{#snippet action()}
|
||||
{#if relays.length > 0}
|
||||
<Link href="/settings/hosting" class="button button-neutral button-xs">Manage</Link>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
import {followLists, relayLists, router, user} from "@app/core"
|
||||
import {isFeedLoading, makeFeed, makeFeedContext, makeScrollLoader} from "@app/feeds"
|
||||
|
||||
const {class: className = ""}: {class?: string} = $props()
|
||||
|
||||
// The hubs most of the user's follows publish to, which is the same set and the same limit
|
||||
// `syncFollowNetwork` reads their lists from.
|
||||
const RELAY_LIMIT = 8
|
||||
|
|
@ -77,7 +79,7 @@
|
|||
})
|
||||
</script>
|
||||
|
||||
<HomeSection title="Network" icon={Planet}>
|
||||
<HomeSection title="Network" icon={Planet} class={className}>
|
||||
<div class="flex flex-col gap-3 px-4 pb-4" bind:this={element}>
|
||||
{#if isEmpty}
|
||||
<div class="flex flex-col items-center gap-3 pb-4 text-center">
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import {sortBy} from "@welshman/lib"
|
||||
import {COMMENT, NOTE} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import Cv from "@lib/components/Cv.svelte"
|
||||
import NoteItem from "@app/components/NoteItem.svelte"
|
||||
import CommentTree from "@app/components/CommentTree.svelte"
|
||||
import type {FeedContext} from "@app/feeds"
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
)
|
||||
</script>
|
||||
|
||||
<div class="cv card card-interactive flex flex-col gap-3">
|
||||
<Cv class="card card-interactive flex flex-col gap-3">
|
||||
<NoteItem {event} {context} class="" />
|
||||
{#if nodes.length > 0}
|
||||
<div class="border-line-less flex flex-col border-t">
|
||||
|
|
@ -38,4 +39,4 @@
|
|||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Cv>
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@
|
|||
icon: string
|
||||
action?: Snippet
|
||||
children: Snippet
|
||||
class?: string
|
||||
}
|
||||
|
||||
const {title, icon, action, children}: Props = $props()
|
||||
const {title, icon, action, children, class: className = ""}: Props = $props()
|
||||
</script>
|
||||
|
||||
<section class="flex min-w-0 flex-col border-b border-line last:border-b-0">
|
||||
<section class="flex min-w-0 flex-col border-b border-line {className}">
|
||||
<div class="flex items-center justify-between gap-3 px-4 pt-4 pb-3">
|
||||
<h2 class="flex items-center gap-2 text-base font-bold tracking-wide uppercase">
|
||||
<Icon {icon} size={5} />
|
||||
|
|
|
|||
36
src/lib/components/ScrollToTop.svelte
Normal file
36
src/lib/components/ScrollToTop.svelte
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<script lang="ts">
|
||||
import {fade} from "svelte/transition"
|
||||
import AltArrowUp from "@assets/icons/alt-arrow-up.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
|
||||
const {element}: {element?: Element} = $props()
|
||||
|
||||
let scrolled = $state(false)
|
||||
|
||||
const scrollToTop = () => element?.scrollTo({top: 0, behavior: "smooth"})
|
||||
|
||||
$effect(() => {
|
||||
if (element) {
|
||||
const onScroll = () => {
|
||||
scrolled = element.scrollTop > 800
|
||||
}
|
||||
|
||||
element.addEventListener("scroll", onScroll, {passive: true})
|
||||
onScroll()
|
||||
|
||||
return () => element.removeEventListener("scroll", onScroll)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if scrolled}
|
||||
<div transition:fade class="absolute right-4 bottom-20 z-nav mb-sai md:bottom-4 md:mb-0">
|
||||
<Button
|
||||
aria-label="Scroll to top"
|
||||
class="button button-neutral button-circle shadow-xl"
|
||||
onclick={scrollToTop}>
|
||||
<Icon icon={AltArrowUp} />
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -103,6 +103,7 @@
|
|||
Nothing else should reach for it. */
|
||||
@utility cv {
|
||||
content-visibility: auto;
|
||||
contain-intrinsic-size: auto 16rem;
|
||||
}
|
||||
/* Marks the event a link pointed at, so the reader can pick it out of the conversation once the
|
||||
jump lands. Brightness rather than a background so it works over any row's own surface. */
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
import Page from "@lib/components/Page.svelte"
|
||||
import PageBar from "@lib/components/PageBar.svelte"
|
||||
import PageContent from "@lib/components/PageContent.svelte"
|
||||
import ScrollToTop from "@lib/components/ScrollToTop.svelte"
|
||||
import HomeInbox from "@app/components/HomeInbox.svelte"
|
||||
import HomeActivity from "@app/components/HomeActivity.svelte"
|
||||
import HomeNetwork from "@app/components/HomeNetwork.svelte"
|
||||
|
|
@ -14,6 +15,8 @@
|
|||
import {HOSTING_ENABLED} from "@app/hosting"
|
||||
import {PLATFORM_RELAYS} from "@app/env"
|
||||
|
||||
let element: Element | undefined = $state()
|
||||
|
||||
const today = new Date().toLocaleDateString(undefined, {
|
||||
weekday: "long",
|
||||
month: "short",
|
||||
|
|
@ -38,19 +41,22 @@
|
|||
<span class="hidden text-sm opacity-75 sm:inline">{today}</span>
|
||||
</div>
|
||||
</PageBar>
|
||||
<PageContent noPad class="flex flex-col bg-surface">
|
||||
<PageContent noPad bind:element class="flex flex-col bg-surface">
|
||||
<div class="flex min-w-0 flex-1 flex-col lg:flex-row lg:items-stretch">
|
||||
<div class="flex min-w-0 flex-col lg:flex-[2] lg:border-r lg:border-line">
|
||||
<!-- The columns are `contents` below lg, which puts every section in one flow and lets the
|
||||
rail's health checks sit between the inbox and the rest of the main column. -->
|
||||
<div class="contents lg:flex lg:min-w-0 lg:flex-[2] lg:flex-col lg:border-r lg:border-line">
|
||||
<HomeInbox />
|
||||
<HomeActivity />
|
||||
<HomeNetwork />
|
||||
<HomeActivity class="order-last" />
|
||||
<HomeNetwork class="order-last border-b-0" />
|
||||
</div>
|
||||
<div class="flex min-w-0 flex-col border-t border-line lg:w-96 lg:shrink-0 lg:border-t-0">
|
||||
<div class="contents lg:flex lg:w-96 lg:min-w-0 lg:shrink-0 lg:flex-col">
|
||||
<HomeHealthChecks />
|
||||
{#if HOSTING_ENABLED}
|
||||
<HomeHosting />
|
||||
<HomeHosting class="border-b-0 max-lg:hidden" />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</PageContent>
|
||||
<ScrollToTop {element} />
|
||||
</Page>
|
||||
|
|
|
|||
Loading…
Reference in a new issue