@primer/react 38.40.0-rc.28e5764e2 → 38.40.0-rc.37bd8a025

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
@@ -4,12 +4,18 @@
4
4
 
5
5
  ### Minor Changes
6
6
 
7
+ - [#8422](https://github.com/primer/react/pull/8422) [`2909f19`](https://github.com/primer/react/commit/2909f19f64dbbc12aefb3455139596d88e5098b2) Thanks [@tay1orjones](https://github.com/tay1orjones)! - NavList, ActionList: Add a `disableItemGap` prop to render navigation items edge-to-edge.
8
+
7
9
  - [#8386](https://github.com/primer/react/pull/8386) [`6c64598`](https://github.com/primer/react/commit/6c645987c5ad27d5c23f57190a10b8707b29c58c) Thanks [@rickyzhangca](https://github.com/rickyzhangca)! - DataTable: Add config-driven row groups that can be interleaved with standalone rows.
8
10
 
9
11
  ### Patch Changes
10
12
 
11
13
  - [#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
14
 
15
+ - [#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
16
+
17
+ - [#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
18
+
13
19
  ## 38.39.0
14
20
 
15
21
  ### Minor Changes
@@ -17,7 +17,7 @@ import { clsx } from "clsx";
17
17
  //#region src/ActionList/List.tsx
18
18
  const UnwrappedList = (props, forwardedRef) => {
19
19
  var _slots$heading$props$;
20
- const $ = c(40);
20
+ const $ = c(41);
21
21
  let className;
22
22
  let restProps;
23
23
  let role;
@@ -26,8 +26,9 @@ const UnwrappedList = (props, forwardedRef) => {
26
26
  let t1;
27
27
  let t2;
28
28
  let t3;
29
+ let t4;
29
30
  if ($[0] !== props) {
30
- ({as: t0, variant: t1, selectionVariant, showDividers: t2, role, disableFocusZone: t3, className, ...restProps} = props);
31
+ ({as: t0, variant: t1, selectionVariant, showDividers: t2, role, disableFocusZone: t3, disableItemGap: t4, className, ...restProps} = props);
31
32
  $[0] = props;
32
33
  $[1] = className;
33
34
  $[2] = restProps;
@@ -37,6 +38,7 @@ const UnwrappedList = (props, forwardedRef) => {
37
38
  $[6] = t1;
38
39
  $[7] = t2;
39
40
  $[8] = t3;
41
+ $[9] = t4;
40
42
  } else {
41
43
  className = $[1];
42
44
  restProps = $[2];
@@ -46,17 +48,19 @@ const UnwrappedList = (props, forwardedRef) => {
46
48
  t1 = $[6];
47
49
  t2 = $[7];
48
50
  t3 = $[8];
51
+ t4 = $[9];
49
52
  }
50
53
  const Component = t0 === void 0 ? "ul" : t0;
51
54
  const variant = t1 === void 0 ? "inset" : t1;
52
55
  const showDividers = t2 === void 0 ? false : t2;
53
56
  const disableFocusZone = t3 === void 0 ? false : t3;
54
- let t4;
55
- if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
56
- t4 = { heading: Heading };
57
- $[9] = t4;
58
- } else t4 = $[9];
59
- const [slots, childrenWithoutSlots] = useSlots(restProps.children, t4);
57
+ const disableItemGap = t4 === void 0 ? false : t4;
58
+ let t5;
59
+ if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
60
+ t5 = { heading: Heading };
61
+ $[10] = t5;
62
+ } else t5 = $[10];
63
+ const [slots, childrenWithoutSlots] = useSlots(restProps.children, t5);
60
64
  const headingId = useId$1();
61
65
  const { listRole: listRoleFromContainer, listLabelledBy, selectionVariant: containerSelectionVariant, enableFocusZone: enableFocusZoneFromContainer, container } = React.useContext(ActionListContainerContext);
62
66
  const ariaLabelledBy = slots.heading ? (_slots$heading$props$ = slots.heading.props.id) !== null && _slots$heading$props$ !== void 0 ? _slots$heading$props$ : headingId : listLabelledBy;
@@ -67,58 +71,58 @@ const UnwrappedList = (props, forwardedRef) => {
67
71
  const providedOrCreatedRef = useProvidedRefOrCreate(forwardedRef);
68
72
  const readRef = mergedRefEnabled ? listRef : providedOrCreatedRef;
69
73
  const appliedRef = mergedRefEnabled ? mergedRef : providedOrCreatedRef;
70
- const itemGapEnabled = useFeatureFlag("primer_react_action_list_item_gap") && container === "NavList";
74
+ const itemGapEnabled = useFeatureFlag("primer_react_action_list_item_gap") && !disableItemGap && container === "NavList";
71
75
  let enableFocusZone = false;
72
76
  if (enableFocusZoneFromContainer !== void 0) enableFocusZone = enableFocusZoneFromContainer;
73
77
  else if (listRole && !disableFocusZone) {
74
- let t5;
75
- if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
76
- t5 = [
78
+ let t6;
79
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
80
+ t6 = [
77
81
  "menu",
78
82
  "menubar",
79
83
  "listbox"
80
84
  ];
81
- $[10] = t5;
82
- } else t5 = $[10];
83
- enableFocusZone = t5.includes(listRole);
85
+ $[11] = t6;
86
+ } else t6 = $[11];
87
+ enableFocusZone = t6.includes(listRole);
84
88
  }
85
- const t5 = !enableFocusZone;
86
- const t6 = listRole === "menu" || container === "SelectPanel" || container === "FilteredActionList" ? "wrap" : void 0;
87
- let t7;
88
- if ($[11] !== readRef || $[12] !== t5 || $[13] !== t6) {
89
- t7 = {
90
- disabled: t5,
89
+ const t6 = !enableFocusZone;
90
+ const t7 = listRole === "menu" || container === "SelectPanel" || container === "FilteredActionList" ? "wrap" : void 0;
91
+ let t8;
92
+ if ($[12] !== readRef || $[13] !== t6 || $[14] !== t7) {
93
+ t8 = {
94
+ disabled: t6,
91
95
  containerRef: readRef,
92
96
  bindKeys: FocusKeys.ArrowVertical | FocusKeys.HomeAndEnd | FocusKeys.PageUpDown,
93
- focusOutBehavior: t6
97
+ focusOutBehavior: t7
94
98
  };
95
- $[11] = readRef;
96
- $[12] = t5;
99
+ $[12] = readRef;
97
100
  $[13] = t6;
98
101
  $[14] = t7;
99
- } else t7 = $[14];
100
- useFocusZone(t7);
101
- const t8 = selectionVariant || containerSelectionVariant;
102
- let t9;
103
- if ($[15] !== headingId || $[16] !== listRole || $[17] !== showDividers || $[18] !== t8 || $[19] !== variant) {
104
- t9 = {
102
+ $[15] = t8;
103
+ } else t8 = $[15];
104
+ useFocusZone(t8);
105
+ const t9 = selectionVariant || containerSelectionVariant;
106
+ let t10;
107
+ if ($[16] !== headingId || $[17] !== listRole || $[18] !== showDividers || $[19] !== t9 || $[20] !== variant) {
108
+ t10 = {
105
109
  variant,
106
- selectionVariant: t8,
110
+ selectionVariant: t9,
107
111
  showDividers,
108
112
  role: listRole,
109
113
  headingId
110
114
  };
111
- $[15] = headingId;
112
- $[16] = listRole;
113
- $[17] = showDividers;
114
- $[18] = t8;
115
- $[19] = variant;
116
- $[20] = t9;
117
- } else t9 = $[20];
118
- const listContextValue = t9;
119
- let t10;
120
- if ($[21] !== readRef.current) {
121
- t10 = () => {
115
+ $[16] = headingId;
116
+ $[17] = listRole;
117
+ $[18] = showDividers;
118
+ $[19] = t9;
119
+ $[20] = variant;
120
+ $[21] = t10;
121
+ } else t10 = $[21];
122
+ const listContextValue = t10;
123
+ let t11;
124
+ if ($[22] !== readRef.current) {
125
+ t11 = () => {
122
126
  const list = readRef.current;
123
127
  if (!list) return;
124
128
  const hasMixed = list.querySelector("[data-has-description=\"true\"]") !== null && list.querySelector("[data-has-description=\"false\"]") !== null;
@@ -126,56 +130,56 @@ const UnwrappedList = (props, forwardedRef) => {
126
130
  if (hasMixed && current !== "true") list.setAttribute("data-mixed-descriptions", "true");
127
131
  else if (!hasMixed && current !== null) list.removeAttribute("data-mixed-descriptions");
128
132
  };
129
- $[21] = readRef.current;
130
- $[22] = t10;
131
- } else t10 = $[22];
132
- useIsomorphicLayoutEffect(t10);
133
- const t11 = slots.heading;
134
- let t12;
135
- if ($[23] !== className) {
136
- t12 = clsx(ActionList_module_css_default.ActionList, className);
137
- $[23] = className;
138
- $[24] = t12;
139
- } else t12 = $[24];
140
- const t13 = itemGapEnabled ? "" : void 0;
141
- let t14;
142
- if ($[25] !== Component || $[26] !== appliedRef || $[27] !== ariaLabelledBy || $[28] !== childrenWithoutSlots || $[29] !== listRole || $[30] !== restProps || $[31] !== showDividers || $[32] !== t12 || $[33] !== t13 || $[34] !== variant) {
143
- t14 = /*#__PURE__*/ jsx(Component, {
144
- className: t12,
133
+ $[22] = readRef.current;
134
+ $[23] = t11;
135
+ } else t11 = $[23];
136
+ useIsomorphicLayoutEffect(t11);
137
+ const t12 = slots.heading;
138
+ let t13;
139
+ if ($[24] !== className) {
140
+ t13 = clsx(ActionList_module_css_default.ActionList, className);
141
+ $[24] = className;
142
+ $[25] = t13;
143
+ } else t13 = $[25];
144
+ const t14 = itemGapEnabled ? "" : void 0;
145
+ let t15;
146
+ if ($[26] !== Component || $[27] !== appliedRef || $[28] !== ariaLabelledBy || $[29] !== childrenWithoutSlots || $[30] !== listRole || $[31] !== restProps || $[32] !== showDividers || $[33] !== t13 || $[34] !== t14 || $[35] !== variant) {
147
+ t15 = /*#__PURE__*/ jsx(Component, {
148
+ className: t13,
145
149
  role: listRole,
146
150
  "aria-labelledby": ariaLabelledBy,
147
151
  ref: appliedRef,
148
152
  "data-component": "ActionList",
149
153
  "data-dividers": showDividers,
150
154
  "data-variant": variant,
151
- "data-item-gap": t13,
155
+ "data-item-gap": t14,
152
156
  ...restProps,
153
157
  children: childrenWithoutSlots
154
158
  });
155
- $[25] = Component;
156
- $[26] = appliedRef;
157
- $[27] = ariaLabelledBy;
158
- $[28] = childrenWithoutSlots;
159
- $[29] = listRole;
160
- $[30] = restProps;
161
- $[31] = showDividers;
162
- $[32] = t12;
159
+ $[26] = Component;
160
+ $[27] = appliedRef;
161
+ $[28] = ariaLabelledBy;
162
+ $[29] = childrenWithoutSlots;
163
+ $[30] = listRole;
164
+ $[31] = restProps;
165
+ $[32] = showDividers;
163
166
  $[33] = t13;
164
- $[34] = variant;
165
- $[35] = t14;
166
- } else t14 = $[35];
167
- let t15;
168
- if ($[36] !== listContextValue || $[37] !== slots.heading || $[38] !== t14) {
169
- t15 = /*#__PURE__*/ jsxs(ListContext.Provider, {
167
+ $[34] = t14;
168
+ $[35] = variant;
169
+ $[36] = t15;
170
+ } else t15 = $[36];
171
+ let t16;
172
+ if ($[37] !== listContextValue || $[38] !== slots.heading || $[39] !== t15) {
173
+ t16 = /*#__PURE__*/ jsxs(ListContext.Provider, {
170
174
  value: listContextValue,
171
- children: [t11, t14]
175
+ children: [t12, t15]
172
176
  });
173
- $[36] = listContextValue;
174
- $[37] = slots.heading;
175
- $[38] = t14;
177
+ $[37] = listContextValue;
178
+ $[38] = slots.heading;
176
179
  $[39] = t15;
177
- } else t15 = $[39];
178
- return t15;
180
+ $[40] = t16;
181
+ } else t16 = $[40];
182
+ return t16;
179
183
  };
180
184
  const List = fixedForwardRef(UnwrappedList);
181
185
  Object.assign(List, { displayName: "ActionList" });
@@ -22,6 +22,7 @@ declare const ActionList: (<As extends React.ElementType = "ul">(props: Distribu
22
22
  role?: AriaRole;
23
23
  disableFocusZone?: boolean;
24
24
  className?: string;
25
+ disableItemGap?: boolean;
25
26
  } & {
26
27
  children?: import("react").ReactNode | undefined;
27
28
  }, "as"> & {
@@ -100,6 +100,10 @@ type ActionListProps<As extends React.ElementType = 'ul'> = PolymorphicProps<As,
100
100
  */
101
101
  disableFocusZone?: boolean;
102
102
  className?: string;
103
+ /**
104
+ * Disable the gap between items when this `ActionList` is rendered in a `NavList`.
105
+ */
106
+ disableItemGap?: boolean;
103
107
  }>>;
104
108
  //#endregion
105
109
  export { ActionListItemProps, ActionListProps };
@@ -12,7 +12,8 @@ import { Icon } from "@primer/octicons-react";
12
12
  //#region src/NavList/NavList.d.ts
13
13
  type NavListHeadingLevels = 'h2' | 'h3';
14
14
  type NavListProps = {
15
- children: React.ReactNode;
15
+ children: React.ReactNode; /** Disable the gap between items when the item gap feature is enabled. */
16
+ disableItemGap?: boolean;
16
17
  } & React.ComponentProps<'nav'>;
17
18
  type NavListHeadingProps = {
18
19
  /** Semantic heading level for the NavList. Also sets the default level for child group headings, which render one level deeper. */as?: NavListHeadingLevels; /** Visually hide the heading while keeping it available to assistive technology. */
@@ -26,76 +26,83 @@ function levelToHeadingTag(level) {
26
26
  }
27
27
  const Root = /*#__PURE__*/ React.forwardRef((t0, ref) => {
28
28
  var _heading$props$id, _ariaLabelledby;
29
- const $ = c(24);
29
+ const $ = c(26);
30
30
  let ariaLabel;
31
31
  let ariaLabelledby;
32
32
  let children;
33
+ let disableItemGap;
33
34
  let props;
34
35
  if ($[0] !== t0) {
35
- ({children, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, ...props} = t0);
36
+ ({children, disableItemGap, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, ...props} = t0);
36
37
  $[0] = t0;
37
38
  $[1] = ariaLabel;
38
39
  $[2] = ariaLabelledby;
39
40
  $[3] = children;
40
- $[4] = props;
41
+ $[4] = disableItemGap;
42
+ $[5] = props;
41
43
  } else {
42
44
  ariaLabel = $[1];
43
45
  ariaLabelledby = $[2];
44
46
  children = $[3];
45
- props = $[4];
47
+ disableItemGap = $[4];
48
+ props = $[5];
46
49
  }
47
50
  let t1;
48
- if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
51
+ if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
49
52
  t1 = { heading: Heading };
50
- $[5] = t1;
51
- } else t1 = $[5];
53
+ $[6] = t1;
54
+ } else t1 = $[6];
52
55
  const [slots, childrenWithoutHeading] = useSlots(children, t1);
53
56
  const fallbackHeadingId = useId$1();
54
57
  const heading = slots.heading;
55
58
  const headingId = heading ? (_heading$props$id = heading.props.id) !== null && _heading$props$id !== void 0 ? _heading$props$id : fallbackHeadingId : void 0;
56
59
  let t2;
57
- if ($[6] !== heading) {
60
+ if ($[7] !== heading) {
58
61
  var _heading$props$as;
59
62
  t2 = heading ? headingTagToLevel((_heading$props$as = heading.props.as) !== null && _heading$props$as !== void 0 ? _heading$props$as : "h2") : null;
60
- $[6] = heading;
61
- $[7] = t2;
62
- } else t2 = $[7];
63
+ $[7] = heading;
64
+ $[8] = t2;
65
+ } else t2 = $[8];
63
66
  const headingLevel = t2;
64
67
  const navLabelledby = (_ariaLabelledby = ariaLabelledby) !== null && _ariaLabelledby !== void 0 ? _ariaLabelledby : ariaLabel ? void 0 : headingId;
65
68
  let t3;
66
- if ($[8] !== heading || $[9] !== headingId) {
69
+ if ($[9] !== heading || $[10] !== headingId) {
67
70
  t3 = heading ? /*#__PURE__*/ React.cloneElement(heading, { id: headingId }) : null;
68
- $[8] = heading;
69
- $[9] = headingId;
70
- $[10] = t3;
71
- } else t3 = $[10];
71
+ $[9] = heading;
72
+ $[10] = headingId;
73
+ $[11] = t3;
74
+ } else t3 = $[11];
72
75
  let t4;
73
- if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
76
+ if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
74
77
  t4 = { container: "NavList" };
75
- $[11] = t4;
76
- } else t4 = $[11];
78
+ $[12] = t4;
79
+ } else t4 = $[12];
77
80
  let t5;
78
- if ($[12] !== childrenWithoutHeading) {
81
+ if ($[13] !== childrenWithoutHeading || $[14] !== disableItemGap) {
79
82
  t5 = /*#__PURE__*/ jsx(ActionListContainerContext.Provider, {
80
83
  value: t4,
81
- children: /*#__PURE__*/ jsx(ActionList, { children: childrenWithoutHeading })
84
+ children: /*#__PURE__*/ jsx(ActionList, {
85
+ disableItemGap,
86
+ children: childrenWithoutHeading
87
+ })
82
88
  });
83
- $[12] = childrenWithoutHeading;
84
- $[13] = t5;
85
- } else t5 = $[13];
89
+ $[13] = childrenWithoutHeading;
90
+ $[14] = disableItemGap;
91
+ $[15] = t5;
92
+ } else t5 = $[15];
86
93
  let t6;
87
- if ($[14] !== headingLevel || $[15] !== t3 || $[16] !== t5) {
94
+ if ($[16] !== headingLevel || $[17] !== t3 || $[18] !== t5) {
88
95
  t6 = /*#__PURE__*/ jsxs(NavListHeadingLevelContext.Provider, {
89
96
  value: headingLevel,
90
97
  children: [t3, t5]
91
98
  });
92
- $[14] = headingLevel;
93
- $[15] = t3;
94
- $[16] = t5;
95
- $[17] = t6;
96
- } else t6 = $[17];
99
+ $[16] = headingLevel;
100
+ $[17] = t3;
101
+ $[18] = t5;
102
+ $[19] = t6;
103
+ } else t6 = $[19];
97
104
  let t7;
98
- if ($[18] !== ariaLabel || $[19] !== navLabelledby || $[20] !== props || $[21] !== ref || $[22] !== t6) {
105
+ if ($[20] !== ariaLabel || $[21] !== navLabelledby || $[22] !== props || $[23] !== ref || $[24] !== t6) {
99
106
  t7 = /*#__PURE__*/ jsx("nav", {
100
107
  ...props,
101
108
  "aria-label": ariaLabel,
@@ -104,13 +111,13 @@ const Root = /*#__PURE__*/ React.forwardRef((t0, ref) => {
104
111
  "data-component": "NavList",
105
112
  children: t6
106
113
  });
107
- $[18] = ariaLabel;
108
- $[19] = navLabelledby;
109
- $[20] = props;
110
- $[21] = ref;
111
- $[22] = t6;
112
- $[23] = t7;
113
- } else t7 = $[23];
114
+ $[20] = ariaLabel;
115
+ $[21] = navLabelledby;
116
+ $[22] = props;
117
+ $[23] = ref;
118
+ $[24] = t6;
119
+ $[25] = t7;
120
+ } else t7 = $[25];
114
121
  return t7;
115
122
  });
116
123
  Root.displayName = "NavList";
@@ -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 isTriggerInteractive = isInteractive(readTriggerRef.current);
135
- 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;
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 = readTriggerRef.current.hasAttribute("aria-label");
142
- 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"));
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, {
@@ -212,6 +212,10 @@
212
212
  "id": "components-actionlist-features--item-dividers",
213
213
  "code": "() => (\n <ActionList showDividers>\n <ActionList.Item>Copy link</ActionList.Item>\n <ActionList.Item>Quote reply</ActionList.Item>\n <ActionList.Item>Edit comment</ActionList.Item>\n </ActionList>\n)"
214
214
  },
215
+ {
216
+ "id": "components-actionlist-features--disable-item-gap",
217
+ "code": "() => (\n <FeatureFlags\n flags={{\n primer_react_action_list_item_gap: true,\n }}\n >\n <ActionList.ContainerContext.Provider\n value={{\n container: 'NavList',\n }}\n >\n <Heading as=\"h3\">Default item gap</Heading>\n <ActionList>\n <ActionList.Item>Copy link</ActionList.Item>\n <ActionList.Item>Quote reply</ActionList.Item>\n <ActionList.Item>Edit comment</ActionList.Item>\n </ActionList>\n\n <Heading as=\"h3\">Item gap disabled</Heading>\n <ActionList disableItemGap>\n <ActionList.Item>Copy link</ActionList.Item>\n <ActionList.Item>Quote reply</ActionList.Item>\n <ActionList.Item>Edit comment</ActionList.Item>\n </ActionList>\n </ActionList.ContainerContext.Provider>\n </FeatureFlags>\n)"
218
+ },
215
219
  {
216
220
  "id": "components-actionlist-features--single-divider",
217
221
  "code": "() => (\n <ActionList>\n <ActionList.Item>Copy link</ActionList.Item>\n <ActionList.Item>Quote reply</ActionList.Item>\n <ActionList.Item>Edit comment</ActionList.Item>\n <ActionList.Divider />\n <ActionList.Item variant=\"danger\">Delete file</ActionList.Item>\n </ActionList>\n)"
@@ -365,6 +369,12 @@
365
369
  "type": "AriaRole",
366
370
  "defaultValue": "",
367
371
  "description": "ARIA role describing the function of the list. `listbox` and `menu` are a common values."
372
+ },
373
+ {
374
+ "name": "disableItemGap",
375
+ "type": "boolean",
376
+ "description": "Disable the gap between items when this `ActionList` is rendered in a `NavList`.",
377
+ "defaultValue": "false"
368
378
  }
369
379
  ],
370
380
  "subcomponents": [
@@ -4234,6 +4244,12 @@
4234
4244
  "defaultValue": "",
4235
4245
  "description": ""
4236
4246
  },
4247
+ {
4248
+ "name": "disableItemGap",
4249
+ "type": "boolean",
4250
+ "defaultValue": "false",
4251
+ "description": "Disable the gap between items when the item gap feature is enabled."
4252
+ },
4237
4253
  {
4238
4254
  "name": "ref",
4239
4255
  "type": "React.RefObject<HTMLElement>"
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.28e5764e2",
4
+ "version": "38.40.0-rc.37bd8a025",
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",