Skip to content

Commit faf0d1a

Browse files
committed
replace react-tooltip against @floating-ui/react's tooltip
1 parent d70de21 commit faf0d1a

18 files changed

+312
-78
lines changed

client/admin/FolderAdmin.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import React, {
55
useRef,
66
useState
77
} from 'react';
8-
import {Tooltip} from 'react-tooltip';
98
import {
109
DndContext,
1110
DragOverlay,
@@ -407,6 +406,5 @@ export default function FolderAdmin() {
407406
</DragOverlay>
408407
</div>
409408
</DndContext>
410-
<Tooltip id="django-finder-tooltip" place="bottom-start" />
411409
</>);
412410
}

client/admin/FolderTabs.tsx

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {useDroppable} from '@dnd-kit/core';
22
import React, {forwardRef, useImperativeHandle, useState} from 'react';
3+
import {Tooltip, TooltipContent, TooltipTrigger} from '../common/Tooltip';
34
import CloseIcon from '../icons/close.svg';
45
import PinIcon from '../icons/pin.svg';
56
import RecycleIcon from '../icons/recycle.svg';
@@ -42,33 +43,61 @@ function FolderTab(props) {
4243
}
4344

4445
if (folder.id === 'return') return (
45-
<li ref={setNodeRef} className={cssClasses(folder)} data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Change to folder view")}>
46-
<a href={settings.folder_url}><UpIcon /></a>
47-
</li>
46+
<Tooltip placement="top-start">
47+
<TooltipTrigger>
48+
<li ref={setNodeRef} className={cssClasses(folder)}>
49+
<a href={settings.folder_url}><UpIcon /></a>
50+
</li>
51+
</TooltipTrigger>
52+
<TooltipContent>{gettext("Change to folder view")}</TooltipContent>
53+
</Tooltip>
4854
);
4955

5056
if (folder.id === 'parent') return (
51-
<li ref={setNodeRef} className={cssClasses(folder)} data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Change to parent folder")}>
52-
<a href={settings.parent_url}><UpIcon /></a>
53-
</li>
57+
<Tooltip placement="top-start">
58+
<TooltipTrigger>
59+
<li ref={setNodeRef} className={cssClasses(folder)}>
60+
<a href={settings.parent_url}><UpIcon /></a>
61+
</li>
62+
</TooltipTrigger>
63+
<TooltipContent>{gettext("Change to parent folder")}</TooltipContent>
64+
</Tooltip>
5465
);
5566

5667
if (folder.is_root) return (
57-
<li ref={setNodeRef} className={cssClasses(folder)} data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Root folder")}>
58-
{!isActive || isSearchResult ? <a href={folder.change_url}><RootIcon /></a> : <RootIcon />}
59-
</li>
68+
<Tooltip placement="top-start">
69+
<TooltipTrigger>
70+
<li ref={setNodeRef} className={cssClasses(folder)}>
71+
{!isActive || isSearchResult ? <a href={folder.change_url}><RootIcon /></a> : <RootIcon />}
72+
</li>
73+
</TooltipTrigger>
74+
<TooltipContent>{gettext("Root folder")}</TooltipContent>
75+
</Tooltip>
76+
);
77+
78+
const TrashFolder = () => (
79+
<Tooltip placement="top-end">
80+
<TooltipTrigger><RecycleIcon /></TooltipTrigger>
81+
<TooltipContent root={settings.rootNode}>{gettext("Trash folder")}</TooltipContent>
82+
</Tooltip>
6083
);
6184

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

6891
return (
6992
<li ref={setNodeRef} className={cssClasses(folder)}>
7093
{!isActive || isSearchResult || settings.download_url ? <a href={folder.change_url}>{folder.name}</a> : folder.name}
71-
<span onClick={togglePin.bind(folder)}>{folder.is_pinned ? <CloseIcon /> : <PinIcon data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Pin this folder")} />}</span>
94+
<span onClick={togglePin.bind(folder)}>{folder.is_pinned ?
95+
<CloseIcon /> :
96+
<Tooltip placement="top">
97+
<TooltipTrigger><PinIcon /></TooltipTrigger>
98+
<TooltipContent>{gettext("Pin this folder")}</TooltipContent>
99+
</Tooltip>
100+
}</span>
72101
</li>
73102
);
74103
}

