@primer/react 38.40.0-rc.629dc4f91 → 38.40.0-rc.960078edf
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.
- package/CHANGELOG.md +4 -0
- package/dist/TooltipV2/Tooltip.js +17 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
- [#8408](https://github.com/primer/react/pull/8408) [`c880319`](https://github.com/primer/react/commit/c8803199ddb0e669596f6e2370fd4117a055cfc3) Thanks [@janmaarten-a11y](https://github.com/janmaarten-a11y)! - Button and LinkButton: Limit link variant underlines to the text label when visuals are present
|
|
12
12
|
|
|
13
|
+
- [#8411](https://github.com/primer/react/pull/8411) [`8c52029`](https://github.com/primer/react/commit/8c520293151054fd39e5094f4740e97e89ce18d8) Thanks [@mattcosta7](https://github.com/mattcosta7)! - Tooltip: Prevent React Fragment triggers from crashing and provide a clear development warning
|
|
14
|
+
|
|
15
|
+
- [#8409](https://github.com/primer/react/pull/8409) [`9d0632c`](https://github.com/primer/react/commit/9d0632ccc6c23e92cbbe786ce922795c92931b04) Thanks [@iansan5653](https://github.com/iansan5653)! - Fix Tooltip ref handling to preserve child element ref
|
|
16
|
+
|
|
13
17
|
## 38.39.0
|
|
14
18
|
|
|
15
19
|
### Minor Changes
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { reactMajorVersion } from "../utils/environment.js";
|
|
1
2
|
import { useMergedRefs } from "../hooks/useMergedRefs.js";
|
|
2
3
|
import { useProvidedRefOrCreate } from "../hooks/useProvidedRefOrCreate.js";
|
|
3
4
|
import { useOnEscapePress } from "../hooks/useOnEscapePress.js";
|
|
@@ -82,10 +83,14 @@ const emptyKeybindingHints = [];
|
|
|
82
83
|
const Tooltip = /*#__PURE__*/ React.forwardRef(({ direction = "s", text, type = "description", children, id, className, keybindingHint = emptyKeybindingHints, delay = "short", _privateDisableTooltip = false, ...rest }, forwardedRef) => {
|
|
83
84
|
const tooltipId = useId$1(id);
|
|
84
85
|
const child = Children.only(children);
|
|
86
|
+
const isFragmentTrigger = /*#__PURE__*/ React.isValidElement(child) && child.type === React.Fragment;
|
|
87
|
+
warning(isFragmentTrigger, "The `Tooltip` component does not support a React Fragment as its trigger. Pass a single interactive element instead.");
|
|
88
|
+
const elementChild = /*#__PURE__*/ React.isValidElement(child) ? child : void 0;
|
|
89
|
+
const childRef = reactMajorVersion > 18 ? elementChild === null || elementChild === void 0 ? void 0 : elementChild.props.ref : elementChild === null || elementChild === void 0 ? void 0 : elementChild.ref;
|
|
85
90
|
const mergedRefEnabled = useFeatureFlag("primer_react_merged_forwarded_refs");
|
|
86
91
|
const triggerRef = useRef(null);
|
|
87
|
-
const mergedTriggerRef = useMergedRefs(triggerRef, forwardedRef);
|
|
88
|
-
const providedOrCreatedRef = useProvidedRefOrCreate(forwardedRef);
|
|
92
|
+
const mergedTriggerRef = useMergedRefs(triggerRef, useMergedRefs(forwardedRef, childRef));
|
|
93
|
+
const providedOrCreatedRef = useProvidedRefOrCreate(forwardedRef !== null && forwardedRef !== void 0 ? forwardedRef : childRef);
|
|
89
94
|
const readTriggerRef = mergedRefEnabled ? triggerRef : providedOrCreatedRef;
|
|
90
95
|
const appliedTriggerRef = mergedRefEnabled ? mergedTriggerRef : providedOrCreatedRef;
|
|
91
96
|
const tooltipElRef = useRef(null);
|
|
@@ -95,7 +100,7 @@ const Tooltip = /*#__PURE__*/ React.forwardRef(({ direction = "s", text, type =
|
|
|
95
100
|
const { safeSetTimeout, safeClearTimeout } = useSafeTimeout();
|
|
96
101
|
const openTooltip = () => {
|
|
97
102
|
try {
|
|
98
|
-
if (tooltipElRef.current && readTriggerRef.current && tooltipElRef.current.hasAttribute("popover") && !tooltipElRef.current.matches(":popover-open") && !_privateDisableTooltip) {
|
|
103
|
+
if (tooltipElRef.current && readTriggerRef.current instanceof HTMLElement && tooltipElRef.current.hasAttribute("popover") && !tooltipElRef.current.matches(":popover-open") && !_privateDisableTooltip) {
|
|
99
104
|
const tooltip = tooltipElRef.current;
|
|
100
105
|
const trigger = readTriggerRef.current;
|
|
101
106
|
tooltip.showPopover();
|
|
@@ -131,15 +136,19 @@ const Tooltip = /*#__PURE__*/ React.forwardRef(({ direction = "s", text, type =
|
|
|
131
136
|
const value = useMemo(() => ({ tooltipId }), [tooltipId]);
|
|
132
137
|
useEffect(() => {
|
|
133
138
|
if (!tooltipElRef.current || !readTriggerRef.current) return;
|
|
134
|
-
const
|
|
135
|
-
const
|
|
139
|
+
const trigger = readTriggerRef.current;
|
|
140
|
+
const isInvalidTrigger = !(trigger instanceof HTMLElement);
|
|
141
|
+
warning(isInvalidTrigger, "The `Tooltip` component expects its trigger ref to resolve to an HTML element. Ensure the trigger forwards its ref to a single interactive element instead of a React Fragment.");
|
|
142
|
+
if (isInvalidTrigger) return;
|
|
143
|
+
const isTriggerInteractive = isInteractive(trigger);
|
|
144
|
+
const triggerChildren = trigger.childNodes;
|
|
136
145
|
const hasInteractiveDescendant = Array.from(triggerChildren).some((child) => {
|
|
137
146
|
return child instanceof HTMLElement && isInteractive(child) || Array.from(child.childNodes).some((grandChild) => grandChild instanceof HTMLElement && isInteractive(grandChild));
|
|
138
147
|
});
|
|
139
148
|
!(isTriggerInteractive || hasInteractiveDescendant) && invariant(false, "The `Tooltip` component expects a single React element that contains interactive content. Consider using a `<button>` or equivalent interactive element instead.");
|
|
140
149
|
if (type === "label") {
|
|
141
|
-
const hasAriaLabel =
|
|
142
|
-
const hasAriaLabelInChildren = Array.from(
|
|
150
|
+
const hasAriaLabel = trigger.hasAttribute("aria-label");
|
|
151
|
+
const hasAriaLabelInChildren = Array.from(trigger.childNodes).some((child) => child instanceof HTMLElement && child.hasAttribute("aria-label"));
|
|
143
152
|
warning(hasAriaLabel || hasAriaLabelInChildren, "The label type `Tooltip` is going to be used here to label the trigger element. Please remove the aria-label from the trigger element.");
|
|
144
153
|
}
|
|
145
154
|
if (typeof window !== "undefined") {
|
|
@@ -162,6 +171,7 @@ const Tooltip = /*#__PURE__*/ React.forwardRef(({ direction = "s", text, type =
|
|
|
162
171
|
const platform = usePlatform();
|
|
163
172
|
const hasAriaLabel = "aria-label" in rest;
|
|
164
173
|
const keybindingHints = Array.isArray(keybindingHint) ? keybindingHint : [keybindingHint];
|
|
174
|
+
if (isFragmentTrigger) return child;
|
|
165
175
|
return /*#__PURE__*/ jsx(TooltipContext.Provider, {
|
|
166
176
|
value,
|
|
167
177
|
children: /*#__PURE__*/ jsxs(Fragment$1, { children: [/*#__PURE__*/ React.isValidElement(child) && /*#__PURE__*/ React.cloneElement(child, {
|
package/package.json
CHANGED