Switch the thread board to the table when the board is wide enough, not the page
This commit is contained in:
parent
057f0bc2bb
commit
3739ea7119
5 changed files with 33 additions and 48 deletions
|
|
@ -1611,8 +1611,8 @@ Threads indicator is as actionable on a phone as it is on a desktop.
|
||||||
|
|
||||||
Acceptance:
|
Acceptance:
|
||||||
|
|
||||||
- The thread list below the md breakpoint is a list of links rather than a
|
- The thread list in a board too narrow for the table is a list of links rather
|
||||||
table, and alice's thread carries a dot there; bob's own does not.
|
than a table, and alice's thread carries a dot there; bob's own does not.
|
||||||
|
|
||||||
### US-114 — See which listings are unread
|
### US-114 — See which listings are unread
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -626,8 +626,9 @@ test("US-113 see which threads are unread on a phone", async ({seed, as}) => {
|
||||||
|
|
||||||
const space = scenario.space("space")
|
const space = scenario.space("space")
|
||||||
|
|
||||||
// ThreadBoard swaps its table for a list of links below tailwind's md breakpoint, and the two
|
// ThreadBoard swaps its table for a list of links when the board is too narrow for the table,
|
||||||
// branches render the thread separately, so a dot on one says nothing about the other.
|
// and the two branches render the thread separately, so a dot on one says nothing about the
|
||||||
|
// other.
|
||||||
const bob = await as(users.bob, `${spacePath(space.url)}/threads`, {
|
const bob = await as(users.bob, `${spacePath(space.url)}/threads`, {
|
||||||
context: {viewport: {width: 390, height: 844}, hasTouch: true},
|
context: {viewport: {width: 390, height: 844}, hasTouch: true},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import Add from "@assets/icons/add.svg?dataurl"
|
import Add from "@assets/icons/add.svg?dataurl"
|
||||||
import {matchMd} from "@lib/theme"
|
|
||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import Button from "@lib/components/Button.svelte"
|
import Button from "@lib/components/Button.svelte"
|
||||||
import RoomNameWithImage from "@app/components/RoomNameWithImage.svelte"
|
import RoomNameWithImage from "@app/components/RoomNameWithImage.svelte"
|
||||||
|
|
@ -19,10 +18,12 @@
|
||||||
|
|
||||||
const {url, h, threads, context}: Props = $props()
|
const {url, h, threads, context}: Props = $props()
|
||||||
|
|
||||||
|
let width = $state(0)
|
||||||
|
|
||||||
const createThread = () => pushModal(ThreadCreate, {url, h})
|
const createThread = () => pushModal(ThreadCreate, {url, h})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="card card-flat p-0">
|
<section bind:clientWidth={width} class="card card-flat p-0">
|
||||||
<header
|
<header
|
||||||
class="flex items-center justify-between gap-2 border-b border-solid border-line px-4 py-3">
|
class="flex items-center justify-between gap-2 border-b border-solid border-line px-4 py-3">
|
||||||
<h2 class="text-lg">
|
<h2 class="text-lg">
|
||||||
|
|
@ -45,9 +46,10 @@
|
||||||
</header>
|
</header>
|
||||||
{#if threads.length === 0}
|
{#if threads.length === 0}
|
||||||
<p class="text-content-muted p-4 text-sm">No topics yet.</p>
|
<p class="text-content-muted p-4 text-sm">No topics yet.</p>
|
||||||
{:else if $matchMd}
|
{:else}
|
||||||
<div class="scroll-container overflow-x-auto pb-4">
|
<div class="pb-4">
|
||||||
<table class="w-full min-w-[640px] border-collapse">
|
{#if width >= 640}
|
||||||
|
<table class="w-full border-collapse">
|
||||||
<thead
|
<thead
|
||||||
class="border-b border-solid border-line bg-surface-less text-xs font-bold uppercase tracking-wide text-content-muted">
|
class="border-b border-solid border-line bg-surface-less text-xs font-bold uppercase tracking-wide text-content-muted">
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -63,12 +65,11 @@
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
|
||||||
{:else}
|
{:else}
|
||||||
<div class="pb-4">
|
|
||||||
{#each threads as event (event.id)}
|
{#each threads as event (event.id)}
|
||||||
<ThreadBoardItem mobile {url} {event} {context} />
|
<ThreadBoardItem stacked {url} {event} {context} />
|
||||||
{/each}
|
{/each}
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,10 @@
|
||||||
url: string
|
url: string
|
||||||
event: TrustedEvent
|
event: TrustedEvent
|
||||||
context: FeedContext
|
context: FeedContext
|
||||||
mobile?: boolean
|
stacked?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const {url, event, context, mobile = false}: Props = $props()
|
const {url, event, context, stacked = false}: Props = $props()
|
||||||
|
|
||||||
const related = context.related(event)
|
const related = context.related(event)
|
||||||
const replies = derived(related, $related => filter(spec({kind: COMMENT}), $related))
|
const replies = derived(related, $related => filter(spec({kind: COMMENT}), $related))
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
const onClick = () => navigate(path)
|
const onClick = () => navigate(path)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if mobile}
|
{#if stacked}
|
||||||
<Link
|
<Link
|
||||||
href={path}
|
href={path}
|
||||||
class="cv hover:bg-surface-less flex w-full flex-col gap-2 border-b border-solid border-line px-4 py-3 text-left text-sm transition-colors">
|
class="cv hover:bg-surface-less flex w-full flex-col gap-2 border-b border-solid border-line px-4 py-3 text-left text-sm transition-colors">
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
import theme from "tailwindcss/defaultTheme"
|
|
||||||
import {readable} from "svelte/store"
|
|
||||||
import type {Readable} from "svelte/store"
|
|
||||||
|
|
||||||
export const matchWidth = (query: string): Readable<boolean> =>
|
|
||||||
readable(typeof window !== "undefined" && window.matchMedia(query).matches, set => {
|
|
||||||
const mq = window.matchMedia(query)
|
|
||||||
|
|
||||||
const onChange = () => set(mq.matches)
|
|
||||||
|
|
||||||
onChange()
|
|
||||||
mq.addEventListener("change", onChange)
|
|
||||||
|
|
||||||
return () => mq.removeEventListener("change", onChange)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const matchMd = matchWidth(`(min-width: ${theme.screens.md})`)
|
|
||||||
Loading…
Reference in a new issue