client/admin/MenuBar.tsx

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import React, {
66
useEffect,
77
useImperativeHandle,
88
useMemo,
9-
useRef,
109
useState,
1110
} from 'react';
1211
import SearchField from './SearchField';
1312
import DropDownMenu from '../common/DropDownMenu';
1413
import FilterByLabel from '../common/FilterByLabel';
1514
import SortingOptions from '../common/SortingOptions';
15+
import {Tooltip, TooltipContent, TooltipTrigger} from '../common/Tooltip';
1616
import MoreVerticalIcon from '../icons/more-vertical.svg';
1717
import CopyIcon from '../icons/copy.svg';
1818
import TilesIcon from '../icons/tiles.svg';
@@ -130,6 +130,23 @@ function ExtraMenu(props) {
130130
}
131131

132132

133+
function MenuItem(props) {
134+
const {children, tooltip} = props;
135+
const itemProps = Object.fromEntries(Object.entries(props).filter(([key]) => !['children', 'tooltip'].includes(key)));
136+
137+
return (
138+
<Tooltip>
139+
<TooltipTrigger>
140+
<li {...itemProps} role="menuitem">
141+
{children}
142+
</li>
143+
</TooltipTrigger>
144+
<TooltipContent>{tooltip}</TooltipContent>
145+
</Tooltip>
146+
);
147+
}
148+
149+
133150
const MenuBar = forwardRef((props: any, forwardedRef) => {
134151
const {
135152
currentFolderId,
@@ -335,48 +352,37 @@ const MenuBar = forwardRef((props: any, forwardedRef) => {
335352
<li className="search-field" role="menuitem" style={{marginRight: 'auto'}}>
336353
<SearchField columnRefs={columnRefs} setSearchResult={setSearchResult} settings={settings}/>
337354
</li>
338-
<li aria-selected={layout === 'tiles'} onClick={() => setLayout('tiles')}
339-
role="menuitem" data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Tiles view")}>
355+
<MenuItem aria-selected={layout === 'tiles'} onClick={() => setLayout('tiles')} tooltip={gettext("Tiles view")}>
340356
<TilesIcon/>
341-
</li>
342-
<li aria-selected={layout === 'mosaic'} onClick={() => setLayout('mosaic')}
343-
role="menuitem" data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Mosaic view")}><MosaicIcon/>
344-
</li>
345-
<li aria-selected={layout === 'list'} onClick={() => setLayout('list')}
346-
role="menuitem" data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("List view")}><ListIcon/>
347-
</li>
348-
<li aria-selected={layout === 'columns'} onClick={() => setLayout('columns')}
349-
role="menuitem" data-tooltip-id="django-finder-tooltip" data-tooltip-content={gettext("Columns view")}>
357+
</MenuItem>
358+
<MenuItem aria-selected={layout === 'mosaic'} onClick={() => setLayout('mosaic')} tooltip={gettext("Mosaic view")}>
359+
<MosaicIcon/>
360+
</MenuItem>
361+
<MenuItem aria-selected={layout === 'list'} onClick={() => setLayout('list')} tooltip={gettext("List view")}>
362+
<ListIcon/>
363+
</MenuItem>
364+
<MenuItem aria-selected={layout === 'columns'} onClick={() => setLayout('columns')} tooltip={gettext("Columns view")}>
350365
<ColumnsIcon/>
351-
</li>
366+
</MenuItem>
352367
<SortingOptions refreshFilesList={refreshColumns} />
353368
{settings.labels && <FilterByLabel refreshFilesList={refreshColumns} labels={settings.labels} />}
354-
<li aria-disabled={numSelectedInodes === 0} onClick={cutInodes}
355-
role="menuitem" data-tooltip-id="django-finder-tooltip"
356-
data-tooltip-content={gettext("Cut selected to clipboard")}>
369+
<MenuItem aria-disabled={numSelectedInodes === 0} onClick={cutInodes} tooltip={gettext("Cut selected to clipboard")}>
357370
<CutIcon/>
358-
</li>
371+
</MenuItem>
359372
{settings.is_trash ? (<>
360-
<li aria-disabled={numSelectedInodes === 0} onClick={undoDiscardInodes}
361-
role="menuitem" data-tooltip-id="django-finder-tooltip"
362-
data-tooltip-content={gettext("Undo discarding files/folders")}>
363-
<UndoIcon/>
364-
</li>
365-
<li className="erase" onClick={confirmEraseTrashFolder} data-tooltip-id="django-finder-tooltip"
366-
role="menuitem" data-tooltip-content={gettext("Empty trash folder")}>
367-
<EraseIcon/>
368-
</li>
373+
<MenuItem aria-disabled={numSelectedInodes === 0} onClick={undoDiscardInodes} tooltip={gettext("Undo discarding files/folders")}>
374+
<UndoIcon/>
375+
</MenuItem>
376+
<MenuItem className="erase" onClick={confirmEraseTrashFolder} tooltip={gettext("Empty trash folder")}>
377+
<EraseIcon/>
378+
</MenuItem>
369379
</>) : (<>
370-
<li aria-disabled={clipboard.length === 0} onClick={pasteInodes}
371-
role="menuitem" data-tooltip-id="django-finder-tooltip"
372-
data-tooltip-content={gettext("Paste from clipboard")}>
380+
<MenuItem aria-disabled={clipboard.length === 0} onClick={pasteInodes} tooltip={gettext("Paste from clipboard")}>
373381
<PasteIcon/>
374-
</li>
375-
<li aria-disabled={numSelectedInodes === 0} onClick={deleteInodes}
376-
role="menuitem" data-tooltip-id="django-finder-tooltip"
377-
data-tooltip-content={gettext("Move selected to trash folder")}>
382+
</MenuItem>
383+
<MenuItem aria-disabled={numSelectedInodes === 0} onClick={deleteInodes} tooltip={gettext("Move selected to trash folder")}>
378384
<TrashIcon/>
379-
</li>
385+
</MenuItem>
380386
<ExtraMenu
381387
numSelectedFiles={numSelectedFiles}
382388
numSelectedInodes={numSelectedInodes}

client/admin/SearchField.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, {useRef, useState} from 'react';
22
import {useSearchRealm} from '../common/Storage';
33
import DropDownMenu from '../common/DropDownMenu';
4+
import {Tooltip, TooltipTrigger, TooltipContent} from '../common/Tooltip';
45
import SearchIcon from '../icons/search.svg';
56

67

@@ -91,12 +92,16 @@ export default function SearchField(props) {
9192
onKeyDown={handleSearch}
9293
/>
9394
<div>
94-
<span className="search-icon" onClick={handleSearch}><SearchIcon/></span>
95+
<Tooltip>
96+
<TooltipTrigger>
97+
<span className="search-icon" onClick={handleSearch}><SearchIcon/></span>
98+
</TooltipTrigger>
99+
<TooltipContent>{gettext("Search for file")}</TooltipContent>
100+
</Tooltip>
95101
<DropDownMenu
96102
wrapperElement="span"
97103
role="menuitem"
98104
className="search-realm with-caret"
99-
tooltip={gettext("Restrict search")}
100105
>
101106
<li {...getItemProps('current')}>{gettext("From current folder")}</li>
102107
<li {...getItemProps('everywhere')}>{gettext("In all folders")}</li>

client/browser/FileSelectDialog.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ const FilesList = memo((props: any) => {
9090
});
9191

9292

93-
const FileSelectDialog = forwardRef((props: any, forwardedRef)=> {
93+
const FileSelectDialog = forwardRef((props: any, forwardedRef) => {
9494
const {realm, baseUrl, csrfToken} = props;
9595
const [structure, setStructure] = useState({
9696
root_folder: null,
@@ -218,13 +218,13 @@ const FileSelectDialog = forwardRef((props: any, forwardedRef)=> {
218218
if (structure.last_folder !== folderId)
219219
throw new Error('Folder mismatch');
220220
setUploadedFile(uploadedFiles[0]);
221-
};
221+
}
222222

223223
const selectFile = useCallback(fileInfo => {
224224
props.selectFile(fileInfo);
225225
setUploadedFile(null);
226226
refreshFilesList();
227-
props.closeDialog();
227+
props.dialogRef.current.close();
228228
}, []);
229229

230230
function scrollToCurrentFolder() {
@@ -251,7 +251,7 @@ const FileSelectDialog = forwardRef((props: any, forwardedRef)=> {
251251
}
252252
setUploadedFile(null);
253253
refreshFilesList();
254-
props.closeDialog();
254+
props.dialogRef.current.close();
255255
}
256256

257257
console.log('FileSelectDialog', isDirty, structure);

client/browser/FinderFileSelect.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React, {useEffect, useRef, useState} from 'react';
22
import FileSelectDialog from './FileSelectDialog';
3-
import {Tooltip} from 'react-tooltip';
43

54

65
export default function FinderFileSelect(props) {
@@ -111,9 +110,8 @@ export default function FinderFileSelect(props) {
111110
baseUrl={baseUrl}
112111
csrfToken={csrfToken}
113112
selectFile={selectFile}
114-
closeDialog={() => dialogRef.current.close()}
113+
dialogRef={dialogRef}
115114
/>
116115
</dialog>
117-
<Tooltip id="django-finder-tooltip" place="bottom-start" />
118116
</>);
119117
}

client/browser/MenuBar.tsx

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
1-
import React, {forwardRef, useImperativeHandle, useRef} from 'react';
1+
import React, {forwardRef, useImperativeHandle, useMemo, useRef} from 'react';
22
import DropDownMenu from '../common/DropDownMenu';
33
import SortingOptions from '../common/SortingOptions';
44
import FilterByLabel from '../common/FilterByLabel';
55
import SearchIcon from '../icons/search.svg';
66
import UploadIcon from '../icons/upload.svg';
7+
import {Tooltip, TooltipContent, TooltipTrigger} from "../common/Tooltip";
78

89

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

15+
const rootNode = useMemo(() => {
16+
return ref.current?.getRootNode().querySelector('dialog');
17+
}, [ref.current]);
18+
1319
useImperativeHandle(forwardedRef, () => ({
1420
clearSearch: () => searchRef.current.value = '',
1521
}));
@@ -43,7 +49,7 @@ const MenuBar = forwardRef((props: any, forwardedRef) => {
4349
}
4450

4551
return (
46-
<ul role="menubar">
52+
<ul role="menubar" ref={ref}>
4753
<li role="menuitem" className="search-field">
4854
<input
4955
ref={searchRef}
@@ -53,12 +59,17 @@ const MenuBar = forwardRef((props: any, forwardedRef) => {
5359
onKeyDown={handleSearch}
5460
/>
5561
<div>
56-
<span className="search-icon" onClick={handleSearch}><SearchIcon/></span>
62+
<Tooltip>
63+
<TooltipTrigger>
64+
<span className="search-icon" onClick={handleSearch}><SearchIcon/></span>
65+
</TooltipTrigger>
66+
<TooltipContent root={rootNode}>{gettext("Search for file")}</TooltipContent>
67+
</Tooltip>
5768
<DropDownMenu
5869
role="menuitem"
5970
wrapperElement="span"
6071
className="search-realm with-caret"
61-
tooltip={gettext("Restrict search")}
72+
root={rootNode}
6273
>
6374
<li {...getItemProps('current')}>{gettext("From current folder")}</li>
6475
<li {...getItemProps('everywhere')}>{gettext("In all folders")}</li>
@@ -68,12 +79,16 @@ const MenuBar = forwardRef((props: any, forwardedRef) => {
6879
</DropDownMenu>
6980
</div>
7081
</li>
71-
<SortingOptions refreshFilesList={refreshFilesList} />
72-
{labels && <FilterByLabel refreshFilesList={refreshFilesList} labels={labels} />}
73-
<li role="menuitem" onClick={openUploader} data-tooltip-id="django-finder-tooltip"
74-
data-tooltip-content={gettext("Upload file")}>
75-
<UploadIcon/>
76-
</li>
82+
<SortingOptions refreshFilesList={refreshFilesList} root={rootNode} />
83+
{labels && <FilterByLabel refreshFilesList={refreshFilesList} labels={labels} root={rootNode} />}
84+
<Tooltip>
85+
<TooltipTrigger>
86+
<li role="menuitem" onClick={openUploader}>
87+
<UploadIcon/>
88+
</li>
89+
</TooltipTrigger>
90+
<TooltipContent root={rootNode}>{gettext("Upload file")}</TooltipContent>
91+
</Tooltip>
7792
</ul>
7893
);
7994
});

client/common/DropDownMenu.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React, {useEffect, useRef} from 'react';
2+
import {Tooltip, TooltipTrigger, TooltipContent} from '../common/Tooltip';
23

34

45
export default function DropDownMenu(props){
56
const ref = useRef(null);
6-
const Wrapper = props.wrapperElement ?? 'li';
7+
const WrapperElement = props.wrapperElement ?? 'li';
78

89
useEffect(() => {
910
const handleClick = (event) => {
@@ -38,19 +39,20 @@ export default function DropDownMenu(props){
3839
}, []);
3940

4041
return (
41-
<Wrapper
42+
<WrapperElement
4243
ref={ref}
4344
role={props.role ? `combobox ${props.role}` : 'combobox'}
4445
aria-haspopup="listbox"
4546
aria-expanded="false"
4647
className={props.className}
47-
data-tooltip-id="django-finder-tooltip"
48-
data-tooltip-content={props.tooltip}
4948
>
50-
{props.icon}
49+
<Tooltip>
50+
<TooltipTrigger><i>{props.icon}</i></TooltipTrigger>
51+
<TooltipContent root={props.root}>{props.tooltip}</TooltipContent>
5152
<ul role="listbox">
5253
{props.children}
5354
</ul>
54-
</Wrapper>
55+
</Tooltip>
56+
</WrapperElement>
5557
)
5658
}

0 commit comments

Comments
 (0)