Replace the compact ExternalPostCard with a full feed-style layout
matching the /bluesky feed when viewing individual Bluesky posts.
Shows large avatar, full text, image/link embeds, and interactive
action buttons (comment, repost, react, share) for a thread-like feel.
Thread hideImage prop through LinkEmbed -> BlueskyEmbed -> ExternalPostCard
so images are suppressed in the compose dialog preview, matching the
behavior of normal post reply indicators.
Clicking the avatar, display name, or handle now navigates to
/i/{bsky.app/profile/handle} instead of the post's /i/ page.
Clicks stop propagation so the card-level navigation still works.
ReplyComposeModal now renders a LinkPreview card when the event is a URL,
so users see what they're commenting on. Previously the preview was skipped
entirely for URL-based comments.
Pass post.likeCount to ExternalReactionButton via new count prop so like
counts display from the Bluesky API. Comment button now opens the
ReplyComposeModal with the post URL instead of navigating away.
The Bluesky page had a broken inline reaction that just published '+' with
no emoji picker. The /i/ page had the full implementation with Popover,
QuickReactMenu, hover-to-open, and custom emoji support. Extracted the
reaction logic into a reusable ExternalReactionButton component and wired
it into both pages, removing ~230 lines of duplicated/inferior code.
Integrate useWikipediaSearch and useArchiveSearch into both the desktop
sidebar dropdown (ProfileSearchDropdown) and mobile bottom-nav sheet
(MobileSearchSheet). At most 1 result from each source is shown, always
positioned after Nostr profiles to preserve profile precedence. Keyboard
navigation indices updated to include the new items.
Detect Wikipedia URLs and render a custom WikipediaArticleHeader with hero
image, article title, Wikidata description, expandable extract, and a
Read on Wikipedia footer link. Also uses the Wikipedia API for accurate
page titles in the header bar and SEO metadata, and navigates back to
/wikipedia on the back button.
Replace dark:prose-invert with text-foreground on all prose containers so
markdown content matches the active theme colors. Also bump article preview
text size from text-sm to text-[15px] to match note content in the feed.
Avoid recreating style objects on every render in MobileBottomNav,
FloatingComposeButton, and MobileDrawer by extracting them to
module-level constants.
- Remove STICKY_HEADER_CLASS + backdrop-blur from TagFeedPage, ListDetailPage,
RelayPage, and DomainFeedPage to match the arc-based header style
- Migrate ListDetailPage tab bar to SubHeaderBar
- Migrate ThemesPage header to use shared PageHeader component
- Extract --top-bar-height and --bottom-nav-height CSS custom properties in
index.css, replacing hardcoded 2.5rem/2.75rem in all calc() expressions
- Document MobileDrawer DRAWER_BG_WIDTH constant (300px + 36px arc overhang)
- Remove unused STICKY_HEADER_CLASS import from ProfilePage
Consolidate duplicated patterns from iterative development into reusable
components:
- ArcBackground: shared SVG arc shape used by SubHeaderBar, MobileTopBar,
and MobileBottomNav (eliminates 3x duplicated SVG paths and magic numbers)
- PlanetButton: extracted FAB planet SVG with useId()-scoped gradient IDs
to prevent collisions if multiple instances ever coexist
- PageHeader: standardized back+icon+title header used across 10 pages
Net reduction of ~144 lines with no behavioral changes.
Create SubHeaderBar component that draws the tab background and
decorative arc as one combined SVG path (rect + curve). Replace all 9
sub-header instances across Feed, Search, Notifications, Videos, Vines,
Photos, Themes, Events, and Books pages.
Also update MobileTopBar to draw its background as a unified SVG shape
(rect-only when sub-header present, rect+arc when standalone).
Eliminates the sub-pixel transparent seam between bg-background/80
containers and their separate SVG arc overlays.