Skip to content

Commit

Permalink
replace react-tooltip against @floating-ui/react's tooltip
Browse files Browse the repository at this point in the history
  • Loading branch information
jrief committed Jan 2, 2025
1 parent d70de21 commit faf0d1a
Show file tree
Hide file tree
Showing 18 changed files with 312 additions and 78 deletions.
2 changes: 0 additions & 2 deletions client/admin/FolderAdmin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import React, {
useRef,
useState
} from 'react';
import {Tooltip} from 'react-tooltip';
import {
DndContext,
DragOverlay,
Expand Down Expand Up @@ -407,6 +406,5 @@ export default function FolderAdmin() {
</DragOverlay>
</div>
</DndContext>
<Tooltip id="django-finder-tooltip" place="bottom-start" />
</>);
}
53 changes: 41 additions & 12 deletions client/admin/FolderTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {useDroppable} from '@dnd-kit/core';
import React, {forwardRef, useImperativeHandle, useState} from 'react';
import {Tooltip, TooltipContent, TooltipTrigger} from '../common/Tooltip';
import CloseIcon from '../icons/close.svg';
import PinIcon from '../icons/pin.svg';
import RecycleIcon from '../icons/recycle.svg';
Expand Down Expand Up @@ -42,33 +43,61 @@ function FolderTab(props) {
}

if (folder.id === 'return') return (
<li ref={setNodeRef} className={cssClasses(folder)} data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Change to folder view")}>
<a href={settings.folder_url}><UpIcon /></a>
</li>
<Tooltip placement="top-start">
<TooltipTrigger>
<li ref={setNodeRef} className={cssClasses(folder)}>
<a href={settings.folder_url}><UpIcon /></a>
</li>
</TooltipTrigger>
<TooltipContent>{gettext("Change to folder view")}</TooltipContent>
</Tooltip>
);

if (folder.id === 'parent') return (
<li ref={setNodeRef} className={cssClasses(folder)} data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Change to parent folder")}>
<a href={settings.parent_url}><UpIcon /></a>
</li>
<Tooltip placement="top-start">
<TooltipTrigger>
<li ref={setNodeRef} className={cssClasses(folder)}>
<a href={settings.parent_url}><UpIcon /></a>
</li>
</TooltipTrigger>
<TooltipContent>{gettext("Change to parent folder")}</TooltipContent>
</Tooltip>
);

if (folder.is_root) return (
<li ref={setNodeRef} className={cssClasses(folder)} data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Root folder")}>
{!isActive || isSearchResult ? <a href={folder.change_url}><RootIcon /></a> : <RootIcon />}
</li>
<Tooltip placement="top-start">
<TooltipTrigger>
<li ref={setNodeRef} className={cssClasses(folder)}>
{!isActive || isSearchResult ? <a href={folder.change_url}><RootIcon /></a> : <RootIcon />}
</li>
</TooltipTrigger>
<TooltipContent>{gettext("Root folder")}</TooltipContent>
</Tooltip>
);

const TrashFolder = () => (
<Tooltip placement="top-end">
<TooltipTrigger><RecycleIcon /></TooltipTrigger>
<TooltipContent root={settings.rootNode}>{gettext("Trash folder")}</TooltipContent>
</Tooltip>
);

if (folder.is_trash) return (
<li ref={setNodeRef} className={cssClasses(folder)} data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Trash folder")}>
{!isActive || isSearchResult ? <a href={folder.change_url}><RecycleIcon /></a> : <RecycleIcon />}
<li ref={setNodeRef} className={cssClasses(folder)}>
{!isActive || isSearchResult ? <a href={folder.change_url}><TrashFolder /></a> : <TrashFolder />}
</li>
);

