@redocly/theme 0.62.0-next.6 → 0.62.0-next.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -51,7 +51,7 @@ function Breadcrumb({ label, link, isActive, onClick, icon }) {
51
51
  react_1.default.createElement(BreadcrumbIcon_1.BreadcrumbIcon, { icon: icon }),
52
52
  displayLabel));
53
53
  const breadcrumbContent = link ? (react_1.default.createElement(BreadcrumbLink, { "data-component-name": "Breadcrumbs/BreadcrumbLink", to: link, onClick: onClick, "$isActive": isActive }, content)) : (react_1.default.createElement(BreadcrumbWrapper, { "data-component-name": "Breadcrumbs/BreadcrumbWrapper", "$isActive": isActive, onClick: onClick, tabIndex: -1 }, content));
54
- return isTruncated ? (react_1.default.createElement(Tooltip_1.TooltipComponent, { tip: label, placement: "bottom", width: "max-content" }, breadcrumbContent)) : (breadcrumbContent);
54
+ return isTruncated ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: label, placement: "bottom" }, breadcrumbContent)) : (breadcrumbContent);
55
55
  }
56
56
  const baseBreadcrumbStyles = `
57
57
  display: flex;
@@ -55,7 +55,7 @@ function BreadcrumbDropdown({ children, label, items, onItemClick, className, })
55
55
  return null;
56
56
  }
57
57
  const isTruncated = label.length > constants_1.BREADCRUMB_MAX_LENGTH;
58
- const triggerContent = isTruncated ? (react_1.default.createElement(Tooltip_1.TooltipComponent, { tip: label, placement: "bottom", width: "max-content" },
58
+ const triggerContent = isTruncated ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: label, placement: "bottom" },
59
59
  react_1.default.createElement(TriggerContentWrapper, null, children))) : (children);
60
60
  const trigger = react_1.default.createElement(StyledDropdownTrigger, null, triggerContent);
61
61
  return (react_1.default.createElement(BreadcrumbDropdownWrapper, { "data-component-name": "Breadcrumbs/BreadcrumbDropdown", className: className, "data-testid": "breadcrumb-dropdown" },
@@ -27,7 +27,7 @@ function CatalogTagsWithTooltip({ items, itemsToShow = 1, showPlaceholder = true
27
27
  }
28
28
  const displayedItems = items.slice(0, itemsToShow);
29
29
  const remainingCount = items.length - itemsToShow;
30
- return (react_1.default.createElement(Tooltip_1.TooltipComponent, { tip: items.join(', '), placement: "bottom", className: "catalog", width: "400px" },
30
+ return (react_1.default.createElement(Tooltip_1.Tooltip, { tip: items.join(', '), placement: "bottom", className: "catalog", width: "400px" },
31
31
  react_1.default.createElement(CatalogTagsWrapper, { "data-component-name": "Catalog/CatalogTagsWithTooltip" },
32
32
  displayedItems.map((item, index) => (react_1.default.createElement(Tag_1.Tag, Object.assign({ key: `${item}-${index}` }, tagProps, { textTransform: "none", maxLength: constants_1.CATALOG_TAG_MAX_LENGTH }),
33
33
  react_1.default.createElement(CatalogHighlight_1.CatalogHighlight, null, item)))),
@@ -8,7 +8,7 @@ const react_1 = __importDefault(require("react"));
8
8
  const styled_components_1 = __importDefault(require("styled-components"));
9
9
  const CodeBlockTabs_1 = require("../../components/CodeBlock/CodeBlockTabs");
10
10
  const CopyButton_1 = require("../../components/Buttons/CopyButton");
11
- const TooltipWrapper_1 = require("../../components/Tooltip/TooltipWrapper");
11
+ const Tooltip_1 = require("../../components/Tooltip/Tooltip");
12
12
  const hooks_1 = require("../../core/hooks");
13
13
  const DeselectIcon_1 = require("../../icons/DeselectIcon/DeselectIcon");
14
14
  const MaximizeIcon_1 = require("../../icons/MaximizeIcon/MaximizeIcon");
@@ -38,15 +38,15 @@ function CodeBlockControls({ children, className, title, controls, tabs, dropdow
38
38
  tabs && react_1.default.createElement(CodeBlockTabs_1.CodeBlockTabs, { tabs: tabs }),
39
39
  react_1.default.createElement(ControlsWrapper, null,
40
40
  dropdown && react_1.default.createElement(CodeBlockDropdown_1.CodeBlockDropdown, Object.assign({}, dropdown)),
41
- report && !report.hidden && !((_a = report === null || report === void 0 ? void 0 : report.props) === null || _a === void 0 ? void 0 : _a.hide) ? (react_1.default.createElement(TooltipWrapper_1.TooltipWrapper, { tip: translate('codeSnippet.report.tooltipText', 'Report a problem'), placement: "top" },
41
+ report && !report.hidden && !((_a = report === null || report === void 0 ? void 0 : report.props) === null || _a === void 0 ? void 0 : _a.hide) ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: translate('codeSnippet.report.tooltipText', 'Report a problem'), placement: "top", arrowPosition: "right" },
42
42
  react_1.default.createElement(ControlButton, Object.assign({ variant: "text", size: "small", "data-testid": "report-button", icon: controlsType === 'icon' ? react_1.default.createElement(WarningSquareIcon_1.WarningSquareIcon, { size: "18px" }) : undefined }, report.props), controlsType != 'icon' && (((_b = report.props) === null || _b === void 0 ? void 0 : _b.buttonText) || 'Report')))) : null,
43
- expand && !((_c = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.expand) === null || _c === void 0 ? void 0 : _c.hide) ? (react_1.default.createElement(TooltipWrapper_1.TooltipWrapper, { tip: translate('codeSnippet.expand.tooltipText', 'Expand all'), placement: "top" },
43
+ expand && !((_c = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.expand) === null || _c === void 0 ? void 0 : _c.hide) ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: translate('codeSnippet.expand.tooltipText', 'Expand all'), placement: "top", arrowPosition: "right" },
44
44
  react_1.default.createElement(ControlButton, { variant: "text", size: "small", "data-testid": "expand-all", icon: controlsType === 'icon' ? react_1.default.createElement(MaximizeIcon_1.MaximizeIcon, null) : undefined, onClick: expand === null || expand === void 0 ? void 0 : expand.onClick }, controlsType !== 'icon' && ((expand === null || expand === void 0 ? void 0 : expand.label) || 'Expand all')))) : null,
45
- collapse && !((_d = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.collapse) === null || _d === void 0 ? void 0 : _d.hide) ? (react_1.default.createElement(TooltipWrapper_1.TooltipWrapper, { tip: translate('codeSnippet.collapse.tooltipText', 'Collapse all'), placement: "top" },
45
+ collapse && !((_d = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.collapse) === null || _d === void 0 ? void 0 : _d.hide) ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: translate('codeSnippet.collapse.tooltipText', 'Collapse all'), placement: "top", arrowPosition: "right" },
46
46
  react_1.default.createElement(ControlButton, { variant: "text", size: "small", "data-testid": "collapse-all", icon: controlsType === 'icon' ? react_1.default.createElement(MinimizeIcon_1.MinimizeIcon, null) : undefined, onClick: collapse === null || collapse === void 0 ? void 0 : collapse.onClick }, controlsType !== 'icon' && ((expand === null || expand === void 0 ? void 0 : expand.label) || 'Collapse all')))) : null,
47
47
  select ? (react_1.default.createElement(ControlButton, { variant: "text", size: "small", "data-testid": "select-all", icon: controlsType === 'icon' ? react_1.default.createElement(SelectIcon_1.SelectIcon, null) : undefined, onClick: select === null || select === void 0 ? void 0 : select.onClick }, controlsType !== 'icon' && (select === null || select === void 0 ? void 0 : select.label) ? select.label : 'Select all')) : null,
48
48
  deselect ? (react_1.default.createElement(ControlButton, { variant: "text", size: "small", "data-testid": "clear-all", icon: controlsType === 'icon' ? react_1.default.createElement(DeselectIcon_1.DeselectIcon, null) : undefined, onClick: deselect === null || deselect === void 0 ? void 0 : deselect.onClick }, controlsType !== 'icon' && (deselect === null || deselect === void 0 ? void 0 : deselect.label) ? deselect.label : 'Clear all')) : null,
49
- copy && !((_e = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.copy) === null || _e === void 0 ? void 0 : _e.hide) ? (react_1.default.createElement(TooltipWrapper_1.TooltipWrapper, { tip: translate('codeSnippet.copy.tooltipText', 'Copy to clipboard'), placement: "top" },
49
+ copy && !((_e = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.copy) === null || _e === void 0 ? void 0 : _e.hide) ? (react_1.default.createElement(Tooltip_1.Tooltip, { tip: translate('codeSnippet.copy.tooltipText', 'Copy to clipboard'), placement: "top", arrowPosition: "right" },
50
50
  react_1.default.createElement(StyledCopyButton, { data: copy.data, "data-source": copy.dataSource, "data-hash": copy.dataHash, type: controlsType, toasterPlacement: copy.toasterPlacement, toasterDuration: copy.toasterDuration, buttonText: copy.label, onCopyClick: () => {
51
51
  var _a;
52
52
  // If there already is a click handler, events should be handled there, cause they pass additional data
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { JSX, PropsWithChildren, ReactNode } from 'react';
2
+ import type { ReactNode } from 'react';
3
3
  export type TooltipProps = {
4
4
  tip: string | ReactNode;
5
5
  isOpen?: boolean;
@@ -9,7 +9,6 @@ export type TooltipProps = {
9
9
  width?: string;
10
10
  dataTestId?: string;
11
11
  disabled?: boolean;
12
- arrowPosition?: 'top' | 'bottom' | 'left' | 'right' | 'center';
12
+ arrowPosition?: 'left' | 'right' | 'center';
13
13
  };
14
- export declare function TooltipComponent({ children, isOpen, tip, withArrow, placement, className, width, dataTestId, disabled, arrowPosition, }: PropsWithChildren<TooltipProps>): JSX.Element;
15
14
  export declare const Tooltip: React.NamedExoticComponent<React.PropsWithChildren<TooltipProps>>;
@@ -34,113 +34,58 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.Tooltip = void 0;
37
- exports.TooltipComponent = TooltipComponent;
38
37
  const react_1 = __importStar(require("react"));
39
38
  const styled_components_1 = __importStar(require("styled-components"));
40
39
  const hooks_1 = require("../../core/hooks");
41
40
  const Portal_1 = require("../../components/Portal/Portal");
42
41
  function TooltipComponent({ children, isOpen, tip, withArrow = true, placement = 'top', className = 'default', width, dataTestId, disabled = false, arrowPosition = 'center', }) {
43
- const ref = (0, react_1.useRef)(null);
42
+ const tooltipWrapperRef = (0, react_1.useRef)(null);
43
+ const tooltipBodyRef = (0, react_1.useRef)(null);
44
44
  const { isOpened, handleOpen, handleClose } = (0, hooks_1.useControl)(isOpen);
45
- const [tooltipPosition, setTooltipPosition] = (0, react_1.useState)({ top: 0, left: 0 });
46
- (0, hooks_1.useOutsideClick)(ref, handleClose);
45
+ const anchorName = `--tooltip${(0, react_1.useId)().replace(/:/g, '')}`;
46
+ (0, hooks_1.useOutsideClick)(isOpened ? [tooltipWrapperRef, tooltipBodyRef] : tooltipWrapperRef, handleClose);
47
47
  const isControlled = isOpen !== undefined;
48
- const updateTooltipPosition = (0, react_1.useCallback)(() => {
49
- if (isOpened && ref.current) {
50
- const rect = ref.current.getBoundingClientRect();
51
- let top = 0;
52
- let left = 0;
53
- switch (placement) {
54
- case 'top':
55
- top = rect.top;
56
- if (arrowPosition === 'left') {
57
- left = rect.left - 24;
58
- }
59
- else if (arrowPosition === 'right') {
60
- left = rect.right + 24;
61
- }
62
- else {
63
- left = rect.left + rect.width / 2;
64
- }
65
- break;
66
- case 'bottom':
67
- top = rect.bottom;
68
- if (arrowPosition === 'left') {
69
- left = rect.left - 24;
70
- }
71
- else if (arrowPosition === 'right') {
72
- left = rect.right + 24;
73
- }
74
- else {
75
- left = rect.left + rect.width / 2;
76
- }
77
- break;
78
- case 'left':
79
- top = rect.top + rect.height / 2;
80
- left = rect.left;
81
- break;
82
- case 'right':
83
- top = rect.top + rect.height / 2;
84
- left = rect.right;
85
- break;
86
- }
87
- setTooltipPosition({ top, left });
88
- }
89
- }, [isOpened, placement, arrowPosition]);
90
- (0, react_1.useEffect)(() => {
91
- if (isOpened && ref.current) {
92
- updateTooltipPosition();
93
- const handleScroll = () => updateTooltipPosition();
94
- const handleResize = () => updateTooltipPosition();
95
- window.addEventListener('scroll', handleScroll, true);
96
- window.addEventListener('resize', handleResize);
97
- return () => {
98
- window.removeEventListener('scroll', handleScroll, true);
99
- window.removeEventListener('resize', handleResize);
100
- };
101
- }
102
- }, [isOpened, placement, updateTooltipPosition]);
103
48
  (0, react_1.useEffect)(() => {
49
+ if (!isControlled)
50
+ return;
104
51
  if (isOpen && !disabled) {
105
52
  handleOpen();
106
53
  }
107
54
  else {
108
55
  handleClose();
109
56
  }
110
- }, [isOpen, handleOpen, handleClose, disabled]);
111
- const controllers = !isControlled &&
112
- !disabled && {
113
- onMouseEnter: handleOpen,
114
- onMouseLeave: handleClose,
115
- onClick: handleClose,
116
- onFocus: handleOpen,
117
- onBlur: handleClose,
118
- };
119
- return (react_1.default.createElement(TooltipWrapper, Object.assign({ ref: ref }, controllers, { className: `tooltip-${className}`, "data-component-name": "Tooltip/Tooltip" }),
57
+ }, [isOpen, disabled, isControlled, handleOpen, handleClose]);
58
+ const controllers = !isControlled && !disabled
59
+ ? {
60
+ onMouseEnter: handleOpen,
61
+ onMouseLeave: handleClose,
62
+ onClick: handleClose,
63
+ onFocus: handleOpen,
64
+ onBlur: handleClose,
65
+ }
66
+ : {};
67
+ return (react_1.default.createElement(TooltipWrapper, Object.assign({ ref: tooltipWrapperRef }, controllers, { className: `tooltip-${className}`, "data-component-name": "Tooltip/Tooltip", anchorName: anchorName }),
120
68
  children,
121
69
  isOpened && !disabled && (react_1.default.createElement(Portal_1.Portal, null,
122
- react_1.default.createElement(TooltipBody, { "data-testid": dataTestId || (typeof tip === 'string' ? tip : ''), placement: placement, width: width, withArrow: withArrow, arrowPosition: arrowPosition, style: {
123
- position: 'fixed',
124
- top: tooltipPosition.top,
125
- left: tooltipPosition.left,
126
- } }, tip)))));
70
+ react_1.default.createElement(TooltipBody, { ref: tooltipBodyRef, "data-testid": dataTestId || (typeof tip === 'string' ? tip : ''), placement: placement, width: width, withArrow: withArrow, arrowPosition: arrowPosition, anchorName: anchorName }, tip)))));
127
71
  }
128
72
  exports.Tooltip = (0, react_1.memo)(TooltipComponent);
129
73
  const PLACEMENTS = {
130
74
  top: (0, styled_components_1.css) `
