forked from akai/readest
Various UI fixes
This commit is contained in:
@@ -1,17 +1,19 @@
|
||||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { AuthProvider } from '@/context/AuthContext';
|
||||
import { EnvProvider } from '@/context/EnvContext';
|
||||
import { CSPostHogProvider } from '@/context/PHContext';
|
||||
import '../styles/globals.css';
|
||||
import '../styles/fonts.css';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Readest',
|
||||
description: 'read to learn',
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
const pathname = usePathname();
|
||||
React.useEffect(() => {
|
||||
document.documentElement.setAttribute('data-page', pathname.replace('/', '') || 'default');
|
||||
}, [pathname]);
|
||||
|
||||
return (
|
||||
<html lang='en'>
|
||||
<head>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { Book, BooksGroup } from '@/types/book';
|
||||
import Alert from '@/components/Alert';
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import clsx from 'clsx';
|
||||
|
||||
type BookshelfItem = Book | BooksGroup;
|
||||
|
||||
@@ -96,24 +97,35 @@ const Bookshelf: React.FC<BookshelfProps> = ({ libraryBooks, isSelectMode, onImp
|
||||
<div className='bookshelf'>
|
||||
<div className='grid grid-cols-3 gap-0 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8'>
|
||||
{bookshelfItems.map((item, index) => (
|
||||
<div
|
||||
key={`library-item-${index}`}
|
||||
className='flex h-full flex-col rounded-md p-4 hover:bg-gray-200'
|
||||
>
|
||||
<div key={`library-item-${index}`} className='flex h-full flex-col p-4 hover:bg-gray-200'>
|
||||
<div className='flex-grow'>
|
||||
{'format' in item ? (
|
||||
<div
|
||||
className='book-item cursor-pointer'
|
||||
onClick={() => handleBookClick(item.hash)}
|
||||
>
|
||||
<div key={(item as Book).hash} className='card bg-base-100 shadow-md'>
|
||||
<div key={(item as Book).hash} className='bg-base-100 shadow-md'>
|
||||
<div className='relative aspect-[28/41]'>
|
||||
<Image
|
||||
src={(item as Book).coverImageUrl!}
|
||||
alt={(item as Book).title}
|
||||
src={item.coverImageUrl!}
|
||||
alt={item.title}
|
||||
fill={true}
|
||||
className='object-cover'
|
||||
onError={(e) => {
|
||||
(e.target as HTMLImageElement).style.display = 'none';
|
||||
(e.target as HTMLImageElement).nextElementSibling?.classList.remove(
|
||||
'invisible',
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={clsx(
|
||||
'invisible absolute inset-0 flex items-center justify-center',
|
||||
'rounded-none text-center font-sans text-lg font-medium text-gray-600',
|
||||
)}
|
||||
>
|
||||
{item.title}
|
||||
</div>
|
||||
{(selectedBooks.includes(item.hash) || clickedImage === item.hash) && (
|
||||
<div className='absolute inset-0 bg-black opacity-30 transition-opacity duration-300'></div>
|
||||
)}
|
||||
|
||||
@@ -52,7 +52,7 @@ const LibraryHeader: React.FC<LibraryHeaderProps> = ({
|
||||
<div
|
||||
ref={headerRef}
|
||||
className={clsx(
|
||||
'titlebar z-10 w-full bg-gray-100 py-2 pr-6',
|
||||
'titlebar z-10 h-11 w-full bg-gray-100 py-2 pr-6',
|
||||
isTrafficLightVisible ? 'pl-16' : 'pl-2',
|
||||
)}
|
||||
>
|
||||
@@ -64,9 +64,11 @@ const LibraryHeader: React.FC<LibraryHeaderProps> = ({
|
||||
<input
|
||||
type='text'
|
||||
placeholder='Search books...'
|
||||
spellCheck='false'
|
||||
className={clsx(
|
||||
'input input-sm rounded-badge w-full bg-gray-200 pl-10 pr-10',
|
||||
'font-sans text-base font-light focus:border-none focus:outline-none',
|
||||
'input rounded-badge h-7 w-full bg-gray-200 pl-10 pr-10',
|
||||
'font-sans text-sm font-light',
|
||||
'border-none focus:outline-none focus:ring-0',
|
||||
)}
|
||||
/>
|
||||
<div className='absolute right-4 flex items-center space-x-4 text-gray-500'>
|
||||
|
||||
@@ -77,22 +77,26 @@ const LibraryPage = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='rounded-window min-h-screen select-none overflow-hidden bg-gray-100'>
|
||||
<LibraryHeader
|
||||
isSelectMode={isSelectMode}
|
||||
onImportBooks={handleImportBooks}
|
||||
onToggleSelectMode={handleToggleSelectMode}
|
||||
/>
|
||||
<div className='flex-grow'>
|
||||
{loading || libraryBooks.length > 0 ? (
|
||||
<div className='hero-content h-full overflow-y-auto px-2 py-4'>
|
||||
<Spinner loading={loading} />
|
||||
<Bookshelf
|
||||
libraryBooks={libraryBooks}
|
||||
isSelectMode={isSelectMode}
|
||||
onImportBooks={handleImportBooks}
|
||||
/>
|
||||
</div>
|
||||
<div className='library-page rounded-window flex h-full min-h-screen select-none flex-col overflow-hidden bg-gray-100'>
|
||||
<div className='fixed top-0 z-40 w-full'>
|
||||
<LibraryHeader
|
||||
isSelectMode={isSelectMode}
|
||||
onImportBooks={handleImportBooks}
|
||||
onToggleSelectMode={handleToggleSelectMode}
|
||||
/>
|
||||
</div>
|
||||
{loading && (
|
||||
<div className='fixed inset-0 z-50 flex items-center justify-center bg-white/50'>
|
||||
<Spinner loading />
|
||||
</div>
|
||||
)}
|
||||
<div className='mt-12 flex-grow overflow-auto px-2'>
|
||||
{libraryBooks.length > 0 ? (
|
||||
<Bookshelf
|
||||
libraryBooks={libraryBooks}
|
||||
isSelectMode={isSelectMode}
|
||||
onImportBooks={handleImportBooks}
|
||||
/>
|
||||
) : (
|
||||
<div className='hero h-full items-center justify-center'>
|
||||
<div className='hero-content text-neutral-content text-center'>
|
||||
|
||||
@@ -30,7 +30,7 @@ const ReaderPage = () => {
|
||||
return (
|
||||
library.length > 0 &&
|
||||
settings.globalReadSettings && (
|
||||
<div className='min-h-screen select-none'>
|
||||
<div className='reader-page min-h-screen select-none bg-white'>
|
||||
<Suspense>
|
||||
<ReaderContent settings={settings} />
|
||||
</Suspense>
|
||||
|
||||
@@ -5,17 +5,32 @@
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
background: var(--background);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
html[data-page="default"] {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
html[data-page="library"] {
|
||||
background: #f3f4f6;
|
||||
}
|
||||
|
||||
html[data-page="reader"] {
|
||||
background: #f3f4f6;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--foreground);
|
||||
background: var(--background);
|
||||
@@ -30,6 +45,14 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
library-page {
|
||||
--background: #f3f4f6;
|
||||
}
|
||||
|
||||
reader-page {
|
||||
--background: #ffffff;
|
||||
}
|
||||
|
||||
foliate-view {
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
||||
Reference in New Issue
Block a user