From dd7c15153e6ff86885c4e89a24b0ce262cd35fcd Mon Sep 17 00:00:00 2001 From: Coracle-Bot Date: Wed, 9 Sep 2026 20:53:25 +0000 Subject: [PATCH] Pair content-visibility with its render-ahead observer in one component --- src/app/components/ArticleItem.svelte | 5 +- src/app/components/CalendarEventItem.svelte | 5 +- src/app/components/ClassifiedItem.svelte | 5 +- src/app/components/GoalItem.svelte | 5 +- src/app/components/NoteCard.svelte | 2 +- src/app/components/NoteItem.svelte | 5 +- src/app/components/PeopleItem.svelte | 5 +- src/app/components/PollItem.svelte | 5 +- src/app/components/RecentConversation.svelte | 5 +- src/app/components/ReportItem.svelte | 5 +- src/app/components/ThreadBoardItem.svelte | 8 ++- src/app/components/ThreadItem.svelte | 5 +- src/lib/components/Cv.svelte | 58 ++++++++++++++++++++ src/lib/components/base.css | 2 + 14 files changed, 96 insertions(+), 24 deletions(-) create mode 100644 src/lib/components/Cv.svelte diff --git a/src/app/components/ArticleItem.svelte b/src/app/components/ArticleItem.svelte index ed75994f..184c2e01 100644 --- a/src/app/components/ArticleItem.svelte +++ b/src/app/components/ArticleItem.svelte @@ -4,6 +4,7 @@ import {getAddress} from "@welshman/util" import {Article} from "@welshman/domain" import Link from "@lib/components/Link.svelte" + import Cv from "@lib/components/Cv.svelte" import Content from "@app/components/Content.svelte" import ProfileLink from "@app/components/ProfileLink.svelte" import ArticleActions from "@app/components/ArticleActions.svelte" @@ -27,7 +28,7 @@ const image = $derived(article.image()) -
+ @@ -58,4 +59,4 @@
- + diff --git a/src/app/components/CalendarEventItem.svelte b/src/app/components/CalendarEventItem.svelte index 40b7cc8c..c12f15f1 100644 --- a/src/app/components/CalendarEventItem.svelte +++ b/src/app/components/CalendarEventItem.svelte @@ -2,6 +2,7 @@ import type {TrustedEvent} from "@welshman/util" import {getAddress, tagValue, tagSpec} from "@welshman/util" import Link from "@lib/components/Link.svelte" + import Cv from "@lib/components/Cv.svelte" import CalendarEventActions from "@app/components/CalendarEventActions.svelte" import type {FeedContext} from "@app/feeds" import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte" @@ -22,7 +23,7 @@ const h = $derived(tagValue(tagSpec("h"), event.tags)) - +
@@ -34,4 +35,4 @@
- +
diff --git a/src/app/components/ClassifiedItem.svelte b/src/app/components/ClassifiedItem.svelte index 604a8b2d..d8ba7a8f 100644 --- a/src/app/components/ClassifiedItem.svelte +++ b/src/app/components/ClassifiedItem.svelte @@ -4,6 +4,7 @@ import {getAddress} from "@welshman/util" import {Classified} from "@welshman/domain" import Link from "@lib/components/Link.svelte" + import Cv from "@lib/components/Cv.svelte" import CurrencySymbol from "@lib/components/CurrencySymbol.svelte" import {reader} from "@app/core" import ContentLinkBlock from "@app/components/ContentLinkBlock.svelte" @@ -31,7 +32,7 @@ const price = $derived(classified.price()) - + {#if title}
@@ -64,4 +65,4 @@
- +
diff --git a/src/app/components/GoalItem.svelte b/src/app/components/GoalItem.svelte index ec818aac..3429f778 100644 --- a/src/app/components/GoalItem.svelte +++ b/src/app/components/GoalItem.svelte @@ -2,6 +2,7 @@ import type {TrustedEvent} from "@welshman/util" import {ZapGoal} from "@welshman/domain" import Link from "@lib/components/Link.svelte" + import Cv from "@lib/components/Cv.svelte" import {reader} from "@app/core" import Content from "@app/components/Content.svelte" import ProfileLink from "@app/components/ProfileLink.svelte" @@ -28,7 +29,7 @@ const h = goal.room() - +

{title}

- +
diff --git a/src/app/components/NoteCard.svelte b/src/app/components/NoteCard.svelte index 1968a30c..e5a36afe 100644 --- a/src/app/components/NoteCard.svelte +++ b/src/app/components/NoteCard.svelte @@ -32,7 +32,7 @@ let muted = $state($isEventMuted(event)) -
+
{#if muted}
diff --git a/src/app/components/NoteItem.svelte b/src/app/components/NoteItem.svelte index 67c621c8..10bd4248 100644 --- a/src/app/components/NoteItem.svelte +++ b/src/app/components/NoteItem.svelte @@ -6,6 +6,7 @@ import SmileCircle from "@assets/icons/smile-circle.svg?dataurl" import Icon from "@lib/components/Icon.svelte" import EmojiButton from "@lib/components/EmojiButton.svelte" + import Cv from "@lib/components/Cv.svelte" import NoteContent from "@app/components/NoteContent.svelte" import {publishReaction, retractReaction} from "@app/reactions" import NoteCard from "@app/components/NoteCard.svelte" @@ -33,7 +34,7 @@ const onEmoji = (emoji: NativeEmoji) => createReaction({content: emoji.unicode, tags: []}) - +
{@render children?.()}
-
+ diff --git a/src/app/components/PeopleItem.svelte b/src/app/components/PeopleItem.svelte index 2ef83932..8f71d675 100644 --- a/src/app/components/PeopleItem.svelte +++ b/src/app/components/PeopleItem.svelte @@ -2,6 +2,7 @@ import UserCircle from "@assets/icons/user-circle.svg?dataurl" import Icon from "@lib/components/Icon.svelte" import Link from "@lib/components/Link.svelte" + import Cv from "@lib/components/Cv.svelte" import Profile from "@app/components/Profile.svelte" import ProfileAbout from "@app/components/ProfileAbout.svelte" import ProfileBadges from "@app/components/ProfileBadges.svelte" @@ -15,7 +16,7 @@ const {pubkey, url}: Props = $props() -
+
@@ -29,4 +30,4 @@ View Profile -
+
diff --git a/src/app/components/PollItem.svelte b/src/app/components/PollItem.svelte index 379ff4d2..1a41d2a0 100644 --- a/src/app/components/PollItem.svelte +++ b/src/app/components/PollItem.svelte @@ -2,6 +2,7 @@ import type {TrustedEvent} from "@welshman/util" import {tagSpec, tagValue} from "@welshman/util" import Link from "@lib/components/Link.svelte" + import Cv from "@lib/components/Cv.svelte" import NoteContent from "@app/components/NoteContent.svelte" import PollActions from "@app/components/PollActions.svelte" import type {FeedContext} from "@app/feeds" @@ -22,7 +23,7 @@ const h = tagValue(tagSpec("h"), event.tags) - +
@@ -34,4 +35,4 @@
- +
diff --git a/src/app/components/RecentConversation.svelte b/src/app/components/RecentConversation.svelte index b5a93d59..6268ce79 100644 --- a/src/app/components/RecentConversation.svelte +++ b/src/app/components/RecentConversation.svelte @@ -7,6 +7,7 @@ import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import Icon from "@lib/components/Icon.svelte" import Button from "@lib/components/Button.svelte" + import Cv from "@lib/components/Cv.svelte" import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte" import ProfileCircle from "@app/components/ProfileCircle.svelte" import RoomNameWithImage from "@app/components/RoomNameWithImage.svelte" @@ -25,7 +26,7 @@ const onClick = () => navigate(h ? makeRoomPath(url, h) : makeSpaceChatPath(url)) -
- + diff --git a/src/app/components/ReportItem.svelte b/src/app/components/ReportItem.svelte index eadc05df..c580a8ac 100644 --- a/src/app/components/ReportItem.svelte +++ b/src/app/components/ReportItem.svelte @@ -4,6 +4,7 @@ import {LOCAL_RELAY_URL} from "@welshman/net" import type {TrustedEvent} from "@welshman/util" import Card from "@lib/components/Card.svelte" + import Cv from "@lib/components/Cv.svelte" import Button from "@lib/components/Button.svelte" import Profile from "@app/components/Profile.svelte" import ProfileName from "@app/components/ProfileName.svelte" @@ -36,7 +37,7 @@ } - +
@@ -80,4 +81,4 @@ {/if}
- + diff --git a/src/app/components/ThreadBoardItem.svelte b/src/app/components/ThreadBoardItem.svelte index 1c070417..68141f05 100644 --- a/src/app/components/ThreadBoardItem.svelte +++ b/src/app/components/ThreadBoardItem.svelte @@ -5,6 +5,7 @@ import type {TrustedEvent} from "@welshman/util" import {COMMENT, tagSpec, tagValue} from "@welshman/util" import Link from "@lib/components/Link.svelte" + import Cv from "@lib/components/Cv.svelte" import ProfileCircle from "@app/components/ProfileCircle.svelte" import ProfileName from "@app/components/ProfileName.svelte" import UnreadDot from "@app/components/UnreadDot.svelte" @@ -30,9 +31,10 @@ {#if stacked} - + class="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">

{title || "Untitled thread"}

@@ -46,7 +48,7 @@ {replyCount} {replyCount === 1 ? "reply" : "replies"} {formatTimestamp(lastActive)}
- +
{:else} - + {#if title}
@@ -49,4 +50,4 @@
- +
diff --git a/src/lib/components/Cv.svelte b/src/lib/components/Cv.svelte new file mode 100644 index 00000000..3340d0ac --- /dev/null +++ b/src/lib/components/Cv.svelte @@ -0,0 +1,58 @@ + + + + +{#if typeof tag === "string"} + + {@render children?.()} + +{:else} + {@const Host = tag} + + {@render children?.()} + +{/if} diff --git a/src/lib/components/base.css b/src/lib/components/base.css index 4adb1e4c..2b631bc6 100644 --- a/src/lib/components/base.css +++ b/src/lib/components/base.css @@ -99,6 +99,8 @@ @utility superheading { @apply font-heading text-center text-4xl font-extrabold; } +/* Applied by Cv.svelte, which pairs it with the observer that paints ahead of a fast scroll. + Nothing else should reach for it. */ @utility cv { content-visibility: auto; }