75
+ bottom: anchor(top);
131
76
  ${({ withArrow, arrowPosition }) => withArrow && arrowPosition === 'left'
132
77
  ? (0, styled_components_1.css) `
133
- transform: translate(0, -100%);
134
- margin-top: -10px;
78
+ transform: translate(-32px, -6px);
79
+ left: anchor(center);
135
80
  `
136
81
  : arrowPosition === 'right'
137
82
  ? (0, styled_components_1.css) `
138
- transform: translate(-100%, -100%);
139
- margin-top: -10px;
83
+ transform: translate(32px, -6px);
84
+ right: anchor(center);
140
85
  `
141
86
  : (0, styled_components_1.css) `
142
- transform: translate(-50%, -100%);
143
- margin-top: -10px;
87
+ transform: translate(-50%, -6px);
88
+ left: anchor(center);
144
89
  `}
145
90
 
146
91
  ${({ withArrow, arrowPosition }) => withArrow &&
@@ -152,26 +97,27 @@ const PLACEMENTS = {
152
97
  border-top-style: solid;
153
98
  border-radius: 2px;
154
99
  bottom: 0;
155
- ${arrowPosition === 'left' && 'left: 16px; transform: translateY(99%);'}
156
- ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 99%);'}
157
- ${arrowPosition === 'right' && 'right: 16px; transform: translateY(99%);'}
100
+ ${arrowPosition === 'left' && 'left: 16px; transform: translateY(100%);'}
101
+ ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 100%);'}
102
+ ${arrowPosition === 'right' && 'right: 16px; transform: translateY(100%);'}
158
103
  }
