h8r4npp3p: Add the new-posts pill, feed list motion and app-wide reduced-motion switch-off
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import type { ReactNode, Ref } from "react";
|
||||
import { canDelete, type CardPost } from "@/lib/feed-model";
|
||||
import { Composer, type ComposerProps } from "./Composer";
|
||||
import { GrowButton } from "./Buttons";
|
||||
import { PostCard } from "./PostCard";
|
||||
|
||||
export type FeedStatus = "loading" | "ready" | "error";
|
||||
@@ -33,6 +34,24 @@ function Spinner() {
|
||||
return <span className="spinner" role="status" aria-label="Loading" />;
|
||||
}
|
||||
|
||||
/** Shimmer placeholder card shown while the next page loads. */
|
||||
function SkeletonCard() {
|
||||
return (
|
||||
<div className="feed-skel" role="status" aria-label="Loading more posts" data-testid="feed-skeleton">
|
||||
<div className="feed-skel-head">
|
||||
<span className="feed-skel-dot" />
|
||||
<span className="feed-skel-lines">
|
||||
<span className="feed-skel-line feed-skel-w40" />
|
||||
<span className="feed-skel-line feed-skel-w25" />
|
||||
</span>
|
||||
</div>
|
||||
<span className="feed-skel-line feed-skel-w100" />
|
||||
<span className="feed-skel-line feed-skel-w80" />
|
||||
<span className="feed-skel-media" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FeedPanel({ children, composer }: { children: ReactNode; composer?: ReactNode }) {
|
||||
return (
|
||||
<section className="tile panel feed" aria-labelledby="h-feed">
|
||||
@@ -69,16 +88,17 @@ export function FeedView(p: FeedViewProps) {
|
||||
<FeedPanel composer={p.composer ? <Composer {...p.composer} /> : null}>
|
||||
<div ref={p.listRef} className="feed-list panel-scroll fade-edges">
|
||||
{p.newCount > 0 ? (
|
||||
<button type="button" className="new-posts" onClick={p.onShowNew}>
|
||||
{p.newCount === 1 ? "1 new post" : `${p.newCount} new posts`}
|
||||
</button>
|
||||
<div className="feed-pill">
|
||||
<GrowButton label={p.newCount === 1 ? "1 new post" : `${p.newCount} new posts`} onClick={p.onShowNew} />
|
||||
</div>
|
||||
) : null}
|
||||
{p.posts.length === 0 ? (
|
||||
<p className="feed-message">No posts yet.</p>
|
||||
) : (
|
||||
p.posts.map((post) => <PostCard
|
||||
p.posts.map((post, i) => <PostCard
|
||||
key={post.key}
|
||||
post={post}
|
||||
index={i}
|
||||
now={p.now}
|
||||
onToggleLike={p.onToggleLike}
|
||||
likeBusy={p.likeBusy?.has(post.key)}
|
||||
@@ -96,11 +116,7 @@ export function FeedView(p: FeedViewProps) {
|
||||
<button type="button" onClick={p.onRetry}>Try again</button>
|
||||
</div>
|
||||
) : null}
|
||||
{p.loadingMore ? (
|
||||
<div className="feed-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : null}
|
||||
{p.loadingMore ? <SkeletonCard /> : null}
|
||||
<div ref={p.sentinelRef} className="sentinel" aria-hidden="true" />
|
||||
</div>
|
||||
</FeedPanel>
|
||||
|
||||
Reference in New Issue
Block a user