From fe39831ada9e074a94f99b84579b128f5fb28bd4 Mon Sep 17 00:00:00 2001 From: kikootwo Date: Wed, 4 Feb 2026 19:50:39 -0500 Subject: [PATCH] Add square cover toggle and UI support Introduce a SquareCoversToggle component and wire cover-aspect switching throughout the app. PreferencesContext now stores and persists a new squareCovers flag (with cross-tab sync), and pages (Home, Search) expose the toggle and pass the squareCovers prop to AudiobookGrid/AudiobookCard. AudiobookCard/Grid and skeletons were updated to respect square vs 2:3 aspect ratios and include smoother transitions. Also update app icons/manifest references to RMAB_1024x1024_ICON.png and make header/branding responsive (truncate titles, adjust version badge placement and logo usage). Minor UI/UX tweaks added for accessibility and visual polish. --- public/RMAB_1024x1024_ICON.png | Bin 0 -> 38553 bytes public/manifest.json | 2 +- src/app/layout.tsx | 2 +- src/app/page.tsx | 15 +++-- src/app/search/page.tsx | 11 ++-- src/components/audiobooks/AudiobookCard.tsx | 8 ++- src/components/audiobooks/AudiobookGrid.tsx | 15 +++-- src/components/layout/Header.tsx | 25 +++++--- src/components/ui/SquareCoversToggle.tsx | 60 ++++++++++++++++++++ src/contexts/PreferencesContext.tsx | 28 ++++++++- 10 files changed, 138 insertions(+), 28 deletions(-) create mode 100644 public/RMAB_1024x1024_ICON.png create mode 100644 src/components/ui/SquareCoversToggle.tsx diff --git a/public/RMAB_1024x1024_ICON.png b/public/RMAB_1024x1024_ICON.png new file mode 100644 index 0000000000000000000000000000000000000000..73c5dd7c3b5257721556339db994e484a2677856 GIT binary patch literal 38553 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 C8jzX* literal 0 HcmV?d00001 diff --git a/public/manifest.json b/public/manifest.json index f9dd91c..efd2c66 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -8,7 +8,7 @@ "theme_color": "#1e3a5f", "icons": [ { - "src": "/RMAB_1024x1024.png", + "src": "/RMAB_1024x1024_ICON.png", "sizes": "1024x1024", "type": "image/png", "purpose": "any maskable" diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 468ac29..cdfcfe4 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -30,7 +30,7 @@ export const metadata: Metadata = { ], shortcut: "/rmab_icon.ico", apple: [ - { url: "/RMAB_1024x1024.png", sizes: "1024x1024", type: "image/png" }, + { url: "/RMAB_1024x1024_ICON.png", sizes: "1024x1024", type: "image/png" }, ], }, appleWebApp: { diff --git a/src/app/page.tsx b/src/app/page.tsx index d1abd9f..b760dc1 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -12,12 +12,13 @@ import { useAudiobooks } from '@/lib/hooks/useAudiobooks'; import { ProtectedRoute } from '@/components/auth/ProtectedRoute'; import { StickyPagination } from '@/components/ui/StickyPagination'; import { CardSizeControls } from '@/components/ui/CardSizeControls'; +import { SquareCoversToggle } from '@/components/ui/SquareCoversToggle'; import { usePreferences } from '@/contexts/PreferencesContext'; export default function HomePage() { const [popularPage, setPopularPage] = useState(1); const [newReleasesPage, setNewReleasesPage] = useState(1); - const { cardSize, setCardSize } = usePreferences(); + const { cardSize, setCardSize, squareCovers, setSquareCovers } = usePreferences(); // Refs for auto-scrolling to section tops const popularSectionRef = useRef(null); @@ -62,10 +63,11 @@ export default function HomePage() {
-

+

Popular Audiobooks

-
+
+
@@ -89,6 +91,7 @@ export default function HomePage() { isLoading={loadingPopular} emptyMessage="No popular audiobooks available" cardSize={cardSize} + squareCovers={squareCovers} /> )}
@@ -101,10 +104,11 @@ export default function HomePage() {
-

+

New Releases

-
+
+
@@ -128,6 +132,7 @@ export default function HomePage() { isLoading={loadingNewReleases} emptyMessage="No new releases available" cardSize={cardSize} + squareCovers={squareCovers} /> )}
diff --git a/src/app/search/page.tsx b/src/app/search/page.tsx index 8852f5c..d904291 100644 --- a/src/app/search/page.tsx +++ b/src/app/search/page.tsx @@ -11,13 +11,14 @@ import { AudiobookGrid } from '@/components/audiobooks/AudiobookGrid'; import { useSearch } from '@/lib/hooks/useAudiobooks'; import { ProtectedRoute } from '@/components/auth/ProtectedRoute'; import { CardSizeControls } from '@/components/ui/CardSizeControls'; +import { SquareCoversToggle } from '@/components/ui/SquareCoversToggle'; import { usePreferences } from '@/contexts/PreferencesContext'; export default function SearchPage() { const [query, setQuery] = useState(''); const [debouncedQuery, setDebouncedQuery] = useState(''); const [page, setPage] = useState(1); - const { cardSize, setCardSize } = usePreferences(); + const { cardSize, setCardSize, squareCovers, setSquareCovers } = usePreferences(); // Debounce search query useEffect(() => { @@ -109,15 +110,16 @@ export default function SearchPage() {
-

+

Search Results

{!isLoading && totalResults > 0 && ( - + ({totalResults.toLocaleString()} result{totalResults !== 1 ? 's' : ''}) )} -
+
+
@@ -130,6 +132,7 @@ export default function SearchPage() { isLoading={!!(isLoading && page === 1)} emptyMessage={`No results found for "${debouncedQuery}"`} cardSize={cardSize} + squareCovers={squareCovers} /> {/* Load More */} diff --git a/src/components/audiobooks/AudiobookCard.tsx b/src/components/audiobooks/AudiobookCard.tsx index 8d38a16..5d8675e 100644 --- a/src/components/audiobooks/AudiobookCard.tsx +++ b/src/components/audiobooks/AudiobookCard.tsx @@ -19,6 +19,7 @@ interface AudiobookCardProps { isRequested?: boolean; requestStatus?: string; onRequestSuccess?: () => void; + squareCovers?: boolean; } export function AudiobookCard({ @@ -26,6 +27,7 @@ export function AudiobookCard({ isRequested = false, requestStatus, onRequestSuccess, + squareCovers = false, }: AudiobookCardProps) { const { user } = useAuth(); const { createRequest, isLoading } = useCreateRequest(); @@ -59,10 +61,12 @@ export function AudiobookCard({ return ( <> -
+
{/* Cover Art - Clickable */}
setShowModal(true)} > {audiobook.coverArtUrl ? ( diff --git a/src/components/audiobooks/AudiobookGrid.tsx b/src/components/audiobooks/AudiobookGrid.tsx index 2599ebb..4c671b3 100644 --- a/src/components/audiobooks/AudiobookGrid.tsx +++ b/src/components/audiobooks/AudiobookGrid.tsx @@ -15,6 +15,7 @@ interface AudiobookGridProps { emptyMessage?: string; onRequestSuccess?: () => void; cardSize?: number; // 1-9, default 5 + squareCovers?: boolean; // true = square (1:1), false = rectangle (2:3) } // Helper function to get grid classes based on card size @@ -41,6 +42,7 @@ export function AudiobookGrid({ emptyMessage = 'No audiobooks found', onRequestSuccess, cardSize = 5, + squareCovers = false, }: AudiobookGridProps) { const gridClasses = getGridClasses(cardSize); @@ -48,7 +50,7 @@ export function AudiobookGrid({ return (
{Array.from({ length: 8 }).map((_, i) => ( - + ))}
); @@ -76,23 +78,26 @@ export function AudiobookGrid({ } return ( -
+
{audiobooks.map((audiobook) => ( ))}
); } -function SkeletonCard() { +function SkeletonCard({ squareCovers = false }: { squareCovers?: boolean }) { return ( -
+
{/* Cover Art Skeleton */} -
+
{/* Content Skeleton */}
diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index 1210e9f..b3f172b 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -118,18 +118,21 @@ export function Header() {
{/* Logo and Version Badge */} -
- +
+ ReadMeABook Logo - + ReadMeABook - + {/* Hide version badge on mobile to prevent overlap */} +
+ +
{/* Desktop Navigation */} @@ -203,7 +206,7 @@ export function Header() { {user ? ( -
+
diff --git a/src/components/ui/SquareCoversToggle.tsx b/src/components/ui/SquareCoversToggle.tsx new file mode 100644 index 0000000..05244b8 --- /dev/null +++ b/src/components/ui/SquareCoversToggle.tsx @@ -0,0 +1,60 @@ +/** + * Component: Square Covers Toggle + * Documentation: UI toggle for switching between square (1:1) and rectangle (2:3) cover aspect ratios + */ + +'use client'; + +import React from 'react'; + +interface SquareCoversToggleProps { + enabled: boolean; + onToggle: (enabled: boolean) => void; +} + +export function SquareCoversToggle({ enabled, onToggle }: SquareCoversToggleProps) { + return ( + + ); +} diff --git a/src/contexts/PreferencesContext.tsx b/src/contexts/PreferencesContext.tsx index 540068c..e7325bd 100644 --- a/src/contexts/PreferencesContext.tsx +++ b/src/contexts/PreferencesContext.tsx @@ -9,23 +9,28 @@ import React, { createContext, useContext, useState, useEffect, ReactNode } from interface Preferences { cardSize: number; // 1-9, default 5 + squareCovers: boolean; // true = square (1:1), false = rectangle (2:3) } interface PreferencesContextType { cardSize: number; setCardSize: (size: number) => void; + squareCovers: boolean; + setSquareCovers: (enabled: boolean) => void; } const PreferencesContext = createContext(undefined); const DEFAULT_PREFERENCES: Preferences = { cardSize: 5, + squareCovers: false, }; const STORAGE_KEY = 'preferences'; export function PreferencesProvider({ children }: { children: ReactNode }) { const [cardSize, setCardSizeState] = useState(DEFAULT_PREFERENCES.cardSize); + const [squareCovers, setSquareCoversState] = useState(DEFAULT_PREFERENCES.squareCovers); // Load preferences from localStorage on mount useEffect(() => { @@ -42,10 +47,13 @@ export function PreferencesProvider({ children }: { children: ReactNode }) { // Invalid size, reset to default setCardSizeState(DEFAULT_PREFERENCES.cardSize); } + // Load squareCovers preference (defaults to false if not set) + setSquareCoversState(preferences.squareCovers ?? DEFAULT_PREFERENCES.squareCovers); } } catch (error) { console.error('Failed to load preferences from localStorage:', error); setCardSizeState(DEFAULT_PREFERENCES.cardSize); + setSquareCoversState(DEFAULT_PREFERENCES.squareCovers); } }, []); @@ -68,6 +76,22 @@ export function PreferencesProvider({ children }: { children: ReactNode }) { } }; + // Update square covers preference in state and localStorage + const setSquareCovers = (enabled: boolean) => { + if (typeof window === 'undefined') return; + + setSquareCoversState(enabled); + + try { + const stored = localStorage.getItem(STORAGE_KEY); + const preferences: Preferences = stored ? JSON.parse(stored) : { ...DEFAULT_PREFERENCES }; + preferences.squareCovers = enabled; + localStorage.setItem(STORAGE_KEY, JSON.stringify(preferences)); + } catch (error) { + console.error('Failed to save preferences to localStorage:', error); + } + }; + // Listen for storage changes in other tabs (cross-tab sync) useEffect(() => { if (typeof window === 'undefined') return; @@ -80,6 +104,8 @@ export function PreferencesProvider({ children }: { children: ReactNode }) { if (preferences.cardSize >= 1 && preferences.cardSize <= 9) { setCardSizeState(preferences.cardSize); } + // Sync squareCovers preference + setSquareCoversState(preferences.squareCovers ?? DEFAULT_PREFERENCES.squareCovers); } catch (error) { console.error('Failed to parse preferences from storage event:', error); } @@ -93,7 +119,7 @@ export function PreferencesProvider({ children }: { children: ReactNode }) { }, []); return ( - + {children} );