@primer/react 38.40.0-rc.3ade0b294 → 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 CHANGED
@@ -10,6 +10,8 @@
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
+
13
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
14
16
 
15
17
  ## 38.39.0
@@ -83,6 +83,8 @@ const emptyKeybindingHints = [];
83
83
  const Tooltip = /*#__PURE__*/ React.forwardRef(({ direction = "s", text, type = "description", children, id, className, keybindingHint = emptyKeybindingHints, delay = "short", _privateDisableTooltip = false, ...rest }, forwardedRef) => {
84
84
  const tooltipId = useId$1(id);
85
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.");
86
88
  const elementChild = /*#__PURE__*/ React.isValidElement(child) ? child : void 0;
87
89
  const childRef = reactMajorVersion > 18 ? elementChild === null || elementChild === void 0 ? void 0 : elementChild.props.ref : elementChild === null || elementChild === void 0 ? void 0 : elementChild.ref;
88
90
  const mergedRefEnabled = useFeatureFlag("primer_react_merged_forwarded_refs");
@@ -98,7 +100,7 @@ const Tooltip = /*#__PURE__*/ React.forwardRef(({ direction = "s", text, type =
98
100
  const { safeSetTimeout, safeClearTimeout } = useSafeTimeout();
99
101
  const openTooltip = () => {
100
102
  try {
101
- 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) {
102
104
  const tooltip = tooltipElRef.current;
103
105
  const trigger = readTriggerRef.current;
104
106
  tooltip.showPopover();
@@ -134,15 +136,19 @@ const Tooltip = /*#__PURE__*/ React.forwardRef(({ direction = "s", text, type =
134
136
  const value = useMemo(() => ({ tooltipId }), [tooltipId]);
135
137
  useEffect(() => {
136
138
  if (!tooltipElRef.current || !readTriggerRef.current) return;
137
- const isTriggerInteractive = isInteractive(readTriggerRef.current);
138
- const triggerChildren = readTriggerRef.current.childNodes;
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;
139
145
  const hasInteractiveDescendant = Array.from(triggerChildren).some((child) => {
140
146
  return child instanceof HTMLElement && isInteractive(child) || Array.from(child.childNodes).some((grandChild) => grandChild instanceof HTMLElement && isInteractive(grandChild));
141
147
  });
142
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.");
143
149
  if (type === "label") {
144
- const hasAriaLabel = readTriggerRef.current.hasAttribute("aria-label");
145
- const hasAriaLabelInChildren = Array.from(readTriggerRef.current.childNodes).some((child) => child instanceof HTMLElement && child.hasAttribute("aria-label"));
150
+ const hasAriaLabel = trigger.hasAttribute("aria-label");
151
+ const hasAriaLabelInChildren = Array.from(trigger.childNodes).some((child) => child instanceof HTMLElement && child.hasAttribute("aria-label"));
146
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.");
147
153
  }
148
154
  if (typeof window !== "undefined") {
@@ -165,6 +171,7 @@ const Tooltip = /*#__PURE__*/ React.forwardRef(({ direction = "s", text, type =
165
171
  const platform = usePlatform();
166
172
  const hasAriaLabel = "aria-label" in rest;
167
173
  const keybindingHints = Array.isArray(keybindingHint) ? keybindingHint : [keybindingHint];
174
+ if (isFragmentTrigger) return child;
168
175
  return /*#__PURE__*/ jsx(TooltipContext.Provider, {
169
176
  value,
170
177
  children: /*#__PURE__*/ jsxs(Fragment$1, { children: [/*#__PURE__*/ React.isValidElement(child) && /*#__PURE__*/ React.cloneElement(child, {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@primer/react",
3
3
  "type": "module",
4
- "version": "38.40.0-rc.3ade0b294",
4
+ "version": "38.40.0-rc.960078edf",
5
5
  "description": "An implementation of GitHub's Primer Design System using React",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",