feat: Add an icon size slider component and implement dynamic icon sizing for document views, while refactoring the documents panel layout.

This commit is contained in:
2025-12-01 23:42:43 +01:00
parent 033026f57c
commit 601ced5981
3 changed files with 66 additions and 16 deletions
@@ -0,0 +1,31 @@
import React from 'react';
interface IconSizeSliderProps {
scale: number;
onChange: (scale: number) => void;
min?: number;
max?: number;
}
const IconSizeSlider: React.FC<IconSizeSliderProps> = ({
scale,
onChange,
min = 0.5,
max = 2,
}) => {
return (
<div className="icon-size-slider">
<input
type="range"
className="icon-size-slider__input"
min={min}
max={max}
step="any"
value={scale}
onChange={(e) => onChange(parseFloat(e.target.value))}
/>
</div>
);
};
export default IconSizeSlider;
+27 -16
View File
@@ -1,4 +1,10 @@
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import React, {
useCallback,
useMemo,
useState,
useRef,
useEffect,
} from 'react';
import { DocumentsList, DocumentsGrid } from '../DocumentsView';
import type { DragEvent, ReactNode, RefObject } from 'react';
import type {
@@ -162,7 +168,6 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
const showingSearchResults = Array.isArray(searchResultIds);
const rows = showingSearchResults && searchDocuments ? searchDocuments : documents;
const searchResultCount = Array.isArray(searchResultIds) ? searchResultIds.length : 0;
const viewId = useMemo(() => {
if (showingSearchResults) {
@@ -185,9 +190,7 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
const headerTitle = showingSearchResults
? 'Search results'
: currentFolderName || 'Documents';
const headerSubtitle = showingSearchResults
? `${searchResultCount} matching document${searchResultCount === 1 ? '' : 's'}`
: null;
const headerSubtitle = null;
const headerActions = useMemo(
() => createDocumentsTableHeaderActions({
viewMode,
@@ -320,7 +323,6 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
const suppressDocumentClickRef = useRef(false);
const isGridView = viewMode === 'grid';
const isDeskView = viewMode === 'desk';
const gridIconSize = DEFAULT_GRID_ICON_SIZE;
const { openPreview } = usePreviewContext();
@@ -472,6 +474,13 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
onEntryPointer,
};
const [iconSizes] = useState({
list: DEFAULT_LIST_ICON_SIZE,
grid: DEFAULT_GRID_ICON_SIZE,
desk: DEFAULT_DESKTOP_CARD_SIZE,
});
const renderBody = () => {
const hasEntries = entries.length > 0;
const isSearchEmpty = (showingSearchResults || isFilterActive) && !hasDocumentEntries && !isSearchLoading;
@@ -494,12 +503,12 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
switch (viewMode) {
case 'desk':
return <DesktopWorkspace {...viewProps} defaultCardSize={DEFAULT_DESKTOP_CARD_SIZE} />;
return <DesktopWorkspace {...viewProps} defaultCardSize={iconSizes.desk} />;
case 'grid':
return <DocumentsGrid {...viewProps} iconSize={gridIconSize} />;
return <DocumentsGrid {...viewProps} iconSize={iconSizes.grid} />;
case 'list':
default:
return <DocumentsList {...viewProps} iconSize={DEFAULT_LIST_ICON_SIZE} />;
return <DocumentsList {...viewProps} iconSize={iconSizes.list} />;
}
};
@@ -519,13 +528,15 @@ const DocumentsPanelInner: React.FC<DocumentsPanelInnerProps> = ({
header={headerConfig}
onBreadcrumbClick={onBreadcrumbNavigate}
/>
<section
ref={scrollRef}
className={`documents-panel documents-panel--view-${panelVariant}`}
onClick={handleSectionClick}
>
{renderBody()}
</section>
<div className="documents-panel-wrapper">
<section
ref={scrollRef}
className={`documents-panel documents-panel--view-${panelVariant}`}
onClick={handleSectionClick}
>
{renderBody()}
</section>
</div>
</>
);
};
@@ -805,4 +805,12 @@
padding: 1rem;
text-align: center;
color: var(--muted);
}
.documents-panel-wrapper {
position: relative;
display: flex;
flex-direction: column;
flex: 1 1 auto;
min-height: 0;
}