fix: improve Bible reader loading UX with skeleton states
- Remove full-screen loading backdrop that hides entire UI - Add skeleton loading components for chapter headers and verses - Implement smooth content transitions without UI disappearance - Change initial loading state to prevent immediate UI hide - Enhance Suspense fallbacks with better loading messages - Keep Bible reader interface visible during all loading states Fixes issue where: - Entire reader disappeared during chapter changes - Users saw only header/footer during loading - Poor perceived performance with jarring transitions Now provides professional skeleton loading within the reader interface for a smooth, responsive user experience. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -175,7 +175,7 @@ export default function BibleReaderNew({ initialVersion, initialBook, initialCha
|
||||
const [selectedBook, setSelectedBook] = useState<string>('')
|
||||
const [selectedChapter, setSelectedChapter] = useState<number>(1)
|
||||
const [verses, setVerses] = useState<BibleVerse[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [versionsLoading, setVersionsLoading] = useState(true)
|
||||
const [showAllVersions, setShowAllVersions] = useState(false)
|
||||
|
||||
@@ -1382,13 +1382,7 @@ export default function BibleReaderNew({ initialVersion, initialBook, initialCha
|
||||
</Dialog>
|
||||
)
|
||||
|
||||
if (loading && books.length === 0) {
|
||||
return (
|
||||
<Backdrop open>
|
||||
<CircularProgress color="inherit" />
|
||||
</Backdrop>
|
||||
)
|
||||
}
|
||||
// Always render the UI - loading will be handled within components
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -1480,24 +1474,101 @@ export default function BibleReaderNew({ initialVersion, initialBook, initialCha
|
||||
<Box sx={{ opacity: loading ? 0.3 : 1, transition: 'opacity 0.3s ease' }}>
|
||||
{/* Chapter Header */}
|
||||
<Box sx={{ mb: 4, textAlign: 'center' }}>
|
||||
<Typography
|
||||
variant="h3"
|
||||
component="h1"
|
||||
sx={{
|
||||
mb: 2,
|
||||
fontFamily: preferences.fontFamily === 'serif' ? 'Georgia, serif' : 'Arial, sans-serif'
|
||||
}}
|
||||
>
|
||||
{currentBook?.name} {selectedChapter}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{(loading && previousVerses.length > 0 ? previousVerses : verses).length} {t('verses')}
|
||||
</Typography>
|
||||
{loading && !currentBook ? (
|
||||
// Skeleton loading for chapter header
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
height: 40,
|
||||
backgroundColor: 'action.hover',
|
||||
borderRadius: 1,
|
||||
mb: 2,
|
||||
margin: '0 auto',
|
||||
width: '200px'
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
height: 16,
|
||||
backgroundColor: 'action.hover',
|
||||
borderRadius: 1,
|
||||
margin: '0 auto',
|
||||
width: '80px'
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Typography
|
||||
variant="h3"
|
||||
component="h1"
|
||||
sx={{
|
||||
mb: 2,
|
||||
fontFamily: preferences.fontFamily === 'serif' ? 'Georgia, serif' : 'Arial, sans-serif'
|
||||
}}
|
||||
>
|
||||
{currentBook?.name} {selectedChapter}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{(loading && previousVerses.length > 0 ? previousVerses : verses).length} {t('verses')}
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Verses */}
|
||||
<Box sx={{ mb: 4 }}>
|
||||
{(loading && previousVerses.length > 0 ? previousVerses : verses).map(renderVerse)}
|
||||
{loading && verses.length === 0 && previousVerses.length === 0 ? (
|
||||
// Skeleton loading for verses
|
||||
<>
|
||||
{Array.from({ length: 8 }).map((_, index) => (
|
||||
<Box key={`skeleton-${index}`} sx={{ mb: 2, display: 'flex', alignItems: 'flex-start' }}>
|
||||
<Box
|
||||
sx={{
|
||||
width: 32,
|
||||
height: 20,
|
||||
backgroundColor: 'action.hover',
|
||||
borderRadius: 1,
|
||||
mr: 2,
|
||||
flexShrink: 0
|
||||
}}
|
||||
/>
|
||||
<Box sx={{ width: '100%' }}>
|
||||
<Box
|
||||
sx={{
|
||||
height: 16,
|
||||
backgroundColor: 'action.hover',
|
||||
borderRadius: 1,
|
||||
mb: 1,
|
||||
width: `${Math.random() * 40 + 60}%`
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
height: 16,
|
||||
backgroundColor: 'action.hover',
|
||||
borderRadius: 1,
|
||||
mb: 1,
|
||||
width: `${Math.random() * 50 + 40}%`
|
||||
}}
|
||||
/>
|
||||
{Math.random() > 0.5 && (
|
||||
<Box
|
||||
sx={{
|
||||
height: 16,
|
||||
backgroundColor: 'action.hover',
|
||||
borderRadius: 1,
|
||||
width: `${Math.random() * 30 + 20}%`
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
(loading && previousVerses.length > 0 ? previousVerses : verses).map(renderVerse)
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Chapter Navigation */}
|
||||
|
||||
Reference in New Issue
Block a user