The Vines page uses an internal snap-scroll container instead of window
scroll, so useScrollDirection (which listened to window.scrollY) never
detected any scroll movement. Add a scrollContainer option to
LayoutOptions so pages with custom scroll containers can communicate
the element to MobileBottomNav, which passes it to useScrollDirection.
Delete MobileBottomNav component and all related code including the
noBottomSpacer layout option, bottom nav height spacer, and CSS
calculations that accounted for the bottom nav height.
Add fabIcon prop to LayoutOptions and FloatingComposeButton so pages can
override the default Plus icon. The Themes page now shows a Pencil icon
on its FAB to indicate editing/customizing rather than composing.
Reverts 6abe9fa and the fabHidden parts of 7f26beb. The FAB is now
always visible when showFAB is true, restoring sticky positioning
inside the center column. Removes IntersectionObserver logic from
Feed.tsx, fabHidden state from LayoutStore, and the useSetFabHidden
hook.
The cleanup guard in useLayoutOptions compared store.getSnapshot() (a LayoutSnapshot spread copy) against prev.current (the original LayoutOptions reference), which are always different objects. The guard was never true, so store.reset() never fired on unmount and the ProfileRightSidebar leaked to other pages. Added getOptions() to expose the raw options reference for a correct identity comparison.
Use IntersectionObserver on the ComposeBox wrapper in Feed.tsx to track
its visibility. When visible, hide the FAB to avoid redundancy. When the
user scrolls past the compose area, the FAB smoothly fades in with an
upward slide animation. Extends LayoutStore with fabHidden state that
is part of the snapshot so useSyncExternalStore triggers re-renders.
Replace the custom WebxdcFeedPage with KindFeedPage, powered by
a new tagFilters option on useFeed/Feed/KindFeedPage. The webxdc
page now uses the same follows/global tabs, pull-to-refresh, and
NoteCard rendering as every other feed.
- useFeed: accept optional tagFilters (e.g. { '#m': [...] })
- Feed/KindFeedPage: pass tagFilters through
- FloatingComposeButton: accept onFabClick callback override
- LayoutOptions: add onFabClick for custom FAB behavior
- Remove useWebxdcFeed (no longer needed)
- Remove ScopedThemeColumns, scopedThemeTokens from LayoutContext and MainLayout
- Profile page now temporarily overrides :root CSS vars with the visited user's theme
- On navigation away, user's own theme is restored via effect cleanup
- Entire page (sidebar, center, right) uses the profile theme
- Removed all display:contents and background extension hacks
- Added scopedThemeTokens to LayoutOptions
- MainLayout wraps center + right columns in ScopedTheme (display:contents)
- Profile page passes theme tokens via useLayoutOptions instead of local wrapper
- Center column and ProfileRightSidebar use bg-background for scoped theme fill
- Removed ProfileThemeWrapper component (no longer needed)
- FloatingComposeButton accepts kind prop: kind=1 opens compose dialog, others show 'Coming soon'
- FAB positioned sticky bottom-right within center column (visible on all screen sizes)
- Center column gets bottom padding (pb-24) to account for FAB obstruction
- LayoutContext extended with fabKind option passed through layout system
- Home feed uses kind=1, KindFeedPage passes its kind, StreamsFeedPage uses 30311
The useLayoutOptions cleanup effect was unconditionally resetting the
layout store on unmount. During page transitions, React runs the new
page's render (which sets the store) before the old page's cleanup
effect fires. The unconditional reset would clobber the new page's
options, causing showFAB to be wiped.
Now the cleanup only resets if the store still holds this component's
options, preventing it from interfering with the incoming page.
MainLayout was rendered inside each page component, causing the entire
layout (sidebar, mobile nav, drawer) to be destroyed and recreated on
every route change. This made navigations feel like full page refreshes.
Restructured to use a React Router layout route with <Outlet />, so
MainLayout persists across navigations and only the page content swaps.
Pages that need custom layout options (showFAB, rightSidebar, etc.) use
the new useLayoutOptions hook to configure the persistent layout.