return (
<li ref={setNodeRef} className={cssClasses(folder)}>
{!isActive || isSearchResult || settings.download_url ? <a href={folder.change_url}>{folder.name}</a> : folder.name}
<span onClick={togglePin.bind(folder)}>{folder.is_pinned ? <CloseIcon /> : <PinIcon data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Pin this folder")} />}</span>
<span onClick={togglePin.bind(folder)}>{folder.is_pinned ?
<CloseIcon /> :
<Tooltip placement="top">
<TooltipTrigger><PinIcon /></TooltipTrigger>
<TooltipContent>{gettext("Pin this folder")}</TooltipContent>
</Tooltip>
}</span>
</li>
);
}
Expand Down
74 changes: 40 additions & 34 deletions client/admin/MenuBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import React, {
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
} from 'react';
import SearchField from './SearchField';
import DropDownMenu from '../common/DropDownMenu';
import FilterByLabel from '../common/FilterByLabel';
import SortingOptions from '../common/SortingOptions';
import {Tooltip, TooltipContent, TooltipTrigger} from '../common/Tooltip';
import MoreVerticalIcon from '../icons/more-vertical.svg';
import CopyIcon from '../icons/copy.svg';
import TilesIcon from '../icons/tiles.svg';
Expand Down Expand Up @@ -130,6 +130,23 @@ function ExtraMenu(props) {
}


function MenuItem(props) {
const {children, tooltip} = props;
const itemProps = Object.fromEntries(Object.entries(props).filter(([key]) => !['children', 'tooltip'].includes(key)));

return (
<Tooltip>
<TooltipTrigger>
<li {...itemProps} role="menuitem">
{children}
</li>
</TooltipTrigger>
<TooltipContent>{tooltip}</TooltipContent>
</Tooltip>
);
}


