Move away from fixed positioned page elements because they act squirrely on android

This commit is contained in:
Jon Staab
2026-04-03 17:14:55 -07:00
parent fceccf47be
commit 9311cab3b2
15 changed files with 181 additions and 202 deletions
+4 -20
View File
@@ -390,28 +390,12 @@ progress[value]::-webkit-progress-value {
/* content width for fixed elements */
.cw {
@apply w-full md:left-[18.5rem] md:w-[calc(100%-18.5rem-var(--sair))];
}
.cw-full {
@apply w-full md:left-[4rem] md:w-[calc(100%-4rem-var(--sair))];
}
.cb {
@apply md:bottom-sai bottom-[calc(var(--saib)+3.5rem)];
}
.ct {
@apply top-[calc(var(--sait)+5rem)] md:top-[calc(var(--sait)+3rem)];
.left-content {
@apply md:left-[calc(18.5rem+var(--sail))];
}
/* Keyboard open state adjustments */
body.keyboard-open .cb {
@apply bottom-sai;
}
body.keyboard-open .hide-on-keyboard {
display: none;
}
@@ -419,11 +403,11 @@ body.keyboard-open .hide-on-keyboard {
/* chat view */
.chat__compose {
@apply cb cw fixed z-compose;
@apply left-content bottom-sai right-sai fixed z-compose;
}
.chat__compose-zone {
@apply cb cw fixed z-compose;
@apply left-content bottom-sai right-sai fixed z-compose;
}
.chat__compose-zone .chat__compose-inner {
+5 -1
View File
@@ -64,7 +64,11 @@
</script>
<div bind:this={spacer}></div>
<form in:fly bind:this={form} onsubmit={preventDefault(submit)} class="cb cw fixed z-feature pt-3">
<form
in:fly
bind:this={form}
onsubmit={preventDefault(submit)}
class="left-content bottom-sai right-sai ml-2 pl-2 fixed z-feature">
<div class="card2 mx-2 my-2 bg-alt shadow-md">
<div class="relative">
<div class="note-editor flex-grow overflow-hidden">
+1 -1
View File
@@ -32,7 +32,7 @@
</script>
<div
class="ml-sai mt-sai mb-sai relative z-nav hidden w-14 flex-shrink-0 bg-base-200 pt-4 md:block">
class="ml-sai mt-sai mb-sai relative z-nav hidden w-14 flex-shrink-0 bg-base-200 pt-2 md:block">
<div class="flex h-full flex-col" class:justify-between={PLATFORM_RELAYS.length === 0}>
<PrimaryNavSpaces />
{#if PLATFORM_RELAYS.length > 0}
+1 -1
View File
@@ -12,7 +12,7 @@
const itemHeight = 56
const navPadding = 8 * itemHeight
const itemLimit = $derived((windowHeight - navPadding) / itemHeight)
const itemLimit = $derived(Math.max(0, (windowHeight - navPadding) / itemHeight))
const [primarySpaceUrls, secondarySpaceUrls] = $derived(splitAt(itemLimit, $userSpaceUrls))
const otherSpaceNotifications = $derived(secondarySpaceUrls.some(p => $notifications.has(p)))
</script>
+67 -69
View File
@@ -130,76 +130,74 @@
}
</script>
<div>
<button class="btn btn-neutral btn-sm btn-square" aria-label="Search" onclick={open}>
<Icon size={4} icon={Magnifier} />
</button>
{#if show}
<button class="fixed inset-0 z-feature" aria-label="Close search" onclick={close}></button>
<div class="fixed cw top-0 right-0 z-feature p-2">
<div
class="card2 card2-sm bg-alt flex flex-col gap-2 shadow-md"
transition:fly={{y: -40, duration: 150}}>
<div class="flex justify-between">
<strong>Search</strong>
<Button onclick={clear}>
<Icon icon={CloseCircle} />
</Button>
</div>
<label class="input input-sm input-bordered flex w-full items-center gap-2">
<Icon size={4} icon={Magnifier} />
<input
bind:this={input}
bind:value={term}
class="min-w-0 grow"
type="text"
placeholder={h ? "Search this room..." : "Search this space..."}
oninput={onInput} />
</label>
<div class="max-h-[65vh] overflow-y-auto">
<p class="mb-2 text-xs opacity-70">{relayStatus}</p>
{#if !term}
<p class="text-sm opacity-70">
{h ? "Search for content in this room." : "Search for content in this space."}
</p>
{:else if loading}
<p class="text-sm opacity-70">Searching...</p>
{:else if eventsByAge.size === 0}
<p class="text-sm opacity-70">No results found.</p>
{:else}
<div class="col-2">
{#each eventsByAge as [key, events] (key)}
<button class="btn btn-neutral btn-sm btn-square" aria-label="Search" onclick={open}>
<Icon size={4} icon={Magnifier} />
</button>
{#if show}
<button class="fixed inset-0 z-feature" aria-label="Close search" onclick={close}></button>
<div class="fixed top-sai right-sai left-content z-feature p-2">
<div
class="card2 card2-sm bg-alt flex flex-col gap-2 shadow-md"
transition:fly={{y: -40, duration: 150}}>
<div class="flex justify-between">
<strong>Search</strong>
<Button onclick={clear}>
<Icon icon={CloseCircle} />
</Button>
</div>
<label class="input input-sm input-bordered flex w-full items-center gap-2">
<Icon size={4} icon={Magnifier} />
<input
bind:this={input}
bind:value={term}
class="min-w-0 grow"
type="text"
placeholder={h ? "Search this room..." : "Search this space..."}
oninput={onInput} />
</label>
<div class="max-h-[65vh] overflow-y-auto">
<p class="mb-2 text-xs opacity-70">{relayStatus}</p>
{#if !term}
<p class="text-sm opacity-70">
{h ? "Search for content in this room." : "Search for content in this space."}
</p>
{:else if loading}
<p class="text-sm opacity-70">Searching...</p>
{:else if eventsByAge.size === 0}
<p class="text-sm opacity-70">No results found.</p>
{:else}
<div class="col-2">
{#each eventsByAge as [key, events] (key)}
<div class="col-2">
<p class="text-xs uppercase tracking-wide opacity-60">
{#if key === "day"}
Last 24 Hours
{:else if key === "week"}
Last 7 Days
{:else}
Older
{/if}
</p>
<div class="col-2">
<p class="text-xs uppercase tracking-wide opacity-60">
{#if key === "day"}
Last 24 Hours
{:else if key === "week"}
Last 7 Days
{:else}
Older
{/if}
</p>
<div class="col-2">
{#each events as event (event.id)}
<button
class="card2 bg-alt card2-sm col-2 transition-colors hover:bg-base-200 text-left"
onclick={() => onRoomSearchResultClick(event)}>
<p class="line-clamp-2 text-sm">
{event.content.trim() || "(No text content)"}
</p>
<div class="row-2 text-xs opacity-70">
<span>{getAgeLabel(event.created_at)}</span>
<span>{formatTimestampAsDate(event.created_at)}</span>
</div>
</button>
{/each}
</div>
{#each events as event (event.id)}
<button
class="card2 bg-alt card2-sm col-2 transition-colors hover:bg-base-200 text-left"
onclick={() => onRoomSearchResultClick(event)}>
<p class="line-clamp-2 text-sm">
{event.content.trim() || "(No text content)"}
</p>
<div class="row-2 text-xs opacity-70">
<span>{getAgeLabel(event.created_at)}</span>
<span>{formatTimestampAsDate(event.created_at)}</span>
</div>
</button>
{/each}
</div>
{/each}
</div>
{/if}
</div>
</div>
{/each}
</div>
{/if}
</div>
</div>
{/if}
</div>
</div>
{/if}
+1 -1
View File
@@ -9,6 +9,6 @@
<div
data-component="Page"
class="scroll-container bottom-sai top-sai cw fixed mb-14 overflow-auto bg-base-200 md:mb-0 {props.class}">
class="relative flex-grow flex flex-col min-w-0 ml-sai mb-sai mt-sai mr-sai bg-base-200 md:ml-0 md:mb-0 {props.class}">
{@render props.children?.()}
</div>
+1 -1
View File
@@ -9,7 +9,7 @@
const {children, ...props}: Props = $props()
</script>
<div data-component="PageBar" class="cw top-sai fixed z-nav p-2 {props.class}">
<div data-component="PageBar" class="relative z-nav p-2 -mb-4 {props.class}">
<div class="rounded-xl bg-base-100 p-4 shadow-md h-20 md:h-12 flex flex-col justify-center">
{@render children?.()}
</div>
+1 -4
View File
@@ -10,10 +10,7 @@
let {children, element = $bindable(), ...props}: Props = $props()
const className = cx(
props.class,
"scroll-container cw cb ct fixed z-feature overflow-y-auto overflow-x-hidden",
)
const className = cx(props.class, "scroll-container z-feature overflow-y-auto overflow-x-hidden")
</script>
<div {...props} bind:this={element} data-component="PageContent" class={className}>
+1 -1
View File
@@ -12,7 +12,7 @@
<div
class={cx(
"ml-sai mt-sai mb-sai max-h-screen w-60 sm:flex-shrink-0 flex-col gap-1 bg-base-300 z-nav hidden md:flex",
"mt-sai mb-sai max-h-screen w-60 min-h-0 flex-shrink-0 flex-col gap-1 bg-base-300 z-nav hidden md:flex",
props.class,
)}>
{@render children?.()}
@@ -7,6 +7,6 @@
const {...props}: Props = $props()
</script>
<div class="flex flex-col gap-1 px-2 py-4 {props.class}">
<div class="flex flex-col gap-1 px-2 py-2 {props.class}">
{@render props.children?.()}
</div>
+1 -1
View File
@@ -37,7 +37,7 @@
})
</script>
<Page class="cw-full">
<Page>
<ContentSearch>
{#snippet input()}
<label class="row-2 input input-bordered">
+3 -3
View File
@@ -180,8 +180,8 @@
})
</script>
<Page class="cw-full">
<PageBar class="cw-full">
<Page>
<PageBar>
{#if showSearch}
<label class="input input-bordered input-sm flex flex-1 items-center gap-2" in:fly>
<Icon icon={Magnifier} />
@@ -218,7 +218,7 @@
</div>
{/if}
</PageBar>
<PageContent class="cw-full flex flex-col gap-2 p-2 pt-4">
<PageContent class="flex flex-col gap-2 p-2 pt-4">
<div class="flex flex-col gap-2" bind:this={element}>
{#each PLATFORM_RELAYS as url (url)}
<Button
+2 -2
View File
@@ -22,10 +22,10 @@
<svelte:window bind:innerWidth={width} />
{#if width <= md}
<div class="ml-sai mt-sai mb-sai relative z-nav w-14 flex-shrink-0 bg-base-200 pt-4">
<div class="ml-sai mt-sai mb-sai relative z-nav w-14 flex-shrink-0 bg-base-200 pt-2">
<PrimaryNavSpaces />
</div>
<SecondaryNav class="!flex !min-h-0 !w-auto flex-grow pb-4">
<SecondaryNav class="!flex !w-auto flex-grow pb-16">
<SpaceMenu {url} />
</SecondaryNav>
{/if}
+90 -94
View File
@@ -216,104 +216,100 @@
<strong>Recent Activity</strong>
{/snippet}
{#snippet action()}
<div>
<button class="btn btn-neutral btn-sm btn-square" aria-label="Search" onclick={openSearch}>
<Icon size={4} icon={Magnifier} />
</button>
{#if showSearch}
<button class="fixed inset-0 z-feature" aria-label="Close search" onclick={closeSearch}
></button>
<div class="fixed cw top-0 right-0 z-feature p-2">
<div
class="card2 card2-sm bg-alt flex flex-col gap-2 shadow-md"
transition:fly={{y: -40, duration: 150}}>
<div class="flex justify-between">
<strong>Search</strong>
<Button onclick={clearSearch}>
<Icon icon={CloseCircle} />
</Button>
</div>
<label class="input input-sm input-bordered flex w-full items-center gap-2">
<Icon size={4} icon={Magnifier} />
<input
bind:this={searchInput}
bind:value={term}
class="min-w-0 grow"
type="text"
placeholder="Search this space..."
oninput={onInput} />
</label>
<div class="max-h-[65vh] overflow-y-auto">
{#if !term}
<p class="text-sm opacity-70">Search for content across this space.</p>
{:else if loading}
<p class="text-sm opacity-70">Searching...</p>
{:else if resultsByAge.size === 0}
<p class="text-sm opacity-70">No results found.</p>
{:else}
<div class="col-2">
{#each resultsByAge as [key, events] (key)}
<button class="btn btn-neutral btn-sm btn-square" aria-label="Search" onclick={openSearch}>
<Icon size={4} icon={Magnifier} />
</button>
{#if showSearch}
<button class="fixed inset-0 z-feature" aria-label="Close search" onclick={closeSearch}
></button>
<div class="fixed top-sai right-sai left-content z-feature p-2">
<div
class="card2 card2-sm bg-alt flex flex-col gap-2 shadow-md"
transition:fly={{y: -40, duration: 150}}>
<div class="flex justify-between">
<strong>Search</strong>
<Button onclick={clearSearch}>
<Icon icon={CloseCircle} />
</Button>
</div>
<label class="input input-sm input-bordered flex w-full items-center gap-2">
<Icon size={4} icon={Magnifier} />
<input
bind:this={searchInput}
bind:value={term}
class="min-w-0 grow"
type="text"
placeholder="Search this space..."
oninput={onInput} />
</label>
<div class="max-h-[65vh] overflow-y-auto">
{#if !term}
<p class="text-sm opacity-70">Search for content across this space.</p>
{:else if loading}
<p class="text-sm opacity-70">Searching...</p>
{:else if resultsByAge.size === 0}
<p class="text-sm opacity-70">No results found.</p>
{:else}
<div class="col-2">
{#each resultsByAge as [key, events] (key)}
<div class="col-2">
<p class="text-xs uppercase tracking-wide opacity-60">
{#if key === "day"}
Last 24 Hours
{:else if key === "week"}
Last 7 Days
{:else}
Older
{/if}
</p>
<div class="col-2">
<p class="text-xs uppercase tracking-wide opacity-60">
{#if key === "day"}
Last 24 Hours
{:else if key === "week"}
Last 7 Days
{:else}
Older
{/if}
</p>
<div class="col-2">
{#each events as event (event.id)}
<button
class="card2 bg-alt card2-sm col-2 transition-colors hover:bg-base-200 text-left"
onclick={() => onResultClick(event)}>
<p class="line-clamp-2 text-sm">
{event.content.trim() ||
getTagValue("title", event.tags) ||
"(No text content)"}
</p>
<div class="row-2 text-xs opacity-70">
<span>{getAgeLabel(event.created_at)}</span>
<span>{formatTimestampAsDate(event.created_at)}</span>
</div>
</button>
{/each}
</div>
{#each events as event (event.id)}
<button
class="card2 bg-alt card2-sm col-2 transition-colors hover:bg-base-200 text-left"
onclick={() => onResultClick(event)}>
<p class="line-clamp-2 text-sm">
{event.content.trim() ||
getTagValue("title", event.tags) ||
"(No text content)"}
</p>
<div class="row-2 text-xs opacity-70">
<span>{getAgeLabel(event.created_at)}</span>
<span>{formatTimestampAsDate(event.created_at)}</span>
</div>
</button>
{/each}
</div>
{/each}
</div>
{/if}
</div>
</div>
{/each}
</div>
{/if}
</div>
</div>
{/if}
</div>
</div>
{/if}
{/snippet}
</SpaceBar>
<div bind:this={element}>
<PageContent class="flex flex-col gap-2 p-2 pt-4">
{#if $recentActivity.length === 0}
<p class="flex flex-col items-center py-20 text-center">No recent activity found!</p>
{:else}
{#each $recentActivity.slice(0, limit) as { type, event, count = 0 } (event.id)}
{#if type === "message"}
<RecentConversation {url} {event} {count} />
{:else if event.kind === THREAD}
<ThreadItem {url} {event} />
{:else if event.kind === CLASSIFIED}
<ClassifiedItem {url} {event} />
{:else if event.kind === ZAP_GOAL}
<GoalItem {url} {event} />
{:else if event.kind === EVENT_TIME}
<CalendarEventItem {url} {event} />
{:else if event.kind === Poll}
<PollItem {url} {event} />
{:else}
<NoteItem {url} {event} />
{/if}
{/each}
{/if}
</PageContent>
</div>
<PageContent class="flex flex-col gap-2 p-2 pt-4" bind:element>
{#if $recentActivity.length === 0}
<p class="flex flex-col items-center py-20 text-center">No recent activity found!</p>
{:else}
{#each $recentActivity.slice(0, limit) as { type, event, count = 0 } (event.id)}
{#if type === "message"}
<RecentConversation {url} {event} {count} />
{:else if event.kind === THREAD}
<ThreadItem {url} {event} />
{:else if event.kind === CLASSIFIED}
<ClassifiedItem {url} {event} />
{:else if event.kind === ZAP_GOAL}
<GoalItem {url} {event} />
{:else if event.kind === EVENT_TIME}
<CalendarEventItem {url} {event} />
{:else if event.kind === Poll}
<PollItem {url} {event} />
{:else}
<NoteItem {url} {event} />
{/if}
{/each}
{/if}
</PageContent>
+2 -2
View File
@@ -8,8 +8,8 @@
import PageContent from "@lib/components/PageContent.svelte"
</script>
<Page class="cw-full">
<PageContent class="cw-full flex flex-col items-center gap-2 p-2 pt-4">
<Page>
<PageContent class="flex flex-col items-center gap-2 p-2 pt-4">
<PageHeader>
{#snippet title()}
<div>Create your own Space</div>