159
104
  `}
160
105
  `,
161
106
  bottom: (0, styled_components_1.css) `
107
+ top: anchor(bottom);
162
108
  ${({ withArrow, arrowPosition }) => withArrow && arrowPosition === 'left'
163
109
  ? (0, styled_components_1.css) `
164
- transform: translate(0, 10px);
165
- margin-top: 0;
110
+ transform: translate(-32px, 6px);
111
+ left: anchor(center);
166
112
  `
167
113
  : arrowPosition === 'right'
168
114
  ? (0, styled_components_1.css) `
169
- transform: translate(-100%, 10px);
170
- margin-top: 0;
115
+ transform: translate(32px, 6px);
116
+ right: anchor(center);
171
117
  `
172
118
  : (0, styled_components_1.css) `
173
- transform: translate(-50%, 10px);
174
- margin-top: 0;
119
+ transform: translate(-50%, 6px);
120
+ left: anchor(center);
175
121
  `}
176
122
 
177
123
  ${({ withArrow, arrowPosition }) => withArrow &&
@@ -183,17 +129,19 @@ const PLACEMENTS = {
183
129
  border-bottom-style: solid;
184
130
  border-radius: 0 0 2px 2px;
185
131
  top: 0;
186
- ${arrowPosition === 'left' && 'left: 16px; transform: translateY(-99%);'}
187
- ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -99%);'}
188
- ${arrowPosition === 'right' && 'right: 16px; transform: translateY(-99%);'}
132
+ ${arrowPosition === 'left' && 'left: 16px; transform: translateY(-100%);'}
133
+ ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -100%);'}
134
+ ${arrowPosition === 'right' && 'right: 16px; transform: translateY(-100%);'}
189
135
  }
190
136
  `}
191
137
  `,
192
138
  left: (0, styled_components_1.css) `
193
139
  transform: translate(-100%, -50%);
194
- margin-left: -10px;
140
+ margin-left: -7px;
141
+ top: anchor(center);
142
+ left: anchor(left);
195
143
 
