Moved bar to bottom of workbench

made gray
made scrolling work on search results
made scrollbars all look the same
This commit is contained in:
Connor Yoh 2025-08-29 12:25:01 +01:00
parent f3d66c189f
commit da212cc120
15 changed files with 82 additions and 73 deletions

View File

@ -1,5 +1,4 @@
import React, { Suspense } from "react"; import React, { Suspense } from "react";
import { ScrollArea } from "@mantine/core";
import { RainbowThemeProvider } from "./components/shared/RainbowThemeProvider"; import { RainbowThemeProvider } from "./components/shared/RainbowThemeProvider";
import { FileContextProvider } from "./contexts/FileContext"; import { FileContextProvider } from "./contexts/FileContext";
import { NavigationProvider } from "./contexts/NavigationContext"; import { NavigationProvider } from "./contexts/NavigationContext";
@ -42,9 +41,7 @@ export default function App() {
<ToolWorkflowProvider> <ToolWorkflowProvider>
<SidebarProvider> <SidebarProvider>
<RightRailProvider> <RightRailProvider>
<ScrollArea h="100vh" scrollbarSize={6} scrollHideDelay={1000}> <HomePage />
<HomePage />
</ScrollArea>
</RightRailProvider> </RightRailProvider>
</SidebarProvider> </SidebarProvider>
</ToolWorkflowProvider> </ToolWorkflowProvider>

View File

@ -454,7 +454,6 @@ const FileEditor = ({
multiple={true} multiple={true}
maxSize={2 * 1024 * 1024 * 1024} maxSize={2 * 1024 * 1024 * 1024}
style={{ style={{
height: '100vh',
border: 'none', border: 'none',
borderRadius: 0, borderRadius: 0,
backgroundColor: 'transparent' backgroundColor: 'transparent'
@ -462,7 +461,7 @@ const FileEditor = ({
activateOnClick={false} activateOnClick={false}
activateOnDrag={true} activateOnDrag={true}
> >
<Box pos="relative" h="100vh" style={{ overflow: 'auto' }}> <Box pos="relative" style={{ overflow: 'auto' }}>
<LoadingOverlay visible={false} /> <LoadingOverlay visible={false} />
<Box p="md" pt="xl"> <Box p="md" pt="xl">
@ -563,7 +562,7 @@ const FileEditor = ({
color="blue" color="blue"
mt="md" mt="md"
onClose={() => setStatus(null)} onClose={() => setStatus(null)}
style={{ position: 'fixed', bottom: 20, right: 20, zIndex: 10001 }} style={{ position: 'fixed', bottom: 40, right: 80, zIndex: 10001 }}
> >
{status} {status}
</Notification> </Notification>

View File

@ -0,0 +1,21 @@
.workbench-scrollable {
overflow-y: auto !important;
overflow-x: hidden !important;
}
.workbench-scrollable::-webkit-scrollbar {
width: 0.375rem;
}
.workbench-scrollable::-webkit-scrollbar-track {
background: transparent;
}
.workbench-scrollable::-webkit-scrollbar-thumb {
background-color: var(--mantine-color-gray-4);
border-radius: 0.1875rem;
}
.workbench-scrollable::-webkit-scrollbar-thumb:hover {
background-color: var(--mantine-color-gray-5);
}

View File

@ -4,9 +4,10 @@ import { useTranslation } from 'react-i18next';
import { useRainbowThemeContext } from '../shared/RainbowThemeProvider'; import { useRainbowThemeContext } from '../shared/RainbowThemeProvider';
import { useToolWorkflow } from '../../contexts/ToolWorkflowContext'; import { useToolWorkflow } from '../../contexts/ToolWorkflowContext';
import { useFileHandler } from '../../hooks/useFileHandler'; import { useFileHandler } from '../../hooks/useFileHandler';
import { useFileState, useFileActions } from '../../contexts/FileContext'; import { useFileState } from '../../contexts/FileContext';
import { useNavigationState, useNavigationActions } from '../../contexts/NavigationContext'; import { useNavigationState, useNavigationActions } from '../../contexts/NavigationContext';
import { useToolManagement } from '../../hooks/useToolManagement'; import { useToolManagement } from '../../hooks/useToolManagement';
import './Workbench.css';
import TopControls from '../shared/TopControls'; import TopControls from '../shared/TopControls';
import FileEditor from '../fileEditor/FileEditor'; import FileEditor from '../fileEditor/FileEditor';
@ -14,6 +15,7 @@ import PageEditor from '../pageEditor/PageEditor';
import PageEditorControls from '../pageEditor/PageEditorControls'; import PageEditorControls from '../pageEditor/PageEditorControls';
import Viewer from '../viewer/Viewer'; import Viewer from '../viewer/Viewer';
import LandingPage from '../shared/LandingPage'; import LandingPage from '../shared/LandingPage';
import Footer from '../shared/Footer';
// No props needed - component uses contexts directly // No props needed - component uses contexts directly
export default function Workbench() { export default function Workbench() {
@ -22,7 +24,6 @@ export default function Workbench() {
// Use context-based hooks to eliminate all prop drilling // Use context-based hooks to eliminate all prop drilling
const { state } = useFileState(); const { state } = useFileState();
const { actions } = useFileActions();
const { workbench: currentView } = useNavigationState(); const { workbench: currentView } = useNavigationState();
const { actions: navActions } = useNavigationActions(); const { actions: navActions } = useNavigationActions();
const setCurrentView = navActions.setWorkbench; const setCurrentView = navActions.setWorkbench;
@ -142,7 +143,7 @@ export default function Workbench() {
return ( return (
<Box <Box
className="flex-1 h-screen min-w-80 relative flex flex-col" className="flex-1 h-full min-w-80 relative flex flex-col"
style={ style={
isRainbowMode isRainbowMode
? {} // No background color in rainbow mode ? {} // No background color in rainbow mode
@ -158,7 +159,7 @@ export default function Workbench() {
{/* Main content area */} {/* Main content area */}
<Box <Box
className="flex-1 min-h-0 relative z-10" className="flex-1 min-h-0 relative z-10 workbench-scrollable "
style={{ style={{
transition: 'opacity 0.15s ease-in-out', transition: 'opacity 0.15s ease-in-out',
marginTop: '1rem', marginTop: '1rem',
@ -166,6 +167,8 @@ export default function Workbench() {
> >
{renderMainContent()} {renderMainContent()}
</Box> </Box>
<Footer analyticsEnabled />
</Box> </Box>
); );
} }

View File

@ -683,11 +683,11 @@ const PageEditor = ({
const displayedPages = displayDocument?.pages || []; const displayedPages = displayDocument?.pages || [];
return ( return (
<Box pos="relative" h="100vh" pt={40} style={{ overflow: 'auto' }} data-scrolling-container="true"> <Box pos="relative" h='100%' pt={40} style={{ overflow: 'auto' }} data-scrolling-container="true">
<LoadingOverlay visible={globalProcessing && !mergedPdfDocument} /> <LoadingOverlay visible={globalProcessing && !mergedPdfDocument} />
{!mergedPdfDocument && !globalProcessing && activeFileIds.length === 0 && ( {!mergedPdfDocument && !globalProcessing && activeFileIds.length === 0 && (
<Center h="100vh"> <Center h='100%'>
<Stack align="center" gap="md"> <Stack align="center" gap="md">
<Text size="lg" c="dimmed">📄</Text> <Text size="lg" c="dimmed">📄</Text>
<Text c="dimmed">No PDF files loaded</Text> <Text c="dimmed">No PDF files loaded</Text>

View File

@ -141,7 +141,7 @@ const PageEditorControls = ({
flexWrap: 'wrap', flexWrap: 'wrap',
justifyContent: 'center', justifyContent: 'center',
padding: "1rem", padding: "1rem",
paddingBottom: "2rem" paddingBottom: "1rem"
}} }}
> >

View File

@ -1,4 +1,4 @@
import { Flex, Text } from '@mantine/core'; import { Flex } from '@mantine/core';
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useCookieConsent } from '../../hooks/useCookieConsent'; import { useCookieConsent } from '../../hooks/useCookieConsent';
@ -16,7 +16,6 @@ export default function Footer({
privacyPolicy = '/privacy', privacyPolicy = '/privacy',
termsAndConditions = '/terms', termsAndConditions = '/terms',
accessibilityStatement = 'accessibility', accessibilityStatement = 'accessibility',
cookiePolicy = 'cookie',
analyticsEnabled = false analyticsEnabled = false
}: FooterProps) { }: FooterProps) {
const { t } = useTranslation(); const { t } = useTranslation();
@ -24,36 +23,19 @@ export default function Footer({
return ( return (
<div style={{ <div style={{
height: 'var(--footer-height)',
zIndex: 999999, zIndex: 999999,
backgroundColor: 'var(--mantine-color-gray-1)', backgroundColor: 'var(--mantine-color-gray-1)',
borderTop: '1px solid var(--mantine-color-gray-3)', borderTop: '1px solid var(--mantine-color-gray-2)',
paddingBottom: '0.5rem', display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
}}> }}>
<Flex pt='sm' gap="md" <Flex gap="md"
justify="center" justify="center"
align="center" align="center"
direction="row" direction="row"
wrap="wrap"
px="lg"
style={{ fontSize: '0.75rem' }}> style={{ fontSize: '0.75rem' }}>
<a
className="footer-link px-3"
id="licenses"
target="_blank"
rel="noopener noreferrer"
href="/licenses"
>
{t('licenses.nav', 'Licenses')}
</a>
<a
className="footer-link px-3"
id="releases"
target="_blank"
rel="noopener noreferrer"
href="/releases"
>
{t('releases.footer', 'Releases')}
</a>
<a <a
className="footer-link px-3" className="footer-link px-3"
id="survey" id="survey"
@ -103,7 +85,6 @@ export default function Footer({
</button> </button>
)} )}
</Flex> </Flex>
</div> </div>
); );
} }

View File

@ -36,13 +36,13 @@ const LandingPage = () => {
}; };
return ( return (
<Container size="70rem" p={0} h="102%" className="flex items-center justify-center" style={{ position: 'relative' }}> <Container size="70rem" p={0} h="100%" className="flex items-center justify-center" style={{ position: 'relative' }}>
{/* White PDF Page Background */} {/* White PDF Page Background */}
<Dropzone <Dropzone
onDrop={handleFileDrop} onDrop={handleFileDrop}
accept={["application/pdf", "application/zip", "application/x-zip-compressed"]} accept={["application/pdf", "application/zip", "application/x-zip-compressed"]}
multiple={true} multiple={true}
className="w-4/5 flex items-center justify-center h-[95vh]" className="w-4/5 flex items-center justify-center h-[95%]"
style={{ style={{
position: 'absolute', position: 'absolute',
left: '50%', left: '50%',

View File

@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next';
import { useToolSections } from '../../hooks/useToolSections'; import { useToolSections } from '../../hooks/useToolSections';
import SubcategoryHeader from './shared/SubcategoryHeader'; import SubcategoryHeader from './shared/SubcategoryHeader';
import NoToolsFound from './shared/NoToolsFound'; import NoToolsFound from './shared/NoToolsFound';
import "./toolPicker/ToolPicker.css";
interface SearchResultsProps { interface SearchResultsProps {
filteredTools: [string, ToolRegistryEntry][]; filteredTools: [string, ToolRegistryEntry][];
@ -21,11 +22,12 @@ const SearchResults: React.FC<SearchResultsProps> = ({ filteredTools, onSelect }
} }
return ( return (
<Stack p="sm" gap="xs"> <Stack p="sm" gap="xs"
className="tool-picker-scrollable">
{searchGroups.map(group => ( {searchGroups.map(group => (
<Box key={group.subcategoryId} w="100%"> <Box key={group.subcategoryId} w="100%">
<SubcategoryHeader label={getSubcategoryLabel(t, group.subcategoryId)} /> <SubcategoryHeader label={getSubcategoryLabel(t, group.subcategoryId)} />
<Stack gap="xs"> <Stack gap="xs">
{group.tools.map(({ id, tool }) => ( {group.tools.map(({ id, tool }) => (
<ToolButton <ToolButton
key={id} key={id}

View File

@ -72,17 +72,15 @@ export default function ToolPanel() {
{searchQuery.trim().length > 0 ? ( {searchQuery.trim().length > 0 ? (
// Searching view (replaces both picker and content) // Searching view (replaces both picker and content)
<div className="flex-1 flex flex-col"> <div className="flex-1 flex flex-col overflow-y-auto">
<div className="flex-1 min-h-0">
<SearchResults <SearchResults
filteredTools={filteredTools} filteredTools={filteredTools}
onSelect={handleToolSelect} onSelect={handleToolSelect}
/> />
</div>
</div> </div>
) : leftPanelView === 'toolPicker' ? ( ) : leftPanelView === 'toolPicker' ? (
// Tool Picker View // Tool Picker View
<div className="flex-1 flex flex-col"> <div className="flex-1 flex flex-col overflow-auto">
<ToolPicker <ToolPicker
selectedToolKey={selectedToolKey} selectedToolKey={selectedToolKey}
onSelect={handleToolSelect} onSelect={handleToolSelect}

View File

@ -91,7 +91,7 @@ const ToolPicker = ({ selectedToolKey, onSelect, filteredTools, isSearching = fa
return ( return (
<Box <Box
h="100vh" h="100%"
style={{ style={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",

View File

@ -1,8 +1,6 @@
.tool-picker-scrollable { .tool-picker-scrollable {
overflow-y: auto !important; overflow-y: auto !important;
overflow-x: hidden !important; overflow-x: hidden !important;
scrollbar-width: thin;
scrollbar-color: var(--mantine-color-gray-4) transparent;
} }
.tool-picker-scrollable::-webkit-scrollbar { .tool-picker-scrollable::-webkit-scrollbar {

View File

@ -439,7 +439,7 @@ const Viewer = ({
}, [pageImages]); }, [pageImages]);
return ( return (
<Box style={{ position: 'relative', height: '100vh', display: 'flex', flexDirection: 'column' }}> <Box style={{ position: 'relative', height: '100%', display: 'flex', flexDirection: 'column' }}>
{/* Close Button - Only show in preview mode */} {/* Close Button - Only show in preview mode */}
{onClose && previewFile && ( {onClose && previewFile && (
<ActionIcon <ActionIcon
@ -558,7 +558,7 @@ const Viewer = ({
radius="xl xl 0 0" radius="xl xl 0 0"
shadow="sm" shadow="sm"
p={12} p={12}
pb={24} pb={12}
style={{ style={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",

View File

@ -1,5 +1,11 @@
body { html, body {
margin: 0; margin: 0;
padding: 0;
height: 100%;
overflow-x: hidden;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif; sans-serif;
@ -12,9 +18,14 @@ code {
monospace; monospace;
} }
/* CSS Variables */
:root {
--footer-height: 2rem;
}
/* Footer link styling - make buttons and links look identical */ /* Footer link styling - make buttons and links look identical */
.footer-link { .footer-link {
color: var(--mantine-color-blue-6); color: var(--mantine-color-gray-6);
text-decoration: none; text-decoration: none;
transition: color 0.2s ease; transition: color 0.2s ease;
border: none; border: none;

View File

@ -39,12 +39,12 @@ export default function HomePage() {
// Note: File selection limits are now handled directly by individual tools // Note: File selection limits are now handled directly by individual tools
return ( return (
<div className="min-h-screen flex flex-col"> <div className="h-screen overflow-hidden">
<Group <Group
align="flex-start" align="flex-start"
gap={0} gap={0}
h="100%"
className="flex-nowrap flex" className="flex-nowrap flex"
style={{ minHeight: '100vh' }}
> >
<QuickAccessBar <QuickAccessBar
ref={quickAccessRef} /> ref={quickAccessRef} />
@ -53,7 +53,6 @@ export default function HomePage() {
<RightRail /> <RightRail />
<FileManager selectedTool={selectedTool as any /* FIX ME */} /> <FileManager selectedTool={selectedTool as any /* FIX ME */} />
</Group> </Group>
<Footer analyticsEnabled />
</div> </div>
); );
} }