remove skeleton loader

This commit is contained in:
EthanHealy01 2025-08-12 15:53:49 +01:00
parent 53e9dbb66e
commit 7801872810
7 changed files with 112 additions and 132 deletions

View File

@ -0,0 +1,70 @@
import React, { useState } from 'react';
import { ActionIcon, Tooltip } from '@mantine/core';
import AppsIcon from '@mui/icons-material/AppsRounded';
import ArrowBackIcon from '@mui/icons-material/ArrowBackRounded';
import { useToolWorkflow } from '../../contexts/ToolWorkflowContext';
interface AllToolsNavButtonProps {
activeButton: string;
setActiveButton: (id: string) => void;
}
const AllToolsNavButton: React.FC<AllToolsNavButtonProps> = ({ activeButton, setActiveButton }) => {
const { selectedTool, selectedToolKey, handleReaderToggle, handleBackToTools } = useToolWorkflow();
const [isHovered, setIsHovered] = useState(false);
const handleClick = () => {
setActiveButton('tools');
// Preserve existing behavior used in QuickAccessBar header
handleReaderToggle();
handleBackToTools();
};
const isActive = activeButton === 'tools';
const iconNode = (() => {
if (selectedToolKey) {
if (isHovered) return <ArrowBackIcon sx={{ fontSize: '1.75rem' }} />;
return (
<span className="iconContainer">
{selectedTool?.icon ?? <AppsIcon sx={{ fontSize: '1.75rem' }} />}
</span>
);
}
return (
<span className="iconContainer">
<AppsIcon sx={{ fontSize: '1.75rem' }} />
</span>
);
})();
return (
<Tooltip label={selectedToolKey && isHovered ? 'Back to all tools' : 'View all available tools'} position="right">
<div className="flex flex-col items-center gap-1 mt-4 mb-2">
<ActionIcon
size="lg"
variant="subtle"
onClick={handleClick}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
style={{
backgroundColor: isActive ? 'var(--icon-tools-bg)' : 'var(--icon-inactive-bg)',
color: isActive ? 'var(--icon-tools-color)' : 'var(--icon-inactive-color)',
border: 'none',
borderRadius: '8px',
}}
className={isActive ? 'activeIconScale' : ''}
>
{iconNode}
</ActionIcon>
<span className={`all-tools-text ${isActive ? 'active' : 'inactive'}`}>
All Tools
</span>
</div>
</Tooltip>
);
};
export default AllToolsNavButton;

View File