196
- ${({ withArrow, arrowPosition }) => withArrow &&
144
+ ${({ withArrow }) => withArrow &&
197
145
  (0, styled_components_1.css) `
198
146
  &::after {
199
147
  border-top: 14px solid transparent;
@@ -201,19 +149,19 @@ const PLACEMENTS = {
201
149
  border-left-width: 8px;
202
150
  border-left-style: solid;
203
151
  border-radius: 2px 0 0 2px;
152
+ right: -9px;
204
153
  top: 50%;
205
- right: 0;
206
- ${arrowPosition === 'top' && 'top: 16px; transform: translateX(99%);'}
207
- ${arrowPosition === 'center' && 'top: 50%; transform: translate(99%, -50%);'}
208
- ${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(99%);'}
154
+ transform: translateY(-50%);
209
155
  }
210
156
  `}
211
157
  `,
212
158
  right: (0, styled_components_1.css) `
213
159
  transform: translate(0, -50%);
214
- margin-left: 10px;
160
+ margin-left: 7px;
161
+ top: anchor(center);
162
+ left: anchor(right);
215
163
 
216
- ${({ withArrow, arrowPosition }) => withArrow &&
164
+ ${({ withArrow }) => withArrow &&
217
165
  (0, styled_components_1.css) `
218
166
  &::after {
219
167
  border-top: 14px solid transparent;
@@ -221,28 +169,33 @@ const PLACEMENTS = {
221
169
  border-right-width: 8px;
222
170
  border-right-style: solid;
223
171
  border-radius: 0 2px 2px 0;
172
+ left: -9px;
224
173
  top: 50%;
225
- left: 0;
226
- ${arrowPosition === 'top' && 'top: 16px; transform: translateX(-99%);'}
227
- ${arrowPosition === 'center' && 'top: 50%; transform: translate(-99%, -50%);'}
228
- ${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(-99%);'}
174
+ transform: translateY(-50%);
229
175
  }
230
176
  `}
231
177
  `,
232
178
  };
233
- const TooltipWrapper = styled_components_1.default.div `
234
- position: relative;
179
+ const TooltipWrapper = styled_components_1.default.div.attrs(({ anchorName }) => ({
180
+ style: {
181
+ anchorName: anchorName,
182
+ },
183
+ })) `
235
184
  display: flex;
236
185
  `;
237
- /* eslint-disable theme/no-raw-colors-in-styles */
238
- const TooltipBody = styled_components_1.default.span `
239
- display: inline-block;
240
-
186
+ const TooltipBody = styled_components_1.default.span.attrs(({ anchorName }) => ({
187
+ style: {
188
+ positionAnchor: anchorName,
189
+ },
190
+ })) `
191
+ position: fixed;
192
+ min-width: 64px;
241
193
  padding: var(--tooltip-padding);
242
- max-width: ${({ width }) => width || 'var(--tooltip-max-width)'};
194
+ max-width: var(--tooltip-max-width);
243
195
  white-space: normal;
244
196
  word-break: normal;
245
197
  overflow-wrap: break-word;
198
+ text-align: left;
246
199
 
247
200
  border-radius: var(--border-radius-md);
248
201
  transition: opacity 0.3s ease-out;
@@ -270,10 +223,10 @@ const TooltipBody = styled_components_1.default.span `
270
223
  0px 8px 24px 8px #0000000a,
271
224
  0px 4px 12px 0px #00000014;
272
225
 
273
- width: ${({ width }) => width || 'auto'};
226
+ width: ${({ width }) => width || 'max-content'};
227
+
274
228
  ${({ placement }) => (0, styled_components_1.css) `
275
229
  ${PLACEMENTS[placement]};
276
230
  `}
277
231
  `;
278
- /* eslint-enable theme/no-raw-colors-in-styles */
279
232
  //# sourceMappingURL=Tooltip.js.map
@@ -5,5 +5,9 @@ const styled_components_1 = require("styled-components");
5
5
  exports.tooltipDarkMode = (0, styled_components_1.css) `
6
6
  --tooltip-bg-color: var(--color-warm-grey-4);
7
7
  --tooltip-border-color: var(--color-warm-grey-5);
8
+
9
+ .tooltip-copy-button {
10
+ --tooltip-bg-color: var(--color-warm-grey-4);
11
+ }
8
12
  `;
9
13
  //# sourceMappingURL=variables.dark.js.map
@@ -20,9 +20,9 @@ exports.tooltip = (0, styled_components_1.css) `
20
20
  --tooltip-max-width: 400px;
21
21
 
22
22
  .tooltip-copy-button {
23
- --tooltip-text-color: var(--text-color-secondary);
24
- --tooltip-bg-color: var(--bg-color-raised);
25
- --tooltip-arrow-color: var(--tooltip-bg-color);
23
+ --tooltip-text-color: var(--color-static-white);
24
+ --tooltip-bg-color: var(--color-warm-grey-10);
25
+ --tooltip-arrow-color: var(--tooltip-border-color);
26
26
  }
27
27
 
28
28
  .tooltip-catalog {
@@ -1,2 +1,4 @@
1
1
  import type { RefObject } from 'react';
2
- export declare function useOutsideClick(ref: RefObject<HTMLElement | null>, handler?: (event: MouseEvent | TouchEvent) => void): void;
2
+ type OutsideClickRef = RefObject<HTMLElement | null>;
3
+ export declare function useOutsideClick(refs: OutsideClickRef | OutsideClickRef[], handler?: (event: MouseEvent | TouchEvent) => void): void;
4
+ export {};
@@ -2,13 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useOutsideClick = useOutsideClick;
4
4
  const react_1 = require("react");
5
- function useOutsideClick(ref, handler) {
5
+ function useOutsideClick(refs, handler) {
6
6
  (0, react_1.useEffect)(() => {
7
+ const refList = Array.isArray(refs) ? refs : [refs];
7
8
  const listener = (event) => {
8
- if (!handler || !ref.current || ref.current.contains(event.target)) {
9
+ if (!handler)
9
10
  return;
11
+ const target = event.target;
12
+ const isInside = refList.some((ref) => ref.current && ref.current.contains(target));
13
+ if (!isInside) {
14
+ handler(event);
10
15
  }
11
- handler(event);
12
16
  };
13
17
  document.addEventListener('mousedown', listener);
14
18
  document.addEventListener('touchstart', listener);
@@ -16,6 +20,6 @@ function useOutsideClick(ref, handler) {
16
20
  document.removeEventListener('mousedown', listener);
17
21
  document.removeEventListener('touchstart', listener);
18
22
  };
19
- }, [ref, handler]);
23
+ }, [refs, handler]);
20
24
  }
21
25
  //# sourceMappingURL=use-outside-click.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.62.0-next.6",
3
+ "version": "0.62.0-next.7",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -31,7 +31,7 @@
31
31
  "lodash.throttle": "^4.1.1",
32
32
  "react": "19.2.4",
33
33
  "react-dom": "19.2.4",
34
- "react-router-dom": "^6.21.1",
34
+ "react-router-dom": "^6.30.3",
35
35
  "styled-components": "^4.1.1 || ^5.3.11 || ^6.0.0"
36
36
  },
37
37
  "devDependencies": {
@@ -51,7 +51,7 @@
51
51
  "@vitest/coverage-v8": "4.0.10",
52
52
  "@vitest/ui": "3.2.4",
53
53
  "concurrently": "7.6.0",
54
- "react-router-dom": "^6.21.1",
54
+ "react-router-dom": "^6.30.3",
55
55
  "resize-observer-polyfill": "1.5.1",
56
56
  "rimraf": "5.0.7",
57
57
  "styled-components": "5.3.11",
@@ -63,7 +63,7 @@
63
63
  "vitest": "4.0.10",
64
64
  "vitest-when": "0.6.2",
65
65
  "webpack": "5.94.0",
66
- "@redocly/realm-asyncapi-sdk": "0.8.0-next.2"
66
+ "@redocly/realm-asyncapi-sdk": "0.8.0-next.3"
67
67
  },
68
68
  "dependencies": {
69
69
  "@tanstack/react-query": "5.62.3",
@@ -4,7 +4,7 @@ import styled, { css } from 'styled-components';
4
4
  import type { JSX } from 'react';
5
5
 
6
6
  import { Link } from '@redocly/theme/components/Link/Link';
7
- import { TooltipComponent } from '@redocly/theme/components/Tooltip/Tooltip';
7
+ import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
8
8
  import { BreadcrumbIcon } from '@redocly/theme/components/Breadcrumbs/BreadcrumbIcon';
9
9
  import { trimText } from '@redocly/theme/core/utils';
10
10
  import { BREADCRUMB_MAX_LENGTH } from '@redocly/theme/core/constants';
@@ -48,9 +48,9 @@ export function Breadcrumb({ label, link, isActive, onClick, icon }: BreadcrumbP
48
48
  );
49
49
 
50
50
  return isTruncated ? (
51
- <TooltipComponent tip={label} placement="bottom" width="max-content">
51
+ <Tooltip tip={label} placement="bottom">
52
52
  {breadcrumbContent}
53
- </TooltipComponent>
53
+ </Tooltip>
54
54
  ) : (
55
55
  breadcrumbContent
56
56
  );
@@ -8,7 +8,7 @@ import { useThemeHooks } from '@redocly/theme/core/hooks';
8
8
  import { Dropdown } from '@redocly/theme/components/Dropdown/Dropdown';
9
9
  import { DropdownMenu } from '@redocly/theme/components/Dropdown/DropdownMenu';
10
10
  import { DropdownMenuItem } from '@redocly/theme/components/Dropdown/DropdownMenuItem';
11
- import { TooltipComponent } from '@redocly/theme/components/Tooltip/Tooltip';
11
+ import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
12
12
  import { GenericIcon } from '@redocly/theme/icons/GenericIcon/GenericIcon';
13
13
  import { BREADCRUMB_MAX_LENGTH } from '@redocly/theme/core/constants';
14
14
  import { BreadcrumbIcon } from '@redocly/theme/components/Breadcrumbs/BreadcrumbIcon';
@@ -39,9 +39,9 @@ export function BreadcrumbDropdown({
39
39
  const isTruncated = label.length > BREADCRUMB_MAX_LENGTH;
40
40
 
41
41
  const triggerContent = isTruncated ? (
42
- <TooltipComponent tip={label} placement="bottom" width="max-content">
42
+ <Tooltip tip={label} placement="bottom">
43
43
  <TriggerContentWrapper>{children}</TriggerContentWrapper>
44
- </TooltipComponent>
44
+ </Tooltip>
45
45
  ) : (
46
46
  children
47
47
  );
@@ -3,7 +3,7 @@ import styled from 'styled-components';
3
3
 
4
4
  import { CATALOG_TAG_MAX_LENGTH } from '@redocly/theme/core/constants';
5
5
  import { Tag, TagProps } from '@redocly/theme/components/Tag/Tag';
6
- import { TooltipComponent } from '@redocly/theme/components/Tooltip/Tooltip';
6
+ import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
7
7
  import { CatalogHighlight } from '@redocly/theme/components/Catalog/CatalogHighlight';
8
8
  import { useThemeHooks } from '@redocly/theme/core/hooks';
9
9
 
@@ -53,7 +53,7 @@ export function CatalogTagsWithTooltip({
53
53
  const remainingCount = items.length - itemsToShow;
54
54
 
55
55
  return (
56
- <TooltipComponent tip={items.join(', ')} placement="bottom" className="catalog" width="400px">
56
+ <Tooltip tip={items.join(', ')} placement="bottom" className="catalog" width="400px">
57
57
  <CatalogTagsWrapper data-component-name="Catalog/CatalogTagsWithTooltip">
58
58
  {displayedItems.map((item, index) => (
59
59
  <Tag
@@ -70,7 +70,7 @@ export function CatalogTagsWithTooltip({
70
70
  +{remainingCount} {translate('catalog.tags.more', 'more')}
71
71
  </MoreTagsButton>
72
72
  </CatalogTagsWrapper>
73
- </TooltipComponent>
73
+ </Tooltip>
74
74
  );
75
75
  }
76
76
 
@@ -6,7 +6,7 @@ import type { CodeBlockItems } from '@redocly/theme/components/CodeBlock/CodeBlo
6
6
 
7
7
  import { CodeBlockTabs } from '@redocly/theme/components/CodeBlock/CodeBlockTabs';
8
8
  import { CopyButton } from '@redocly/theme/components/Buttons/CopyButton';
9
- import { TooltipWrapper } from '@redocly/theme/components/Tooltip/TooltipWrapper';
9
+ import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
10
10
  import { useThemeHooks, useThemeConfig } from '@redocly/theme/core/hooks';
11
11
  import { DeselectIcon } from '@redocly/theme/icons/DeselectIcon/DeselectIcon';
12
12
  import { MaximizeIcon } from '@redocly/theme/icons/MaximizeIcon/MaximizeIcon';
@@ -86,9 +86,10 @@ export function CodeBlockControls({
86
86
  <ControlsWrapper>
87
87
  {dropdown && <CodeBlockDropdown {...dropdown} />}
88
88
  {report && !report.hidden && !report?.props?.hide ? (
89
- <TooltipWrapper
89
+ <Tooltip
90
90
  tip={translate('codeSnippet.report.tooltipText', 'Report a problem')}
91
91
  placement="top"
92
+ arrowPosition="right"
92
93
  >
93
94
  <ControlButton
94
95
  variant="text"
@@ -99,13 +100,14 @@ export function CodeBlockControls({
99
100
  >
100
101
  {controlsType != 'icon' && (report.props?.buttonText || 'Report')}
101
102
  </ControlButton>
102
- </TooltipWrapper>
103
+ </Tooltip>
103
104
  ) : null}
104
105
 
105
106
  {expand && !codeSnippet?.expand?.hide ? (
106
- <TooltipWrapper
107
+ <Tooltip
107
108
  tip={translate('codeSnippet.expand.tooltipText', 'Expand all')}
108
109
  placement="top"
110
+ arrowPosition="right"
109
111
  >
110
112
  <ControlButton
111
113
  variant="text"
@@ -116,13 +118,14 @@ export function CodeBlockControls({
116
118
  >
117
119
  {controlsType !== 'icon' && (expand?.label || 'Expand all')}
118
120
  </ControlButton>
119
- </TooltipWrapper>
121
+ </Tooltip>
120
122
  ) : null}
121
123
 
122
124
  {collapse && !codeSnippet?.collapse?.hide ? (
123
- <TooltipWrapper
125
+ <Tooltip
124
126
  tip={translate('codeSnippet.collapse.tooltipText', 'Collapse all')}
125
127
  placement="top"
128
+ arrowPosition="right"
126
129
  >
127
130
  <ControlButton
128
131
  variant="text"
@@ -133,7 +136,7 @@ export function CodeBlockControls({
133
136
  >
134
137
  {controlsType !== 'icon' && (expand?.label || 'Collapse all')}
135
138
  </ControlButton>
136
- </TooltipWrapper>
139
+ </Tooltip>
137
140
  ) : null}
138
141
 
139
142
  {select ? (
@@ -161,9 +164,10 @@ export function CodeBlockControls({
161
164
  ) : null}
162
165
 
163
166
  {copy && !codeSnippet?.copy?.hide ? (
164
- <TooltipWrapper
167
+ <Tooltip
165
168
  tip={translate('codeSnippet.copy.tooltipText', 'Copy to clipboard')}
166
169
  placement="top"
170
+ arrowPosition="right"
167
171
  >
168
172
  <StyledCopyButton
169
173
  data={copy.data}
@@ -184,7 +188,7 @@ export function CodeBlockControls({
184
188
  }
185
189
  }}
186
190
  />
187
- </TooltipWrapper>
191
+ </Tooltip>
188
192
  ) : null}
189
193
  </ControlsWrapper>
190
194
  </>
@@ -1,4 +1,4 @@
1
- import React, { useEffect, memo, useRef, useState, useCallback } from 'react';
1
+ import React, { memo, useEffect, useRef, useId } from 'react';
2
2
  import styled, { css } from 'styled-components';
3
3
 
4
4
  import type { JSX, PropsWithChildren, ReactNode } from 'react';
@@ -15,10 +15,10 @@ export type TooltipProps = {
15
15
  width?: string;
16
16
  dataTestId?: string;
17
17
  disabled?: boolean;
18
- arrowPosition?: 'top' | 'bottom' | 'left' | 'right' | 'center';
18
+ arrowPosition?: 'left' | 'right' | 'center';
19
19
  };
20
20
 
21
- export function TooltipComponent({
21
+ function TooltipComponent({
22
22
  children,
23
23
  isOpen,
24
24
  tip,
@@ -30,111 +30,55 @@ export function TooltipComponent({
30
30
  disabled = false,
31
31
  arrowPosition = 'center',
32
32
  }: PropsWithChildren<TooltipProps>): JSX.Element {
33
- const ref = useRef<HTMLDivElement | null>(null);
33
+ const tooltipWrapperRef = useRef<HTMLDivElement | null>(null);
34
+ const tooltipBodyRef = useRef<HTMLDivElement | null>(null);
34
35
  const { isOpened, handleOpen, handleClose } = useControl(isOpen);
35
- const [tooltipPosition, setTooltipPosition] = useState({ top: 0, left: 0 });
36
+ const anchorName = `--tooltip${useId().replace(/:/g, '')}`;
36
37
 
37
- useOutsideClick(ref, handleClose);
38
+ useOutsideClick(isOpened ? [tooltipWrapperRef, tooltipBodyRef] : tooltipWrapperRef, handleClose);
38
39
 
39
40
  const isControlled = isOpen !== undefined;
40
41
 
41
- const updateTooltipPosition = useCallback(() => {
42
- if (isOpened && ref.current) {
43
- const rect = ref.current.getBoundingClientRect();
44
-
45
- let top = 0;
46
- let left = 0;
47
-
48
- switch (placement) {
49
- case 'top':
50
- top = rect.top;
51
- if (arrowPosition === 'left') {
52
- left = rect.left - 24;
53
- } else if (arrowPosition === 'right') {
54
- left = rect.right + 24;
55
- } else {
56
- left = rect.left + rect.width / 2;
57
- }
58
- break;
59
- case 'bottom':
60
- top = rect.bottom;
61
- if (arrowPosition === 'left') {
62
- left = rect.left - 24;
63
- } else if (arrowPosition === 'right') {
64
- left = rect.right + 24;
65
- } else {
66
- left = rect.left + rect.width / 2;
67
- }
68
- break;
69
- case 'left':
70
- top = rect.top + rect.height / 2;
71
- left = rect.left;
72
- break;
73
- case 'right':
74
- top = rect.top + rect.height / 2;
75
- left = rect.right;
76
- break;
77
- }
78
-
79
- setTooltipPosition({ top, left });
80
- }
81
- }, [isOpened, placement, arrowPosition]);
82
-
83
42
  useEffect(() => {
84
- if (isOpened && ref.current) {
85
- updateTooltipPosition();
86
-
87
- const handleScroll = () => updateTooltipPosition();
88
- const handleResize = () => updateTooltipPosition();
89
-
90
- window.addEventListener('scroll', handleScroll, true);
91
- window.addEventListener('resize', handleResize);
92
-
93
- return () => {
94
- window.removeEventListener('scroll', handleScroll, true);
95
- window.removeEventListener('resize', handleResize);
96
- };
97
- }
98
- }, [isOpened, placement, updateTooltipPosition]);
43
+ if (!isControlled) return;
99
44
 
100
- useEffect(() => {
101
45
  if (isOpen && !disabled) {
102
46
  handleOpen();
103
47
  } else {
104
48
  handleClose();
105
49
  }
106
- }, [isOpen, handleOpen, handleClose, disabled]);
107
-
108
- const controllers = !isControlled &&
109
- !disabled && {
110
- onMouseEnter: handleOpen,
111
- onMouseLeave: handleClose,
112
- onClick: handleClose,
113
- onFocus: handleOpen,
114
- onBlur: handleClose,
115
- };
50
+ }, [isOpen, disabled, isControlled, handleOpen, handleClose]);
51
+
52
+ const controllers =
53
+ !isControlled && !disabled
54
+ ? {
55
+ onMouseEnter: handleOpen,
56
+ onMouseLeave: handleClose,
57
+ onClick: handleClose,
58
+ onFocus: handleOpen,
59
+ onBlur: handleClose,
60
+ }
61
+ : {};
116
62
 
117
63
  return (
118
64
  <TooltipWrapper
119
- ref={ref}
65
+ ref={tooltipWrapperRef}
120
66
  {...controllers}
121
67
  className={`tooltip-${className}`}
122
68
  data-component-name="Tooltip/Tooltip"
69
+ anchorName={anchorName}
123
70
  >
124
71
  {children}
125
72
  {isOpened && !disabled && (
126
73
  <Portal>
127
74
  <TooltipBody
75
+ ref={tooltipBodyRef}
128
76
  data-testid={dataTestId || (typeof tip === 'string' ? tip : '')}
129
77
  placement={placement}
130
78
  width={width}
131
79
  withArrow={withArrow}
132
80
  arrowPosition={arrowPosition}
133
- style={{
134
- position: 'fixed',
135
- top: tooltipPosition.top,
136
- left: tooltipPosition.left,
137
- }}
81
+ anchorName={anchorName}
138
82
  >
139
83
  {tip}
140
84
  </TooltipBody>
@@ -148,20 +92,21 @@ export const Tooltip = memo<PropsWithChildren<TooltipProps>>(TooltipComponent);
148
92
 
149
93
  const PLACEMENTS = {
150
94
  top: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
95
+ bottom: anchor(top);
151
96
  ${({ withArrow, arrowPosition }) =>
152
97
  withArrow && arrowPosition === 'left'
153
98
  ? css`
154
- transform: translate(0, -100%);
155
- margin-top: -10px;
99
+ transform: translate(-32px, -6px);
100
+ left: anchor(center);
156
101
  `
157
102
  : arrowPosition === 'right'
158
103
  ? css`
159
- transform: translate(-100%, -100%);
160
- margin-top: -10px;
104
+ transform: translate(32px, -6px);
105
+ right: anchor(center);
161
106
  `
162
107
  : css`
163
- transform: translate(-50%, -100%);
164
- margin-top: -10px;
108
+ transform: translate(-50%, -6px);
109
+ left: anchor(center);
165
110
  `}
166
111
 
167
112
  ${({ withArrow, arrowPosition }) =>
@@ -174,27 +119,28 @@ const PLACEMENTS = {
174
119
  border-top-style: solid;
175
120
  border-radius: 2px;
176
121
  bottom: 0;
177
- ${arrowPosition === 'left' && 'left: 16px; transform: translateY(99%);'}
178
- ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 99%);'}
179
- ${arrowPosition === 'right' && 'right: 16px; transform: translateY(99%);'}
122
+ ${arrowPosition === 'left' && 'left: 16px; transform: translateY(100%);'}
123
+ ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 100%);'}
124
+ ${arrowPosition === 'right' && 'right: 16px; transform: translateY(100%);'}
180
125
  }
181
126
  `}
182
127
  `,
183
128
  bottom: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
129
+ top: anchor(bottom);
184
130
  ${({ withArrow, arrowPosition }) =>
185
131
  withArrow && arrowPosition === 'left'
186
132
  ? css`
187
- transform: translate(0, 10px);
188
- margin-top: 0;
133
+ transform: translate(-32px, 6px);
134
+ left: anchor(center);
189
135
  `
190
136
  : arrowPosition === 'right'
191
137
  ? css`
192
- transform: translate(-100%, 10px);
193
- margin-top: 0;
138
+ transform: translate(32px, 6px);
139
+ right: anchor(center);
194
140
  `
195
141
  : css`
196
- transform: translate(-50%, 10px);
197
- margin-top: 0;
142
+ transform: translate(-50%, 6px);
143
+ left: anchor(center);
198
144
  `}
199
145
 
200
146
  ${({ withArrow, arrowPosition }) =>
@@ -207,17 +153,19 @@ const PLACEMENTS = {
207
153
  border-bottom-style: solid;
208
154
  border-radius: 0 0 2px 2px;
209
155
  top: 0;
210
- ${arrowPosition === 'left' && 'left: 16px; transform: translateY(-99%);'}
211
- ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -99%);'}
212
- ${arrowPosition === 'right' && 'right: 16px; transform: translateY(-99%);'}
156
+ ${arrowPosition === 'left' && 'left: 16px; transform: translateY(-100%);'}
157
+ ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -100%);'}
158
+ ${arrowPosition === 'right' && 'right: 16px; transform: translateY(-100%);'}
213
159
  }
214
160
  `}
