diff --git a/src/common/MetaPreview/ActionButton/ActionButton.js b/src/common/MetaPreview/ActionButton/ActionButton.js
index f1120e054..8e2fcd11b 100644
--- a/src/common/MetaPreview/ActionButton/ActionButton.js
+++ b/src/common/MetaPreview/ActionButton/ActionButton.js
@@ -6,7 +6,7 @@ const classnames = require('classnames');
const { default: Icon } = require('@stremio/stremio-icons/react');
const Button = require('stremio/common/Button');
const styles = require('./styles');
-const { Tooltip } = require('stremio/common/Tooltip');
+const { Tooltip } = require('stremio/common/Tooltips');
const ActionButton = ({ className, icon, label, tooltip, ...props }) => {
return (
diff --git a/src/common/Tooltip/TooltipProvider.js b/src/common/Tooltip/TooltipProvider.js
deleted file mode 100644
index c19780248..000000000
--- a/src/common/Tooltip/TooltipProvider.js
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (C) 2017-2023 Smart code 203358507
-
-const React = require('react');
-const { useState, createRef } = require('react');
-const PropTypes = require('prop-types');
-const classNames = require('classnames');
-const TooltipContext = require('./TooltipContext');
-const styles = require('./styles');
-
-const TooltipProvider = ({ children, className }) => {
- const [tooltips, setTooltips] = useState([]);
-
- const add = ({ id, label, position, margin = 15, parent }) => {
- const ref = createRef(null);
-
- const tooltip = {
- ref,
- id,
- label,
- position,
- margin: margin,
- active: false,
- parent,
- };
-
- setTooltips((tooltips) => ([
- ...tooltips,
- tooltip,
- ]));
- };
-
- const remove = (id) => {
- setTooltips((tooltips) => (
- tooltips.filter((tooltip) => tooltip.id !== id)
- ));
- };
-
- const toggle = (id, state) => {
- setTooltips((tooltips) => (
- tooltips.map((tooltip) => {
- if (tooltip.id === id) {
- tooltip.active = state;
- }
- return tooltip;
- })
- ));
- };
-
- const style = (ref, position, margin, active, parent) => {
- if (!active) return {};
-
- const tooltipHeight = ref.current?.offsetHeight ?? 0;
- const tooltipWidth = ref.current?.offsetWidth ?? 0;
- const parentBounds = parent.getBoundingClientRect();
-
- switch (position) {
- case 'top':
- return {
- top: `${parentBounds.top - tooltipHeight - margin}px`,
- left: `${(parentBounds.left + (parentBounds.width / 2)) - (tooltipWidth / 2)}px`,
- };
- case 'bottom':
- return {
- top: `${parentBounds.top + parentBounds.height + margin}px`,
- left: `${(parentBounds.left + (parentBounds.width / 2)) - (tooltipWidth / 2)}px`,
- };
- case 'left':
- return {
- top: `${parentBounds.top + (parentBounds.height / 2) - (tooltipHeight / 2)}px`,
- left: `${(parentBounds.left - tooltipWidth - margin)}px`,
- };
- case 'right':
- return {
- top: `${parentBounds.top + (parentBounds.height / 2) - (tooltipHeight / 2)}px`,
- left: `${(parentBounds.left + parentBounds.width + margin)}px`,
- };
- }
- };
-
- return (
-
- { children }
-
- {
- tooltips.map(({ ref, id, label, position, margin, active, parent }) => (
-
- { label }
-
- ))
- }
-
-
- );
-};
-
-TooltipProvider.propTypes = {
- children: PropTypes.node,
- className: PropTypes.string,
-};
-
-module.exports = TooltipProvider;
diff --git a/src/common/Tooltip/Tooltip.js b/src/common/Tooltips/Tooltip/Tooltip.js
similarity index 77%
rename from src/common/Tooltip/Tooltip.js
rename to src/common/Tooltips/Tooltip/Tooltip.js
index 40316c484..7f0c5bdad 100644
--- a/src/common/Tooltip/Tooltip.js
+++ b/src/common/Tooltips/Tooltip/Tooltip.js
@@ -2,25 +2,35 @@
const React = require('react');
const PropTypes = require('prop-types');
-const useTooltip = require('./useTooltip');
+const useTooltip = require('../useTooltip');
const styles = require('./styles');
const createId = () => (Math.random() + 1).toString(36).substring(7);
-const Tooltip = ({ label, position, margin }) => {
+const Tooltip = ({ label, position, margin = 15 }) => {
const tooltip = useTooltip();
const id = React.useRef(createId());
const element = React.useRef(null);
const onMouseEnter = () => {
- tooltip.toggle(id.current, true);
+ tooltip.update(id.current, {
+ active: true,
+ });
};
const onMouseLeave = () => {
- tooltip.toggle(id.current, false);
+ tooltip.update(id.current, {
+ active: false,
+ });
};
+ React.useEffect(() => {
+ tooltip.update(id.current, {
+ label,
+ });
+ }, [label]);
+
React.useLayoutEffect(() => {
if (element.current && element.current.parentElement) {
const parentElement = element.current.parentElement;
@@ -45,15 +55,13 @@ const Tooltip = ({ label, position, margin }) => {
tooltip.remove(id.current);
}
};
- }, [label]);
+ }, []);
return (
-
+
);
};
-Tooltip.displayName = 'Tooltip';
-
Tooltip.propTypes = {
label: PropTypes.string.isRequired,
position: PropTypes.string.isRequired,
diff --git a/src/common/Tooltips/Tooltip/index.js b/src/common/Tooltips/Tooltip/index.js
new file mode 100644
index 000000000..c2972e079
--- /dev/null
+++ b/src/common/Tooltips/Tooltip/index.js
@@ -0,0 +1,6 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+const Tooltip = require('./Tooltip');
+
+module.exports = Tooltip;
+
diff --git a/src/common/Tooltips/Tooltip/styles.less b/src/common/Tooltips/Tooltip/styles.less
new file mode 100644
index 000000000..bfe64c47c
--- /dev/null
+++ b/src/common/Tooltips/Tooltip/styles.less
@@ -0,0 +1,11 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+.tooltip-placeholder {
+ z-index: -1;
+ visibility: hidden;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
\ No newline at end of file
diff --git a/src/common/Tooltip/TooltipContext.js b/src/common/Tooltips/TooltipContext.js
similarity index 100%
rename from src/common/Tooltip/TooltipContext.js
rename to src/common/Tooltips/TooltipContext.js
diff --git a/src/common/Tooltips/TooltipItem/TooltipItem.js b/src/common/Tooltips/TooltipItem/TooltipItem.js
new file mode 100644
index 000000000..38c6e6455
--- /dev/null
+++ b/src/common/Tooltips/TooltipItem/TooltipItem.js
@@ -0,0 +1,72 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+const React = require('react');
+const PropTypes = require('prop-types');
+const classNames = require('classnames');
+const styles = require('./styles');
+
+const TooltipItem = React.memo(({ className, active, label, position, margin, parent }) => {
+ const ref = React.useRef(null);
+ const timeout = React.useRef(null);
+
+ const [style, setStyle] = React.useState({});
+
+ React.useEffect(() => {
+ clearTimeout(timeout.current);
+
+ timeout.current = setTimeout(() => {
+ if (active && ref.current) {
+ const tooltipBounds = ref.current.getBoundingClientRect();
+ const parentBounds = parent.getBoundingClientRect();
+
+ switch (position) {
+ case 'top':
+ return setStyle({
+ top: `${parentBounds.top - tooltipBounds.height - margin}px`,
+ left: `${(parentBounds.left + (parentBounds.width / 2)) - (tooltipBounds.width / 2)}px`,
+ });
+ case 'bottom':
+ return setStyle({
+ top: `${parentBounds.top + parentBounds.height + margin}px`,
+ left: `${(parentBounds.left + (parentBounds.width / 2)) - (tooltipBounds.width / 2)}px`,
+ });
+ case 'left':
+ return setStyle({
+ top: `${parentBounds.top + (parentBounds.height / 2) - (tooltipBounds.height / 2)}px`,
+ left: `${(parentBounds.left - tooltipBounds.width - margin)}px`,
+ });
+ case 'right':
+ return setStyle({
+ top: `${parentBounds.top + (parentBounds.height / 2) - (tooltipBounds.height / 2)}px`,
+ left: `${(parentBounds.left + parentBounds.width + margin)}px`,
+ });
+ }
+ }
+ });
+
+ return () => clearTimeout(timeout.current);
+ }, [active, position, margin, parent, label]);
+
+ return (
+
+ { label }
+
+ );
+});
+
+TooltipItem.displayName = 'TooltipItem';
+
+TooltipItem.propTypes = {
+ className: PropTypes.string,
+ active: PropTypes.bool,
+ label: PropTypes.string,
+ position: PropTypes.string,
+ margin: PropTypes.number,
+ parent: PropTypes.instanceOf(HTMLElement),
+};
+
+module.exports = TooltipItem;
diff --git a/src/common/Tooltips/TooltipItem/index.js b/src/common/Tooltips/TooltipItem/index.js
new file mode 100644
index 000000000..04eb64174
--- /dev/null
+++ b/src/common/Tooltips/TooltipItem/index.js
@@ -0,0 +1,6 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+const TooltipItem = require('./TooltipItem');
+
+module.exports = TooltipItem;
+
diff --git a/src/common/Tooltip/styles.less b/src/common/Tooltips/TooltipItem/styles.less
similarity index 55%
rename from src/common/Tooltip/styles.less
rename to src/common/Tooltips/TooltipItem/styles.less
index d69825b71..4fcbecbb9 100644
--- a/src/common/Tooltip/styles.less
+++ b/src/common/Tooltips/TooltipItem/styles.less
@@ -1,16 +1,6 @@
// Copyright (C) 2017-2023 Smart code 203358507
-.tooltip {
- z-index: -1;
- visibility: hidden;
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
-}
-
-.tooltip-container {
+.tooltip-item {
position: fixed;
visibility: hidden;
opacity: 0;
diff --git a/src/common/Tooltips/TooltipProvider.js b/src/common/Tooltips/TooltipProvider.js
new file mode 100644
index 000000000..b52ed0c26
--- /dev/null
+++ b/src/common/Tooltips/TooltipProvider.js
@@ -0,0 +1,66 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+const React = require('react');
+const PropTypes = require('prop-types');
+const TooltipContext = require('./TooltipContext');
+const TooltipItem = require('./TooltipItem');
+
+const TooltipProvider = ({ children, className }) => {
+ const [tooltips, setTooltips] = React.useState([]);
+
+ const add = (options) => {
+ const tooltip = {
+ ...options,
+ active: false,
+ };
+
+ setTooltips((tooltips) => ([
+ ...tooltips,
+ tooltip,
+ ]));
+ };
+
+ const remove = (id) => {
+ setTooltips((tooltips) => (
+ tooltips.filter((tooltip) => tooltip.id !== id)
+ ));
+ };
+
+ const update = (id, state) => {
+ setTooltips((tooltips) => (
+ tooltips.map((tooltip) => {
+ if (tooltip.id === id) {
+ tooltip = {
+ ...tooltip,
+ ...state,
+ };
+ }
+ return tooltip;
+ })
+ ));
+ };
+
+ return (
+
+ { children }
+
+ {
+ tooltips.map(({ id, ...tooltip }) => (
+
+ ))
+ }
+
+
+ );
+};
+
+TooltipProvider.propTypes = {
+ children: PropTypes.node,
+ className: PropTypes.string,
+};
+
+module.exports = TooltipProvider;
diff --git a/src/common/Tooltip/index.js b/src/common/Tooltips/index.js
similarity index 100%
rename from src/common/Tooltip/index.js
rename to src/common/Tooltips/index.js
diff --git a/src/common/Tooltip/useTooltip.js b/src/common/Tooltips/useTooltip.js
similarity index 100%
rename from src/common/Tooltip/useTooltip.js
rename to src/common/Tooltips/useTooltip.js
diff --git a/src/common/index.js b/src/common/index.js
index 700fd432b..a173a66d4 100644
--- a/src/common/index.js
+++ b/src/common/index.js
@@ -23,7 +23,7 @@ const SharePrompt = require('./SharePrompt');
const Slider = require('./Slider');
const TextInput = require('./TextInput');
const { ToastProvider, useToast } = require('./Toast');
-const { TooltipProvider, Tooltip } = require('./Tooltip');
+const { TooltipProvider, Tooltip } = require('./Tooltips');
const comparatorWithPriorities = require('./comparatorWithPriorities');
const CONSTANTS = require('./CONSTANTS');
const { withCoreSuspender, useCoreSuspender } = require('./CoreSuspender');