Mobile UX: fixed bottom nav, compact header, less cramped cards
- App-shell layout (height:100dvh, only main scrolls) so the bottom nav is a natural flex child and never disappears regardless of browser chrome show/hide behaviour - Bottom nav reduced from h-16 to h-14, icons from 20px to 18px, labels from 10px to 9px — slimmer bar, still readable - Header: min-w-0 on search prevents horizontal overflow; user/sign-out hidden on mobile (accessible via Settings); logo shortened to "YT" on mobile; px-3 / h-12 on mobile instead of px-4 / h-14 - Grid card descriptions hidden on mobile (hidden sm:block) — reduces height cramping in the 2-column feed - scrollToTop() utility replaces window.scrollTo so pagination still scrolls to top within the new scroll container Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
followDiscovery, dismissDiscovery, dismissDiscoveryVideo, refreshDiscovery,
|
||||
} from "../api";
|
||||
import VideoCard from "../components/VideoCard";
|
||||
import { scrollToTop } from "../utils/scroll";
|
||||
|
||||
const PAGE_SIZE = 50;
|
||||
|
||||
@@ -305,7 +306,7 @@ export default function DiscoveryPage() {
|
||||
</div>
|
||||
<div className="flex items-center justify-center gap-3 pt-2">
|
||||
<button
|
||||
onClick={() => { setChannelPage(p => p - 1); window.scrollTo({ top: 0, behavior: "smooth" }); }}
|
||||
onClick={() => { setChannelPage(p => p - 1); scrollToTop(); }}
|
||||
disabled={channelPage === 0}
|
||||
className="px-4 py-2 rounded-lg bg-zinc-800 text-zinc-300 text-sm font-medium hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
@@ -313,7 +314,7 @@ export default function DiscoveryPage() {
|
||||
</button>
|
||||
<span className="text-zinc-500 text-sm tabular-nums">Page {channelPage + 1}</span>
|
||||
<button
|
||||
onClick={() => { setChannelPage(p => p + 1); window.scrollTo({ top: 0, behavior: "smooth" }); }}
|
||||
onClick={() => { setChannelPage(p => p + 1); scrollToTop(); }}
|
||||
disabled={!hasNextChannelPage}
|
||||
className="px-4 py-2 rounded-lg bg-zinc-800 text-zinc-300 text-sm font-medium hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
@@ -334,7 +335,7 @@ export default function DiscoveryPage() {
|
||||
</div>
|
||||
<div className="flex items-center justify-center gap-3 pt-2">
|
||||
<button
|
||||
onClick={() => { setVideoPage(p => p - 1); window.scrollTo({ top: 0, behavior: "smooth" }); }}
|
||||
onClick={() => { setVideoPage(p => p - 1); scrollToTop(); }}
|
||||
disabled={videoPage === 0}
|
||||
className="px-4 py-2 rounded-lg bg-zinc-800 text-zinc-300 text-sm font-medium hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
@@ -342,7 +343,7 @@ export default function DiscoveryPage() {
|
||||
</button>
|
||||
<span className="text-zinc-500 text-sm tabular-nums">Page {videoPage + 1}</span>
|
||||
<button
|
||||
onClick={() => { setVideoPage(p => p + 1); window.scrollTo({ top: 0, behavior: "smooth" }); }}
|
||||
onClick={() => { setVideoPage(p => p + 1); scrollToTop(); }}
|
||||
disabled={!hasNextVideoPage}
|
||||
className="px-4 py-2 rounded-lg bg-zinc-800 text-zinc-300 text-sm font-medium hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState } from "react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getHistory } from "../api";
|
||||
import VideoCard from "../components/VideoCard";
|
||||
import { scrollToTop } from "../utils/scroll";
|
||||
|
||||
const PAGE_SIZE = 25;
|
||||
|
||||
@@ -40,7 +41,7 @@ export default function History() {
|
||||
</div>
|
||||
<div className="flex items-center justify-center gap-3 pt-2">
|
||||
<button
|
||||
onClick={() => { setPage(p => p - 1); window.scrollTo({ top: 0, behavior: "smooth" }); }}
|
||||
onClick={() => { setPage(p => p - 1); scrollToTop(); }}
|
||||
disabled={page === 0}
|
||||
className="px-4 py-2 rounded-lg bg-zinc-800 text-zinc-300 text-sm font-medium hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
@@ -48,7 +49,7 @@ export default function History() {
|
||||
</button>
|
||||
<span className="text-zinc-500 text-sm tabular-nums">Page {page + 1}</span>
|
||||
<button
|
||||
onClick={() => { setPage(p => p + 1); window.scrollTo({ top: 0, behavior: "smooth" }); }}
|
||||
onClick={() => { setPage(p => p + 1); scrollToTop(); }}
|
||||
disabled={!hasNext}
|
||||
className="px-4 py-2 rounded-lg bg-zinc-800 text-zinc-300 text-sm font-medium hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState, useMemo } from "react";
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { homeFeed, surpriseMe, getSettings, updateSettings, getChannels, markChannelsSeen } from "../api";
|
||||
import VideoCard from "../components/VideoCard";
|
||||
import { scrollToTop } from "../utils/scroll";
|
||||
|
||||
const PAGE_SIZE = 25;
|
||||
|
||||
@@ -95,7 +96,7 @@ export default function Home() {
|
||||
setShuffleKey(k => k + 1);
|
||||
setPage(0);
|
||||
setDismissed(new Set());
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
scrollToTop();
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -235,7 +236,7 @@ export default function Home() {
|
||||
)}
|
||||
<div className="flex items-center justify-center gap-3 pt-2">
|
||||
<button
|
||||
onClick={() => { setPage(p => p - 1); window.scrollTo({ top: 0, behavior: "smooth" }); }}
|
||||
onClick={() => { setPage(p => p - 1); scrollToTop(); }}
|
||||
disabled={page === 0}
|
||||
className="px-4 py-2 rounded-lg bg-zinc-800 text-zinc-300 text-sm font-medium hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
@@ -243,7 +244,7 @@ export default function Home() {
|
||||
</button>
|
||||
<span className="text-zinc-500 text-sm tabular-nums">Page {page + 1}</span>
|
||||
<button
|
||||
onClick={() => { setPage(p => p + 1); window.scrollTo({ top: 0, behavior: "smooth" }); }}
|
||||
onClick={() => { setPage(p => p + 1); scrollToTop(); }}
|
||||
disabled={!hasNextPage}
|
||||
className="px-4 py-2 rounded-lg bg-zinc-800 text-zinc-300 text-sm font-medium hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user