215
161
  `,
216
162
  left: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
217
163
  transform: translate(-100%, -50%);
218
- margin-left: -10px;
164
+ margin-left: -7px;
165
+ top: anchor(center);
166
+ left: anchor(left);
219
167
 
220
- ${({ withArrow, arrowPosition }) =>
168
+ ${({ withArrow }) =>
221
169
  withArrow &&
222
170
  css`
223
171
  &::after {
@@ -226,19 +174,19 @@ const PLACEMENTS = {
226
174
  border-left-width: 8px;
227
175
  border-left-style: solid;
228
176
  border-radius: 2px 0 0 2px;
177
+ right: -9px;
229
178
  top: 50%;
230
- right: 0;
231
- ${arrowPosition === 'top' && 'top: 16px; transform: translateX(99%);'}
232
- ${arrowPosition === 'center' && 'top: 50%; transform: translate(99%, -50%);'}
233
- ${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(99%);'}
179
+ transform: translateY(-50%);
234
180
  }
235
181
  `}
236
182
  `,
237
183
  right: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
238
184
  transform: translate(0, -50%);
239
- margin-left: 10px;
185
+ margin-left: 7px;
186
+ top: anchor(center);
187
+ left: anchor(right);
240
188
 
241
- ${({ withArrow, arrowPosition }) =>
189
+ ${({ withArrow }) =>
242
190
  withArrow &&
243
191
  css`
244
192
  &::after {
@@ -247,31 +195,40 @@ const PLACEMENTS = {
247
195
  border-right-width: 8px;
248
196
  border-right-style: solid;
249
197
  border-radius: 0 2px 2px 0;
198
+ left: -9px;
250
199
  top: 50%;
251
- left: 0;
252
- ${arrowPosition === 'top' && 'top: 16px; transform: translateX(-99%);'}
253
- ${arrowPosition === 'center' && 'top: 50%; transform: translate(-99%, -50%);'}
254
- ${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(-99%);'}
200
+ transform: translateY(-50%);
255
201
  }
256
202
  `}
257
203
  `,
258
204
  };
259
205
 
260
- const TooltipWrapper = styled.div`
261
- position: relative;
206
+ const TooltipWrapper = styled.div.attrs<{ anchorName: string }>(({ anchorName }) => ({
207
+ style: {
208
+ anchorName: anchorName,
209
+ } as React.CSSProperties,
210
+ }))<{ anchorName: string }>`
262
211
  display: flex;
263
212
  `;
264
- /* eslint-disable theme/no-raw-colors-in-styles */
265
- const TooltipBody = styled.span<
266
- Pick<Required<TooltipProps>, 'placement' | 'withArrow' | 'arrowPosition'> & { width?: string }
267
- >`
268
- display: inline-block;
269
213
 
214
+ const TooltipBody = styled.span.attrs<{ anchorName: string }>(({ anchorName }) => ({
215
+ style: {
216
+ positionAnchor: anchorName,
217
+ } as React.CSSProperties,
218
+ }))<
219
+ Pick<Required<TooltipProps>, 'placement' | 'withArrow' | 'arrowPosition'> & {
220
+ width?: string;
221
+ anchorName: string;
222
+ }
223
+ >`
224
+ position: fixed;
225
+ min-width: 64px;
270
226
  padding: var(--tooltip-padding);
271
- max-width: ${({ width }) => width || 'var(--tooltip-max-width)'};
227
+ max-width: var(--tooltip-max-width);
272
228
  white-space: normal;
273
229
  word-break: normal;
274
230
  overflow-wrap: break-word;
231
+ text-align: left;
275
232
 
276
233
  border-radius: var(--border-radius-md);
277
234
  transition: opacity 0.3s ease-out;
@@ -299,9 +256,9 @@ const TooltipBody = styled.span<
299
256
  0px 8px 24px 8px #0000000a,
300
257
  0px 4px 12px 0px #00000014;
301
258
 
302
- width: ${({ width }) => width || 'auto'};
259
+ width: ${({ width }) => width || 'max-content'};
260
+
303
261
  ${({ placement }) => css`
304
262
  ${PLACEMENTS[placement]};
305
263
  `}
306
264
  `;
307
- /* eslint-enable theme/no-raw-colors-in-styles */
@@ -3,4 +3,8 @@ import { css } from 'styled-components';
3
3
  export const tooltipDarkMode = css`
4
4
  --tooltip-bg-color: var(--color-warm-grey-4);
5
5
  --tooltip-border-color: var(--color-warm-grey-5);
6
+
7
+ .tooltip-copy-button {
8
+ --tooltip-bg-color: var(--color-warm-grey-4);
9
+ }
6
10
  `;
@@ -18,9 +18,9 @@ export const tooltip = css`
18
18
  --tooltip-max-width: 400px;
19
19
 
20
20
  .tooltip-copy-button {
21
- --tooltip-text-color: var(--text-color-secondary);
22
- --tooltip-bg-color: var(--bg-color-raised);
23
- --tooltip-arrow-color: var(--tooltip-bg-color);
21
+ --tooltip-text-color: var(--color-static-white);
22
+ --tooltip-bg-color: var(--color-warm-grey-10);
23
+ --tooltip-arrow-color: var(--tooltip-border-color);
24
24
  }
25
25
 
26
26
  .tooltip-catalog {
@@ -2,22 +2,33 @@ import { useEffect } from 'react';
2
2
 
3
3
  import type { RefObject } from 'react';
4
4
 
5
+ type OutsideClickRef = RefObject<HTMLElement | null>;
6
+
5
7
  export function useOutsideClick(
6
- ref: RefObject<HTMLElement | null>,
8
+ refs: OutsideClickRef | OutsideClickRef[],
7
9
  handler?: (event: MouseEvent | TouchEvent) => void,
8
10
  ): void {
9
11
  useEffect(() => {
12
+ const refList = Array.isArray(refs) ? refs : [refs];
13
+
10
14
  const listener = (event: MouseEvent | TouchEvent) => {
11
- if (!handler || !ref.current || ref.current.contains(event.target as Node)) {
12
- return;
15
+ if (!handler) return;
16
+
17
+ const target = event.target as Node;
18
+
19
+ const isInside = refList.some((ref) => ref.current && ref.current.contains(target));
20
+
21
+ if (!isInside) {
22
+ handler(event);
13
23
  }
14
- handler(event);
15
24
  };
25
+
16
26
  document.addEventListener('mousedown', listener);
17
27
  document.addEventListener('touchstart', listener);
28
+
18
29
  return () => {
19
30
  document.removeEventListener('mousedown', listener);
20
31
  document.removeEventListener('touchstart', listener);
21
32
  };
22
- }, [ref, handler]);
33
+ }, [refs, handler]);
23
34
  }
@@ -1,12 +0,0 @@
1
- import type { JSX, ReactElement } from 'react';
2
- import type { TooltipProps } from '../../components/Tooltip/Tooltip';
3
- export type TooltipWrapperProps = {
4
- children: ReactElement;
5
- tip: string;
6
- placement?: TooltipProps['placement'];
7
- width?: string;
8
- className?: string;
9
- showOnHover?: boolean;
10
- disabled?: boolean;
11
- };
12
- export declare function TooltipWrapper({ children, tip, placement, width, className, showOnHover, disabled, }: TooltipWrapperProps): JSX.Element;
@@ -1,34 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.TooltipWrapper = TooltipWrapper;
7
- const styled_components_1 = __importDefault(require("styled-components"));
8
- const react_1 = __importDefault(require("react"));
9
- const hooks_1 = require("../../core/hooks");
10
- const Tooltip_1 = require("../../components/Tooltip/Tooltip");
11
- function TooltipWrapper({ children, tip, placement = 'top', width = 'max-content', className = '', showOnHover = true, disabled = false, }) {
12
- const tooltip = (0, hooks_1.useControl)(false);
13
- const handleMouseEnter = () => {
14
- if (showOnHover && !disabled) {
15
- tooltip.handleOpen();
16
- }
17
- };
18
- const handleMouseLeave = () => {
19
- if (showOnHover) {
20
- tooltip.handleClose();
21
- }
22
- };
23
- const handleClick = () => {
24
- if (showOnHover) {
25
- tooltip.handleClose();
26
- }
27
- };
28
- return (react_1.default.createElement(Tooltip_1.Tooltip, { className: className, tip: tip, isOpen: tooltip.isOpened, placement: placement, width: width },
29
- react_1.default.createElement(TooltipEventWrapper, { onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onClick: handleClick }, children)));
30
- }
31
- const TooltipEventWrapper = styled_components_1.default.div `
32
- display: contents;
33
- `;
34
- //# sourceMappingURL=TooltipWrapper.js.map
@@ -1,70 +0,0 @@
1
- import styled from 'styled-components';
2
- import React from 'react';
3
-
4
- import type { JSX, ReactElement } from 'react';
5
- import type { TooltipProps } from '@redocly/theme/components/Tooltip/Tooltip';
6
-
7
- import { useControl } from '@redocly/theme/core/hooks';
8
- import { Tooltip } from '@redocly/theme/components/Tooltip/Tooltip';
9
-
10
- export type TooltipWrapperProps = {
11
- children: ReactElement;
12
- tip: string;
13
- placement?: TooltipProps['placement'];
14
- width?: string;
15
- className?: string;
16
- showOnHover?: boolean;
17
- disabled?: boolean;
18
- };
19
-
20
- export function TooltipWrapper({
21
- children,
22
- tip,
23
- placement = 'top',
24
- width = 'max-content',
25
- className = '',
26
- showOnHover = true,
27
- disabled = false,
28
- }: TooltipWrapperProps): JSX.Element {
29
- const tooltip = useControl(false);
30
-
31
- const handleMouseEnter = (): void => {
32
- if (showOnHover && !disabled) {
33
- tooltip.handleOpen();
34
- }
35
- };
36
-
37
- const handleMouseLeave = (): void => {
38
- if (showOnHover) {
39
- tooltip.handleClose();
40
- }
41
- };
42
-
43
- const handleClick = (): void => {
44
- if (showOnHover) {
45
- tooltip.handleClose();
46
- }
47
- };
48
-
49
- return (
50
- <Tooltip
51
- className={className}
52
- tip={tip}
53
- isOpen={tooltip.isOpened}
54
- placement={placement}
55
- width={width}
56
- >
57
- <TooltipEventWrapper
58
- onMouseEnter={handleMouseEnter}
59
- onMouseLeave={handleMouseLeave}
60
- onClick={handleClick}
61
- >
62
- {children}
63
- </TooltipEventWrapper>
64
- </Tooltip>
65
- );
66
- }
67
-
68
- const TooltipEventWrapper = styled.div`
69
- display: contents;
70
- `;