@ -1,12 +1,8 @@
import React, { useState, useRef, forwardRef } from "react"; import React, { useState, useRef, forwardRef } from "react";
import { ActionIcon, Stack, Tooltip, Divider } from "@mantine/core"; import { ActionIcon, Stack, Tooltip, Divider } from "@mantine/core";
import MenuBookIcon from "@mui/icons-material/MenuBookRounded"; import MenuBookIcon from "@mui/icons-material/MenuBookRounded";
import AppsIcon from "@mui/icons-material/AppsRounded";
import SettingsIcon from "@mui/icons-material/SettingsRounded"; import SettingsIcon from "@mui/icons-material/SettingsRounded";
import AutoAwesomeIcon from "@mui/icons-material/AutoAwesomeRounded";
import FolderIcon from "@mui/icons-material/FolderRounded"; import FolderIcon from "@mui/icons-material/FolderRounded";
import PersonIcon from "@mui/icons-material/PersonRounded";
import NotificationsIcon from "@mui/icons-material/NotificationsRounded";
import { useRainbowThemeContext } from "./RainbowThemeProvider"; import { useRainbowThemeContext } from "./RainbowThemeProvider";
import AppConfigModal from './AppConfigModal'; import AppConfigModal from './AppConfigModal';
import { useIsOverflowing } from '../../hooks/useIsOverflowing'; import { useIsOverflowing } from '../../hooks/useIsOverflowing';
@ -14,48 +10,7 @@ import { useFilesModalContext } from '../../contexts/FilesModalContext';
import { useToolWorkflow } from '../../contexts/ToolWorkflowContext'; import { useToolWorkflow } from '../../contexts/ToolWorkflowContext';
import { ButtonConfig } from '../../types/sidebar'; import { ButtonConfig } from '../../types/sidebar';
import './QuickAccessBar.css'; import './QuickAccessBar.css';
import AllToolsNavButton from './AllToolsNavButton';
function NavHeader({
activeButton,
setActiveButton
}: {
activeButton: string;
setActiveButton: (id: string) => void;
}) {
const { handleReaderToggle, handleBackToTools } = useToolWorkflow();
return (
<>
{/* All Tools button below divider */}
<Tooltip label="View all available tools" position="right">
<div className="flex flex-col items-center gap-1 mt-4 mb-2">
<ActionIcon
size="lg"
variant="subtle"
onClick={() => {
setActiveButton('tools');
handleReaderToggle();
handleBackToTools();
}}
style={{
backgroundColor: activeButton === 'tools' ? 'var(--icon-tools-bg)' : 'var(--icon-inactive-bg)',
color: activeButton === 'tools' ? 'var(--icon-tools-color)' : 'var(--icon-inactive-color)',
border: 'none',
borderRadius: '8px',
}}
className={activeButton === 'tools' ? 'activeIconScale' : ''}
>
<span className="iconContainer">
<AppsIcon sx={{ fontSize: "1.75rem" }} />
</span>
</ActionIcon>
<span className={`all-tools-text ${activeButton === 'tools' ? 'active' : 'inactive'}`}>
All Tools
</span>
</div>
</Tooltip>
</>
);
}
const QuickAccessBar = forwardRef<HTMLDivElement>(({ const QuickAccessBar = forwardRef<HTMLDivElement>(({
}, ref) => { }, ref) => {
@ -89,9 +44,9 @@ const QuickAccessBar = forwardRef<HTMLDivElement>(({
id: 'sign', id: 'sign',
name: 'Sign', name: 'Sign',
icon: icon:
<span className="material-symbols-rounded font-size-20"> <span className="material-symbols-rounded font-size-20">
signature signature
</span>, </span>,
tooltip: 'Sign your document', tooltip: 'Sign your document',
size: 'lg', size: 'lg',
isRound: false, isRound: false,
@ -102,9 +57,9 @@ const QuickAccessBar = forwardRef<HTMLDivElement>(({
id: 'automate', id: 'automate',
name: 'Automate', name: 'Automate',
icon: icon:
<span className="material-symbols-rounded font-size-20"> <span className="material-symbols-rounded font-size-20">
automation automation
</span>, </span>,
tooltip: 'Automate workflows', tooltip: 'Automate workflows',
size: 'lg', size: 'lg',
isRound: false, isRound: false,
@ -125,9 +80,9 @@ const QuickAccessBar = forwardRef<HTMLDivElement>(({
id: 'activity', id: 'activity',
name: 'Activity', name: 'Activity',
icon: icon:
<span className="material-symbols-rounded font-size-20"> <span className="material-symbols-rounded font-size-20">
vital_signs vital_signs
</span>, </span>,
tooltip: 'View activity and analytics', tooltip: 'View activity and analytics',
isRound: true, isRound: true,
size: 'lg', size: 'lg',
@ -194,10 +149,8 @@ const QuickAccessBar = forwardRef<HTMLDivElement>(({
> >
{/* Fixed header outside scrollable area */} {/* Fixed header outside scrollable area */}
<div className="quick-access-header"> <div className="quick-access-header">
<NavHeader <AllToolsNavButton activeButton={activeButton} setActiveButton={setActiveButton} />
activeButton={activeButton}
setActiveButton={setActiveButton}
/>
</div> </div>
{/* Conditional divider when overflowing */} {/* Conditional divider when overflowing */}
@ -244,10 +197,10 @@ const QuickAccessBar = forwardRef<HTMLDivElement>(({
{/* Add divider after Automate button (index 2) */} {/* Add divider after Automate button (index 2) */}
{index === 2 && ( {index === 2 && (
<Divider <Divider
size="xs" size="xs"
className="content-divider" className="content-divider"
/> />
)} )}
</React.Fragment> </React.Fragment>
))} ))}

View File

@ -1,4 +1,4 @@
import React, { createContext, useContext, useMemo, useRef, useEffect, useState } from 'react'; import React, { createContext, useContext, useMemo, useRef } from 'react';
import { Paper, Text, Stack, Box, Flex } from '@mantine/core'; import { Paper, Text, Stack, Box, Flex } from '@mantine/core';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import ChevronRightIcon from '@mui/icons-material/ChevronRight';
@ -22,10 +22,6 @@ export interface ToolStepProps {
completedMessage?: string; completedMessage?: string;
helpText?: string; helpText?: string;
showNumber?: boolean; showNumber?: boolean;
/** Show a brief skeleton for smoother tool transitions */
enableInitialSkeleton?: boolean;
/** Duration for the initial skeleton in milliseconds */
initialSkeletonMs?: number;
tooltip?: { tooltip?: {
content?: React.ReactNode; content?: React.ReactNode;
tips?: TooltipTip[]; tips?: TooltipTip[];
@ -78,8 +74,6 @@ const ToolStep = ({
completedMessage, completedMessage,
helpText, helpText,
showNumber, showNumber,
enableInitialSkeleton = true,
initialSkeletonMs = 800,
tooltip tooltip
}: ToolStepProps) => { }: ToolStepProps) => {
if (!isVisible) return null; if (!isVisible) return null;
@ -94,16 +88,6 @@ const ToolStep = ({
const stepNumber = parent?.getStepNumber?.() || 1; const stepNumber = parent?.getStepNumber?.() || 1;
// Show a step-sized skeleton immediately after mount to indicate tool switch
const [showInitialSkeleton, setShowInitialSkeleton] = useState(enableInitialSkeleton);
useEffect(() => {
if (!enableInitialSkeleton) return;
setShowInitialSkeleton(true);
const id = setTimeout(() => setShowInitialSkeleton(false), initialSkeletonMs);
return () => clearTimeout(id);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return ( return (
<Paper <Paper
p="md" p="md"
@ -125,19 +109,11 @@ const ToolStep = ({
> >
<Flex align="center" gap="sm"> <Flex align="center" gap="sm">
{shouldShowNumber && ( {shouldShowNumber && (
showInitialSkeleton ? ( <Text fw={500} size="lg" c="dimmed">
<Box w={18} h={18} bg="gray.1" style={{ borderRadius: 4 }} /> {stepNumber}
) : ( </Text>
<Text fw={500} size="lg" c="dimmed">
{stepNumber}
</Text>
)
)}
{showInitialSkeleton ? (
<Box w={80} h={20} bg="gray.1" style={{ borderRadius: 4 }} />
) : (
renderTooltipTitle(title, tooltip, isCollapsed)
)} )}
{renderTooltipTitle(title, tooltip, isCollapsed)}
</Flex> </Flex>
{isCollapsed ? ( {isCollapsed ? (
@ -157,19 +133,15 @@ const ToolStep = ({
{isCollapsed ? ( {isCollapsed ? (
<Box> <Box>
{showInitialSkeleton ? ( {isCompleted && completedMessage && (
<Box w="40%" h={14} bg="gray.1" style={{ borderRadius: 4 }} /> <Text size="sm" c="green">
) : ( {completedMessage}
isCompleted && completedMessage && ( {onCollapsedClick && (
<Text size="sm" c="green"> <Text span c="dimmed" size="xs" ml="sm">
{completedMessage} (click to change)
{onCollapsedClick && ( </Text>
<Text span c="dimmed" size="xs" ml="sm"> )}
(click to change) </Text>
</Text>
)}
</Text>
)
)} )}
</Box> </Box>
) : ( ) : (
@ -179,16 +151,7 @@ const ToolStep = ({
{helpText} {helpText}
</Text> </Text>
)} )}
{showInitialSkeleton ? ( {children}
<>
<Box w="80%" h={16} bg="gray.1" style={{ borderRadius: 4 }} />
<Box w="60%" h={16} bg="gray.1" style={{ borderRadius: 4 }} />
<Box w="100%" h={44} bg="gray.1" style={{ borderRadius: 8 }} />
<Box w="100%" h={44} bg="gray.1" style={{ borderRadius: 8 }} />
</>
) : (
children
)}
</Stack> </Stack>
)} )}
</Paper> </Paper>

View File

@ -1,7 +1,6 @@
import React from 'react'; import React from 'react';
import SplitPdfPanel from "../tools/Split"; import SplitPdfPanel from "../tools/Split";
import CompressPdfPanel from "../tools/Compress"; import CompressPdfPanel from "../tools/Compress";
import MergePdfPanel from "../tools/Merge";
import OCRPanel from '../tools/OCR'; import OCRPanel from '../tools/OCR';
import ConvertPanel from '../tools/Convert'; import ConvertPanel from '../tools/Convert';
@ -282,7 +281,7 @@ export const flatToolRegistryMap: ToolRegistry = {
"mergePdfs": { "mergePdfs": {
icon: <span className="material-symbols-rounded">library_add</span>, icon: <span className="material-symbols-rounded">library_add</span>,
name: "home.merge.title", name: "home.merge.title",
component: MergePdfPanel, component: null,
view: "merge", view: "merge",
description: "home.merge.desc", description: "home.merge.desc",
category: "Recommended Tools", category: "Recommended Tools",

View File

@ -102,7 +102,6 @@ const Compress = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
<ToolStep <ToolStep
title="Settings" title="Settings"
isVisible={hasFiles} isVisible={hasFiles}
enableInitialSkeleton={false}
isCollapsed={settingsCollapsed} isCollapsed={settingsCollapsed}
isCompleted={settingsCollapsed} isCompleted={settingsCollapsed}
onCollapsedClick={settingsCollapsed ? handleSettingsReset : undefined} onCollapsedClick={settingsCollapsed ? handleSettingsReset : undefined}
@ -130,7 +129,6 @@ const Compress = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
<ToolStep <ToolStep
title="Results" title="Results"
isVisible={hasResults} isVisible={hasResults}
enableInitialSkeleton={false}
> >
<Stack gap="sm"> <Stack gap="sm">
{compressOperation.status && ( {compressOperation.status && (

View File

@ -163,7 +163,6 @@ const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
<ToolStep <ToolStep
title={t("convert.results", "Results")} title={t("convert.results", "Results")}
isVisible={hasResults} isVisible={hasResults}
enableInitialSkeleton={false}
data-testid="conversion-results" data-testid="conversion-results"
> >
<Stack gap="sm"> <Stack gap="sm">

View File

@ -97,7 +97,6 @@ const Split = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
<ToolStep <ToolStep
title="Settings" title="Settings"
isVisible={true} isVisible={true}
enableInitialSkeleton={true}
isCollapsed={settingsCollapsed} isCollapsed={settingsCollapsed}
isCompleted={settingsCollapsed} isCompleted={settingsCollapsed}
onCollapsedClick={settingsCollapsed ? handleSettingsReset : undefined} onCollapsedClick={settingsCollapsed ? handleSettingsReset : undefined}
@ -126,7 +125,6 @@ const Split = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
<ToolStep <ToolStep
title="Results" title="Results"
isVisible={hasResults} isVisible={hasResults}
enableInitialSkeleton={false}
> >
<Stack gap="sm"> <Stack gap="sm">
{splitOperation.status && ( {splitOperation.status && (