From 0b9108c2363619768cfe729d2c2f173936a0cc55 Mon Sep 17 00:00:00 2001 From: Arnei Date: Thu, 18 Dec 2025 12:24:34 +0100 Subject: [PATCH] Switch to react-tooltips Replaces our mui tooltip wrapper with react-tooltip. Also adds back tooltips that were commented out. The reason for this change is that tooltips from react-tooltip are much more performant when used in larger quantities. It will still add about ~100ms to the render time of events or series tables with a 100 elements, which is not great but hardly noticable with our load times of over a second. --- package-lock.json | 39 +++++++++- package.json | 3 +- src/App.tsx | 8 ++ src/components/Footer.tsx | 7 +- src/components/Header.tsx | 73 ++++++++---------- .../partials/ThemesActionsCell.tsx | 4 +- .../events/partials/EventActionCell.tsx | 42 +++++----- .../events/partials/EventsDateCell.tsx | 2 +- .../events/partials/EventsLocationCell.tsx | 2 +- .../events/partials/EventsPresentersCell.tsx | 2 +- .../events/partials/EventsSeriesCell.tsx | 2 +- .../events/partials/EventsStatusCell.tsx | 2 +- .../EventDetailsWorkflowTab.tsx | 5 +- .../ModalTabsAndPages/NewTobiraPage.tsx | 11 +-- .../events/partials/PublishedCell.tsx | 8 +- .../events/partials/SeriesActionsCell.tsx | 4 +- .../partials/SeriesContributorsCell.tsx | 2 +- .../events/partials/SeriesDateTimeCell.tsx | 2 +- .../events/partials/SeriesOrganizersCell.tsx | 2 +- .../events/partials/SeriesTitleCell.tsx | 2 +- .../partials/RecordingsActionCell.tsx | 4 +- .../partials/RecordingsNameCell.tsx | 2 +- src/components/shared/BaseButton.tsx | 23 +++--- src/components/shared/MainNav.tsx | 11 +-- src/components/shared/SaveEditFooter.tsx | 20 +++-- src/components/shared/Tooltip.tsx | 76 ------------------- .../systems/partials/ServicesActionsCell.tsx | 2 +- .../users/partials/AclsActionsCell.tsx | 4 +- .../users/partials/GroupsActionsCell.tsx | 4 +- .../users/partials/UsersActionsCell.tsx | 4 +- src/styles/components/_tooltips.scss | 12 ++- 31 files changed, 161 insertions(+), 223 deletions(-) delete mode 100644 src/components/shared/Tooltip.tsx diff --git a/package-lock.json b/package-lock.json index 3638a2f84e..fc21e7352e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,12 +33,13 @@ "react-datepicker": "^8.8.0", "react-dom": "^19.2.4", "react-hotkeys-hook": "^5.2.4", - "react-i18next": "^16.5.4", + "react-i18next": "^16.5.0", "react-icons": "^5.5.0", "react-redux": "^9.2.0", "react-router": "^7.13.0", "react-select": "^5.10.2", "react-textarea-autosize": "^8.5.9", + "react-tooltip": "^5.30.0", "react-window": "^2.2.7", "redux": "^5.0.1", "redux-persist": "^6.0.0", @@ -101,6 +102,7 @@ "version": "7.24.6", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.6", @@ -413,6 +415,7 @@ "node_modules/@emotion/react": { "version": "11.14.0", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -455,6 +458,7 @@ "version": "11.14.1", "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -1247,8 +1251,7 @@ }, "node_modules/@kurkle/color": { "version": "0.3.2", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@mui/core-downloads-tracker": { "version": "7.3.8", @@ -2690,6 +2693,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -2699,6 +2703,7 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -2775,6 +2780,7 @@ "integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.56.0", "@typescript-eslint/types": "8.56.0", @@ -3145,6 +3151,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3426,6 +3433,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001629", "electron-to-chromium": "^1.4.796", @@ -4136,6 +4144,7 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4897,6 +4906,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.4" }, @@ -6032,6 +6042,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -6172,6 +6183,20 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/react-tooltip": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.30.0.tgz", + "integrity": "sha512-Yn8PfbgQ/wmqnL7oBpz1QiDaLKrzZMdSUUdk7nVeGTwzbxCAJiJzR4VSYW+eIO42F1INt57sPUmpgKv0KwJKtg==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.6.1", + "classnames": "^2.3.0" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "license": "BSD-3-Clause", @@ -6210,7 +6235,8 @@ }, "node_modules/redux": { "version": "5.0.1", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/redux-persist": { "version": "6.0.0", @@ -6295,6 +6321,7 @@ "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -6804,6 +6831,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -6965,6 +6993,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7125,6 +7154,7 @@ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -7267,6 +7297,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, diff --git a/package.json b/package.json index ad0b798a4f..aefacb3792 100644 --- a/package.json +++ b/package.json @@ -30,12 +30,13 @@ "react-datepicker": "^8.8.0", "react-dom": "^19.2.4", "react-hotkeys-hook": "^5.2.4", - "react-i18next": "^16.5.4", + "react-i18next": "^16.5.0", "react-icons": "^5.5.0", "react-redux": "^9.2.0", "react-router": "^7.13.0", "react-select": "^5.10.2", "react-textarea-autosize": "^8.5.9", + "react-tooltip": "^5.30.0", "react-window": "^2.2.7", "redux": "^5.0.1", "redux-persist": "^6.0.0", diff --git a/src/App.tsx b/src/App.tsx index 81c18f7daa..3f1a0b7a1c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -17,6 +17,7 @@ import { useAppDispatch } from "./store"; import { fetchOcVersion, fetchUserInfo } from "./slices/userInfoSlice"; import { subscribeToAuthEvents } from "./utils/broadcastSync"; import { useTableFilterStateValidation } from "./hooks/useTableFilterStateValidation"; +import { Tooltip } from "react-tooltip"; function App() { const dispatch = useAppDispatch(); @@ -74,6 +75,13 @@ function App() { element={} /> + ); } diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 1daea7009a..5526ee6140 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -6,7 +6,6 @@ import { import { useAppSelector } from "../store"; import { Link } from "react-router"; import { useTranslation } from "react-i18next"; -import { Tooltip } from "./shared/Tooltip"; /** * Component that renders the footer @@ -35,14 +34,14 @@ const Footer: React.FC = () => { {user.ocVersion && (
  • {"Opencast "} - {version} + {version} {user.isAdmin && ( {user.ocVersion.buildNumber && ( - <>{" – "} {user.ocVersion.buildNumber} + <>{" – "} {user.ocVersion.buildNumber} )} {lastModified && ( - <>{" – "} {t("BUILD.BUILT_ON")} {lastModified} + <>{" – "} {t("BUILD.BUILT_ON")} {lastModified} )} )} diff --git a/src/components/Header.tsx b/src/components/Header.tsx index abc054a621..145ba57ad4 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -20,7 +20,6 @@ import { useHotkeys } from "react-hotkeys-hook"; import { useAppDispatch, useAppSelector } from "../store"; import { HealthStatus, fetchHealthStatus } from "../slices/healthSlice"; import { UserInfoState } from "../slices/userInfoSlice"; -import { Tooltip } from "./shared/Tooltip"; import { HiOutlineTranslate } from "react-icons/hi"; import ButtonLikeAnchor from "./shared/ButtonLikeAnchor"; import { ModalHandle } from "./shared/modals/Modal"; @@ -160,11 +159,9 @@ const Header = () => {