const MenuBar = forwardRef((props: any, forwardedRef) => {
const {
currentFolderId,
Expand Down Expand Up @@ -335,48 +352,37 @@ const MenuBar = forwardRef((props: any, forwardedRef) => {
<li className="search-field" role="menuitem" style={{marginRight: 'auto'}}>
<SearchField columnRefs={columnRefs} setSearchResult={setSearchResult} settings={settings}/>
</li>
<li aria-selected={layout === 'tiles'} onClick={() => setLayout('tiles')}
role="menuitem" data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Tiles view")}>
<MenuItem aria-selected={layout === 'tiles'} onClick={() => setLayout('tiles')} tooltip={gettext("Tiles view")}>
<TilesIcon/>
</li>
<li aria-selected={layout === 'mosaic'} onClick={() => setLayout('mosaic')}
role="menuitem" data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Mosaic view")}><MosaicIcon/>
</li>
<li aria-selected={layout === 'list'} onClick={() => setLayout('list')}
role="menuitem" data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("List view")}><ListIcon/>
</li>
<li aria-selected={layout === 'columns'} onClick={() => setLayout('columns')}
role="menuitem" data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Columns view")}>
</MenuItem>
<MenuItem aria-selected={layout === 'mosaic'} onClick={() => setLayout('mosaic')} tooltip={gettext("Mosaic view")}>
<MosaicIcon/>
</MenuItem>
<MenuItem aria-selected={layout === 'list'} onClick={() => setLayout('list')} tooltip={gettext("List view")}>
<ListIcon/>
</MenuItem>
<MenuItem aria-selected={layout === 'columns'} onClick={() => setLayout('columns')} tooltip={gettext("Columns view")}>
<ColumnsIcon/>
</li>
</MenuItem>
<SortingOptions refreshFilesList={refreshColumns} />
{settings.labels && <FilterByLabel refreshFilesList={refreshColumns} labels={settings.labels} />}
<li aria-disabled={numSelectedInodes === 0} onClick={cutInodes}
role="menuitem" data-tooltip-id="django-finder-tooltip"
data-tooltip-content={gettext("Cut selected to clipboard")}>
<MenuItem aria-disabled={numSelectedInodes === 0} onClick={cutInodes} tooltip={gettext("Cut selected to clipboard")}>
<CutIcon/>
</li>
</MenuItem>
{settings.is_trash ? (<>
<li aria-disabled={numSelectedInodes === 0} onClick={undoDiscardInodes}
role="menuitem" data-tooltip-id="django-finder-tooltip"
data-tooltip-content={gettext("Undo discarding files/folders")}>
<UndoIcon/>
</li>
<li className="erase" onClick={confirmEraseTrashFolder} data-tooltip-id="django-finder-tooltip"
role="menuitem" data-tooltip-content={gettext("Empty trash folder")}>
<EraseIcon/>
</li>
<MenuItem aria-disabled={numSelectedInodes === 0} onClick={undoDiscardInodes} tooltip={gettext("Undo discarding files/folders")}>
<UndoIcon/>
</MenuItem>
<MenuItem className="erase" onClick={confirmEraseTrashFolder} tooltip={gettext("Empty trash folder")}>
<EraseIcon/>
</MenuItem>
</>) : (<>
<li aria-disabled={clipboard.length === 0} onClick={pasteInodes}
role="menuitem" data-tooltip-id="django-finder-tooltip"
data-tooltip-content={gettext("Paste from clipboard")}>
<MenuItem aria-disabled={clipboard.length === 0} onClick={pasteInodes} tooltip={gettext("Paste from clipboard")}>
<PasteIcon/>
</li>
<li aria-disabled={numSelectedInodes === 0} onClick={deleteInodes}
role="menuitem" data-tooltip-id="django-finder-tooltip"
data-tooltip-content={gettext("Move selected to trash folder")}>
</MenuItem>
<MenuItem aria-disabled={numSelectedInodes === 0} onClick={deleteInodes} tooltip={gettext("Move selected to trash folder")}>
<TrashIcon/>
</li>
</MenuItem>
<ExtraMenu
numSelectedFiles={numSelectedFiles}
numSelectedInodes={numSelectedInodes}
Expand Down
9 changes: 7 additions & 2 deletions client/admin/SearchField.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, {useRef, useState} from 'react';
import {useSearchRealm} from '../common/Storage';
import DropDownMenu from '../common/DropDownMenu';
import {Tooltip, TooltipTrigger, TooltipContent} from '../common/Tooltip';
import SearchIcon from '../icons/search.svg';


Expand Down Expand Up @@ -91,12 +92,16 @@ export default function SearchField(props) {
onKeyDown={handleSearch}
/>
<div>
<span className="search-icon" onClick={handleSearch}><SearchIcon/></span>
<Tooltip>
<TooltipTrigger>
<span className="search-icon" onClick={handleSearch}><SearchIcon/></span>
</TooltipTrigger>
<TooltipContent>{gettext("Search for file")}</TooltipContent>
</Tooltip>
<DropDownMenu
wrapperElement="span"
role="menuitem"
className="search-realm with-caret"
tooltip={gettext("Restrict search")}
>
<li {...getItemProps('current')}>{gettext("From current folder")}</li>
<li {...getItemProps('everywhere')}>{gettext("In all folders")}</li>
Expand Down
8 changes: 4 additions & 4 deletions client/browser/FileSelectDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const FilesList = memo((props: any) => {
});


const FileSelectDialog = forwardRef((props: any, forwardedRef)=> {
const FileSelectDialog = forwardRef((props: any, forwardedRef) => {
const {realm, baseUrl, csrfToken} = props;
const [structure, setStructure] = useState({
root_folder: null,
Expand Down Expand Up @@ -218,13 +218,13 @@ const FileSelectDialog = forwardRef((props: any, forwardedRef)=> {
if (structure.last_folder !== folderId)
throw new Error('Folder mismatch');
setUploadedFile(uploadedFiles[0]);
};
}

const selectFile = useCallback(fileInfo => {
props.selectFile(fileInfo);
setUploadedFile(null);
refreshFilesList();
props.closeDialog();
props.dialogRef.current.close();
}, []);

function scrollToCurrentFolder() {
Expand All @@ -251,7 +251,7 @@ const FileSelectDialog = forwardRef((props: any, forwardedRef)=> {
}
setUploadedFile(null);
refreshFilesList();
props.closeDialog();
props.dialogRef.current.close();
}

console.log('FileSelectDialog', isDirty, structure);
Expand Down
4 changes: 1 addition & 3 deletions client/browser/FinderFileSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, {useEffect, useRef, useState} from 'react';
import FileSelectDialog from './FileSelectDialog';
import {Tooltip} from 'react-tooltip';


export default function FinderFileSelect(props) {
Expand Down Expand Up @@ -111,9 +110,8 @@ export default function FinderFileSelect(props) {
baseUrl={baseUrl}
csrfToken={csrfToken}
selectFile={selectFile}
closeDialog={() => dialogRef.current.close()}
dialogRef={dialogRef}
/>
</dialog>
<Tooltip id="django-finder-tooltip" place="bottom-start" />
</>);
}
35 changes: 25 additions & 10 deletions client/browser/MenuBar.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import React, {forwardRef, useImperativeHandle, useRef} from 'react';
import React, {forwardRef, useImperativeHandle, useMemo, useRef} from 'react';
import DropDownMenu from '../common/DropDownMenu';
import SortingOptions from '../common/SortingOptions';
import FilterByLabel from '../common/FilterByLabel';
import SearchIcon from '../icons/search.svg';
import UploadIcon from '../icons/upload.svg';
import {Tooltip, TooltipContent, TooltipTrigger} from "../common/Tooltip";


const MenuBar = forwardRef((props: any, forwardedRef) => {
const {openUploader, labels, refreshFilesList, setDirty, setSearchQuery, searchRealm, setSearchRealm} = props;
const ref = useRef(null);
const searchRef = useRef(null);

const rootNode = useMemo(() => {
return ref.current?.getRootNode().querySelector('dialog');
}, [ref.current]);

useImperativeHandle(forwardedRef, () => ({
clearSearch: () => searchRef.current.value = '',
}));
Expand Down Expand Up @@ -43,7 +49,7 @@ const MenuBar = forwardRef((props: any, forwardedRef) => {
}

return (
<ul role="menubar">
<ul role="menubar" ref={ref}>
<li role="menuitem" className="search-field">
<input
ref={searchRef}
Expand All @@ -53,12 +59,17 @@ const MenuBar = forwardRef((props: any, forwardedRef) => {
onKeyDown={handleSearch}
/>
<div>
<span className="search-icon" onClick={handleSearch}><SearchIcon/></span>
<Tooltip>
<TooltipTrigger>
<span className="search-icon" onClick={handleSearch}><SearchIcon/></span>
</TooltipTrigger>
<TooltipContent root={rootNode}>{gettext("Search for file")}</TooltipContent>
</Tooltip>
<DropDownMenu
role="menuitem"
wrapperElement="span"
className="search-realm with-caret"
tooltip={gettext("Restrict search")}
root={rootNode}
>
<li {...getItemProps('current')}>{gettext("From current folder")}</li>
<li {...getItemProps('everywhere')}>{gettext("In all folders")}</li>
Expand All @@ -68,12 +79,16 @@ const MenuBar = forwardRef((props: any, forwardedRef) => {
</DropDownMenu>
</div>
</li>
<SortingOptions refreshFilesList={refreshFilesList} />
{labels && <FilterByLabel refreshFilesList={refreshFilesList} labels={labels} />}
<li role="menuitem" onClick={openUploader} data-tooltip-id="django-finder-tooltip"
data-tooltip-content={gettext("Upload file")}>
<UploadIcon/>
</li>
<SortingOptions refreshFilesList={refreshFilesList} root={rootNode} />
{labels && <FilterByLabel refreshFilesList={refreshFilesList} labels={labels} root={rootNode} />}
<Tooltip>
<TooltipTrigger>
<li role="menuitem" onClick={openUploader}>
<UploadIcon/>
</li>
</TooltipTrigger>
<TooltipContent root={rootNode}>{gettext("Upload file")}</TooltipContent>
</Tooltip>
</ul>
);
});
Expand Down
14 changes: 8 additions & 6 deletions client/common/DropDownMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, {useEffect, useRef} from 'react';
import {Tooltip, TooltipTrigger, TooltipContent} from '../common/Tooltip';


export default function DropDownMenu(props){
const ref = useRef(null);
const Wrapper = props.wrapperElement ?? 'li';
const WrapperElement = props.wrapperElement ?? 'li';

useEffect(() => {
const handleClick = (event) => {
Expand Down Expand Up @@ -38,19 +39,20 @@ export default function DropDownMenu(props){
}, []);

return (
<Wrapper
<WrapperElement
ref={ref}
role={props.role ? `combobox ${props.role}` : 'combobox'}
aria-haspopup="listbox"
aria-expanded="false"
className={props.className}
data-tooltip-id="django-finder-tooltip"
data-tooltip-content={props.tooltip}
>
{props.icon}
<Tooltip>
<TooltipTrigger><i>{props.icon}</i></TooltipTrigger>
<TooltipContent root={props.root}>{props.tooltip}</TooltipContent>
<ul role="listbox">
{props.children}
</ul>
</Wrapper>
</Tooltip>
</WrapperElement>
)
}
Loading

0 comments on commit faf0d1a

Please sign in to comment.