mobile: responsive font size in UI (#227)
This commit is contained in:
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { MdCheck } from 'react-icons/md';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useDefaultIconSize } from '@/hooks/useResponsiveSize';
|
||||
|
||||
interface DialogMenuProps {
|
||||
toggleDropdown?: () => void;
|
||||
@@ -9,6 +10,7 @@ interface DialogMenuProps {
|
||||
|
||||
const DialogMenu: React.FC<DialogMenuProps> = ({ toggleDropdown }) => {
|
||||
const _ = useTranslation();
|
||||
const iconSize = useDefaultIconSize();
|
||||
const { isFontLayoutSettingsGlobal, setFontLayoutSettingsGlobal } = useSettingsStore();
|
||||
|
||||
const handleToggleGlobal = () => {
|
||||
@@ -26,7 +28,7 @@ const DialogMenu: React.FC<DialogMenuProps> = ({ toggleDropdown }) => {
|
||||
onClick={handleToggleGlobal}
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<span style={{ minWidth: '20px' }}>
|
||||
<span style={{ minWidth: `${iconSize}px` }}>
|
||||
{isFontLayoutSettingsGlobal && <MdCheck className='text-base-content' />}
|
||||
</span>
|
||||
<div
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from 'react';
|
||||
import { FiChevronUp, FiChevronLeft } from 'react-icons/fi';
|
||||
import { MdCheck } from 'react-icons/md';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
import { useDefaultIconSize, useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
|
||||
interface DropdownProps {
|
||||
family?: string;
|
||||
@@ -24,6 +24,7 @@ const FontDropdown: React.FC<DropdownProps> = ({
|
||||
}) => {
|
||||
const _ = useTranslation();
|
||||
const iconSize16 = useResponsiveSize(16);
|
||||
const defaultIconSize = useDefaultIconSize();
|
||||
return (
|
||||
<div className='dropdown dropdown-top'>
|
||||
<button
|
||||
@@ -40,7 +41,7 @@ const FontDropdown: React.FC<DropdownProps> = ({
|
||||
{options.map((option) => (
|
||||
<li key={option} onClick={() => onSelect(option)}>
|
||||
<div className='flex items-center px-0'>
|
||||
<span style={{ minWidth: '20px' }}>
|
||||
<span style={{ minWidth: `${defaultIconSize}px` }}>
|
||||
{selected === option && <MdCheck className='text-base-content' />}
|
||||
</span>
|
||||
<span style={{ fontFamily: onGetFontFamily(option, family ?? '') }}>{option}</span>
|
||||
@@ -50,7 +51,7 @@ const FontDropdown: React.FC<DropdownProps> = ({
|
||||
{moreOptions && moreOptions.length > 0 && (
|
||||
<li className='dropdown dropdown-left dropdown-top'>
|
||||
<div className='flex items-center px-0'>
|
||||
<span style={{ minWidth: '20px' }}>
|
||||
<span style={{ minWidth: `${iconSize16}px` }}>
|
||||
<FiChevronLeft size={iconSize16} />
|
||||
</span>
|
||||
<span>{_('System Fonts')}</span>
|
||||
@@ -65,7 +66,7 @@ const FontDropdown: React.FC<DropdownProps> = ({
|
||||
{moreOptions.map((option) => (
|
||||
<li key={option} onClick={() => onSelect(option)}>
|
||||
<div className='flex items-center px-2'>
|
||||
<span style={{ minWidth: '20px' }}>
|
||||
<span style={{ minWidth: `${defaultIconSize}px` }}>
|
||||
{selected === option && <MdCheck className='text-base-content' />}
|
||||
</span>
|
||||
<span style={{ fontFamily: onGetFontFamily(option, family ?? '') }}>
|
||||
|
||||
@@ -135,7 +135,7 @@ const MiscPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
>
|
||||
<div className='relative p-1'>
|
||||
<textarea
|
||||
className='textarea textarea-ghost h-48 w-full border-0 p-3 !outline-none'
|
||||
className='textarea textarea-ghost h-48 w-full border-0 p-3 text-base !outline-none sm:text-sm'
|
||||
placeholder={_('Enter your custom CSS here...')}
|
||||
spellCheck='false'
|
||||
value={draftStylesheet}
|
||||
|
||||
@@ -68,8 +68,8 @@ const SidebarContent: React.FC<{
|
||||
<>
|
||||
<div
|
||||
className={clsx(
|
||||
'sidebar-content flex min-h-0 flex-grow flex-col',
|
||||
'font-sans text-sm font-normal shadow-inner',
|
||||
'sidebar-content flex min-h-0 flex-grow flex-col shadow-inner',
|
||||
'font-sans text-base font-normal sm:text-sm',
|
||||
)}
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -29,7 +29,7 @@ const SidebarHeader: React.FC<{
|
||||
isTrafficLightVisible ? 'pl-20' : 'pl-1.5',
|
||||
)}
|
||||
>
|
||||
<div className='flex items-center gap-x-4'>
|
||||
<div className='flex items-center gap-x-8'>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className={'btn btn-ghost btn-circle flex h-6 min-h-6 w-6 hover:bg-transparent sm:hidden'}
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { MdCheck } from 'react-icons/md';
|
||||
import { BookSearchConfig } from '@/types/book';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useDefaultIconSize } from '@/hooks/useResponsiveSize';
|
||||
|
||||
interface SearchOptionsProps {
|
||||
searchConfig: BookSearchConfig;
|
||||
@@ -21,7 +22,7 @@ const Option: React.FC<OptionProps> = ({ label, isActive, onClick }) => (
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<span style={{ minWidth: '20px' }}>
|
||||
<span style={{ minWidth: `${useDefaultIconSize()}px` }}>
|
||||
{isActive && <MdCheck className='text-base-content' />}
|
||||
</span>
|
||||
<span className='ml-2'>{label}</span>
|
||||
|
||||
@@ -183,9 +183,13 @@ const TTSControl = () => {
|
||||
throttle(async (rate: number) => {
|
||||
const ttsController = ttsControllerRef.current;
|
||||
if (ttsController) {
|
||||
await ttsController.stop();
|
||||
await ttsController.setRate(rate);
|
||||
await ttsController.start();
|
||||
if (ttsController.state === 'playing') {
|
||||
await ttsController.stop();
|
||||
await ttsController.setRate(rate);
|
||||
await ttsController.start();
|
||||
} else {
|
||||
await ttsController.setRate(rate);
|
||||
}
|
||||
}
|
||||
}, 3000),
|
||||
[],
|
||||
@@ -196,9 +200,13 @@ const TTSControl = () => {
|
||||
throttle(async (voice: string) => {
|
||||
const ttsController = ttsControllerRef.current;
|
||||
if (ttsController) {
|
||||
await ttsController.stop();
|
||||
await ttsController.setVoice(voice);
|
||||
await ttsController.start();
|
||||
if (ttsController.state === 'playing') {
|
||||
await ttsController.stop();
|
||||
await ttsController.setVoice(voice);
|
||||
await ttsController.start();
|
||||
} else {
|
||||
await ttsController.setVoice(voice);
|
||||
}
|
||||
}
|
||||
}, 3000),
|
||||
[],
|
||||
|
||||
@@ -6,7 +6,7 @@ import { MdPlayCircle, MdPauseCircle, MdFastRewind, MdFastForward, MdStop } from
|
||||
import { RiVoiceAiFill } from 'react-icons/ri';
|
||||
import { MdCheck } from 'react-icons/md';
|
||||
import { TTSVoice } from '@/services/tts';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
import { useDefaultIconSize, useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
|
||||
type TTSPanelProps = {
|
||||
bookKey: string;
|
||||
@@ -43,6 +43,7 @@ const TTSPanel = ({
|
||||
const [rate, setRate] = useState(viewSettings?.ttsRate ?? 1.0);
|
||||
const [selectedVoice, setSelectedVoice] = useState(viewSettings?.ttsVoice ?? '');
|
||||
|
||||
const defaultIconSize = useDefaultIconSize();
|
||||
const iconSize32 = useResponsiveSize(32);
|
||||
const iconSize48 = useResponsiveSize(48);
|
||||
|
||||
@@ -144,10 +145,10 @@ const TTSPanel = ({
|
||||
onClick={() => !voice.disabled && handleSelectVoice(voice.id)}
|
||||
>
|
||||
<div className='flex items-center px-2'>
|
||||
<span style={{ minWidth: '20px' }}>
|
||||
<span style={{ minWidth: `${defaultIconSize}px` }}>
|
||||
{selectedVoice === voice.id && <MdCheck className='text-base-content' />}
|
||||
</span>
|
||||
<span className={clsx('text-sm', voice.disabled && 'text-gray-400')}>
|
||||
<span className={clsx('text-base sm:text-sm', voice.disabled && 'text-gray-400')}>
|
||||
{voice.name}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
import { useDefaultIconSize } from '@/hooks/useResponsiveSize';
|
||||
|
||||
interface MenuItemProps {
|
||||
label: string;
|
||||
@@ -22,6 +23,7 @@ const MenuItem: React.FC<MenuItemProps> = ({
|
||||
children,
|
||||
onClick,
|
||||
}) => {
|
||||
const iconSize = useDefaultIconSize();
|
||||
const menuButton = (
|
||||
<button
|
||||
className={clsx(
|
||||
@@ -32,10 +34,10 @@ const MenuItem: React.FC<MenuItemProps> = ({
|
||||
disabled={disabled}
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
{!noIcon && <span style={{ minWidth: '20px' }}>{icon}</span>}
|
||||
{!noIcon && <span style={{ minWidth: `${iconSize}px` }}>{icon}</span>}
|
||||
<span className={clsx('ml-2 max-w-32 truncate', labelClass)}>{label}</span>
|
||||
</div>
|
||||
{shortcut && <span className='text-neutral-content text-sm'>{shortcut}</span>}
|
||||
{shortcut && <span className='text-neutral-content hidden text-sm sm:flex'>{shortcut}</span>}
|
||||
</button>
|
||||
);
|
||||
|
||||
|
||||
@@ -164,6 +164,13 @@ foliate-view {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.dropdown-content,
|
||||
.settings-content {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.config-item {
|
||||
@apply flex h-14 items-center justify-between p-4;
|
||||
@apply hover:bg-base-100/50;
|
||||
|
||||
Reference in New Issue
Block a user