@sproutsocial/seeds-react-tooltip 1.1.20 → 1.1.27

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/dist/index.js CHANGED
@@ -39,7 +39,9 @@ module.exports = __toCommonJS(index_exports);
39
39
  var React = __toESM(require("react"));
40
40
  var import_react = require("react");
41
41
  var import_unitless = __toESM(require("@sproutsocial/seeds-motion/unitless"));
42
- var import_seeds_react_popout = __toESM(require("@sproutsocial/seeds-react-popout"));
42
+ var import_tooltip = require("@base-ui/react/tooltip");
43
+ var import_seeds_react_portal = require("@sproutsocial/seeds-react-portal");
44
+ var import_seeds_react_box2 = __toESM(require("@sproutsocial/seeds-react-box"));
43
45
 
44
46
  // src/styles.ts
45
47
  var import_styled_components = __toESM(require("styled-components"));
@@ -56,46 +58,33 @@ var idCounter = 0;
56
58
  var hasAttribute = (child, attribute) => {
57
59
  return React.isValidElement(child) && child.props[attribute] !== void 0;
58
60
  };
59
- var TooltipBubble = ({
60
- appearance = "pill",
61
- children,
62
- onFocus,
63
- onBlur,
64
- legacyMouseInteraction,
65
- ...rest
66
- }) => {
67
- const handleFocus = (e) => {
68
- onFocus(e);
69
- };
70
- const handleBlur = (e) => {
71
- onBlur(e);
72
- };
73
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
74
- StyledTooltipContent,
75
- {
76
- role: "tooltip",
77
- appearance,
78
- borderRadius: appearance === "box" ? 500 : "5000em",
79
- px: 400,
80
- py: appearance === "box" ? 400 : 200,
81
- m: 200,
82
- color: "text.body",
83
- bg: "container.background.base",
84
- boxShadow: "medium",
85
- border: 500,
86
- borderColor: "container.border.base",
87
- ...legacyMouseInteraction && {
88
- onFocus: handleFocus,
89
- onBlur: handleBlur,
90
- onMouseEnter: handleFocus,
91
- onMouseLeave: handleBlur
92
- },
93
- tabIndex: 0,
94
- ...rest,
95
- children
96
- }
97
- );
98
- };
61
+ function mapPlacement(placement) {
62
+ const parts = placement.split("-");
63
+ let side;
64
+ let align = "center";
65
+ switch (parts[0]) {
66
+ case "bottom":
67
+ side = "bottom";
68
+ break;
69
+ case "left":
70
+ side = "left";
71
+ break;
72
+ case "right":
73
+ side = "right";
74
+ break;
75
+ case "top":
76
+ case "auto":
77
+ default:
78
+ side = "top";
79
+ break;
80
+ }
81
+ if (parts[1] === "start") {
82
+ align = "start";
83
+ } else if (parts[1] === "end") {
84
+ align = "end";
85
+ }
86
+ return { side, align };
87
+ }
99
88
  var Tooltip = ({
100
89
  content,
101
90
  children,
@@ -106,101 +95,120 @@ var Tooltip = ({
106
95
  zIndex = 7,
107
96
  qa,
108
97
  popoutProps,
98
+ triggerProps,
109
99
  truncated = false,
110
100
  onFocus,
111
101
  onBlur,
112
102
  legacyMouseInteraction,
113
103
  ...rest
114
104
  }) => {
115
- const [shouldShow, setShouldShow] = (0, import_react.useState)(false);
116
- const [isOpen, setIsOpen] = (0, import_react.useState)(false);
105
+ const [open, setOpen] = (0, import_react.useState)(false);
117
106
  const [id] = (0, import_react.useState)(`Racine-tooltip-${idCounter++}`);
107
+ const triggerRef = (0, import_react.useRef)(null);
118
108
  const isInvalidContent = content === null || content === void 0;
109
+ const disablePortalToBody = (0, import_react.useContext)(import_seeds_react_portal.DisablePortalToBodyContext);
110
+ const [portalContainer, setPortalContainer] = (0, import_react.useState)(void 0);
119
111
  const resolvedExitDelay = exitDelay !== void 0 ? exitDelay : legacyMouseInteraction ? import_unitless.default.MOTION_DURATION_FAST * 1e3 : 0;
120
- const show = (e) => {
121
- onFocus?.(e);
122
- setShouldShow(true);
123
- };
124
- const hide = (e) => {
125
- onBlur?.(e);
126
- setShouldShow(false);
127
- };
128
112
  const defaultAppearance = appearance || (typeof content === "object" ? "box" : "pill");
113
+ const { side, align } = mapPlacement(placement);
114
+ const mergedWrapperProps = {
115
+ ...popoutProps,
116
+ ...triggerProps
117
+ };
118
+ const hasWrapperProps = Object.keys(mergedWrapperProps).length > 0;
129
119
  (0, import_react.useEffect)(() => {
130
- const documentBody = document.body;
131
- let timeout;
132
- const onEsc = (e) => {
133
- if (["Escape", "Esc"].includes(e.key)) {
134
- setIsOpen(false);
135
- setShouldShow(false);
136
- }
137
- };
138
- if (shouldShow) {
139
- timeout = setTimeout(() => setIsOpen(true), enterDelay);
140
- } else {
141
- timeout = setTimeout(() => {
142
- setIsOpen(false);
143
- }, resolvedExitDelay);
120
+ if (disablePortalToBody && triggerRef.current) {
121
+ const dialogContent = triggerRef.current.closest("[role='dialog']");
122
+ setPortalContainer(dialogContent ?? void 0);
144
123
  }
145
- if (isOpen) {
146
- documentBody.addEventListener("keydown", onEsc, { capture: true });
147
- }
148
- return () => {
149
- documentBody.removeEventListener("keydown", onEsc, { capture: true });
150
- clearTimeout(timeout);
151
- };
152
- }, [isOpen, setShouldShow, shouldShow, enterDelay, resolvedExitDelay]);
153
- const TooltipContent = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
154
- TooltipBubble,
155
- {
156
- appearance: defaultAppearance,
157
- onFocus: show,
158
- onBlur: hide,
159
- legacyMouseInteraction,
160
- "aria-expanded": isOpen,
161
- id,
162
- ...rest,
163
- children: content
164
- }
165
- );
166
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
167
- import_seeds_react_popout.default,
124
+ }, [disablePortalToBody]);
125
+ if (isInvalidContent) {
126
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
127
+ "span",
128
+ {
129
+ style: truncated ? {
130
+ overflow: "hidden",
131
+ textOverflow: "ellipsis",
132
+ whiteSpace: "nowrap"
133
+ } : {},
134
+ children
135
+ }
136
+ );
137
+ }
138
+ const tooltipTree = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
139
+ import_tooltip.Tooltip.Root,
168
140
  {
169
- content: !isInvalidContent ? TooltipContent : void 0,
170
- isOpen,
171
- placement,
172
- qa: {
173
- "data-qa-tooltip": id,
174
- ...qa
175
- },
176
- id: id + "-wrapper",
177
- focusOnContent: false,
178
- zIndex,
179
- "aria-haspopup": "false",
180
- display: truncated ? "flex" : void 0,
181
- disableWrapperAria: true,
182
- ...popoutProps,
183
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
184
- "span",
185
- {
186
- onBlur: hide,
187
- onFocus: show,
188
- onMouseEnter: show,
189
- onMouseLeave: hide,
190
- style: truncated ? {
191
- overflow: "hidden",
192
- textOverflow: "ellipsis",
193
- whiteSpace: "nowrap"
194
- } : {},
195
- children: React.isValidElement(children) ? React.cloneElement(children, {
196
- //** There may be cases where the Tooltip's child needs to properly describe its role as expanding a drawer, in which case that property takes priority */
197
- "aria-expanded": hasAttribute(children, "aria-expanded") ? children.props["aria-expanded"] : void 0,
198
- "aria-describedby": isOpen ? id : void 0
199
- }) : children
200
- }
201
- )
141
+ open,
142
+ onOpenChange: setOpen,
143
+ disabled: isInvalidContent,
144
+ disableHoverablePopup: !legacyMouseInteraction,
145
+ children: [
146
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
147
+ import_tooltip.Tooltip.Trigger,
148
+ {
149
+ delay: enterDelay,
150
+ closeDelay: resolvedExitDelay,
151
+ render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
152
+ "span",
153
+ {
154
+ ref: triggerRef,
155
+ onFocus,
156
+ onBlur,
157
+ "data-qa-popout-isopen": open ? "true" : "false",
158
+ "data-qa-tooltip": id,
159
+ ...qa || {},
160
+ style: truncated ? {
161
+ overflow: "hidden",
162
+ textOverflow: "ellipsis",
163
+ whiteSpace: "nowrap",
164
+ display: "inline-flex"
165
+ } : void 0
166
+ }
167
+ ),
168
+ children: React.isValidElement(children) ? React.cloneElement(children, {
169
+ "aria-expanded": hasAttribute(children, "aria-expanded") ? children.props["aria-expanded"] : void 0,
170
+ "aria-describedby": open ? id : void 0
171
+ }) : children
172
+ }
173
+ ),
174
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tooltip.Tooltip.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
175
+ import_tooltip.Tooltip.Positioner,
176
+ {
177
+ side,
178
+ align,
179
+ sideOffset: 4,
180
+ style: { zIndex },
181
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
182
+ import_tooltip.Tooltip.Popup,
183
+ {
184
+ id,
185
+ render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
186
+ StyledTooltipContent,
187
+ {
188
+ role: "tooltip",
189
+ appearance: defaultAppearance,
190
+ borderRadius: defaultAppearance === "box" ? 500 : "5000em",
191
+ px: 400,
192
+ py: defaultAppearance === "box" ? 400 : 200,
193
+ m: 200,
194
+ color: "text.body",
195
+ bg: "container.background.base",
196
+ boxShadow: "medium",
197
+ border: 500,
198
+ borderColor: "container.border.base",
199
+ tabIndex: legacyMouseInteraction ? 0 : void 0,
200
+ ...rest
201
+ }
202
+ ),
203
+ children: content
204
+ }
205
+ )
206
+ }
207
+ ) })
208
+ ]
202
209
  }
203
210
  );
211
+ return hasWrapperProps ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_box2.default, { ...mergedWrapperProps, children: tooltipTree }) : tooltipTree;
204
212
  };
205
213
  var Tooltip_default = Tooltip;
206
214
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/Tooltip.tsx","../src/styles.ts","../src/TooltipTypes.ts"],"sourcesContent":["import Tooltip from \"./Tooltip\";\n\nexport default Tooltip;\nexport { Tooltip };\nexport * from \"./TooltipTypes\";\n","import * as React from \"react\";\nimport { useState, useEffect } from \"react\";\nimport MOTION from \"@sproutsocial/seeds-motion/unitless\";\nimport Popout from \"@sproutsocial/seeds-react-popout\";\nimport { StyledTooltipContent } from \"./styles\";\nimport type { TypeTooltipProps, TypeTooltipContent } from \"./TooltipTypes\";\n\nlet idCounter = 0;\n\nconst hasAttribute = (child: React.ReactNode, attribute: string) => {\n return React.isValidElement(child) && child.props[attribute] !== undefined;\n};\n\n/** Tooltip Styled Popout wrapper for handling events */\nconst TooltipBubble = ({\n appearance = \"pill\",\n children,\n onFocus,\n onBlur,\n legacyMouseInteraction,\n ...rest\n}: TypeTooltipContent) => {\n // @ts-ignore Will fix during refactor\n const handleFocus = (e) => {\n onFocus(e);\n };\n // @ts-ignore Will fix during refactor\n const handleBlur = (e) => {\n onBlur(e);\n };\n return (\n <StyledTooltipContent\n role=\"tooltip\"\n appearance={appearance}\n borderRadius={appearance === \"box\" ? 500 : \"5000em\"}\n px={400}\n py={appearance === \"box\" ? 400 : 200}\n m={200}\n color=\"text.body\"\n bg=\"container.background.base\"\n boxShadow=\"medium\"\n border={500}\n borderColor=\"container.border.base\"\n {...(legacyMouseInteraction && {\n onFocus: handleFocus,\n onBlur: handleBlur,\n onMouseEnter: handleFocus,\n onMouseLeave: handleBlur,\n })}\n tabIndex={0}\n {...rest}\n >\n {children}\n </StyledTooltipContent>\n );\n};\n\n/** Core component */\nconst Tooltip = ({\n content,\n children,\n enterDelay = MOTION.MOTION_DURATION_FAST * 1000,\n exitDelay,\n placement = \"auto\",\n appearance,\n zIndex = 7,\n qa,\n popoutProps,\n truncated = false,\n onFocus,\n onBlur,\n legacyMouseInteraction,\n ...rest\n}: TypeTooltipProps) => {\n const [shouldShow, setShouldShow] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [id] = useState(`Racine-tooltip-${idCounter++}`);\n const isInvalidContent = content === null || content === undefined;\n\n // Compute exitDelay based on legacyMouseInteraction if not explicitly provided\n const resolvedExitDelay =\n exitDelay !== undefined\n ? exitDelay\n : legacyMouseInteraction\n ? MOTION.MOTION_DURATION_FAST * 1000\n : 0;\n\n // @ts-ignore Will fix during refactor\n const show = (e) => {\n onFocus?.(e);\n setShouldShow(true);\n };\n // @ts-ignore Will fix during refactor\n const hide = (e) => {\n onBlur?.(e);\n setShouldShow(false);\n };\n\n const defaultAppearance =\n appearance || (typeof content === \"object\" ? \"box\" : \"pill\");\n\n /** Handles all the logic around whether to display/not display */\n useEffect(() => {\n const documentBody = document.body;\n let timeout;\n const onEsc = (e: KeyboardEvent): void => {\n // older browsers use \"Esc\"\n if ([\"Escape\", \"Esc\"].includes(e.key)) {\n setIsOpen(false);\n setShouldShow(false);\n }\n };\n\n if (shouldShow) {\n timeout = setTimeout(() => setIsOpen(true), enterDelay);\n } else {\n timeout = setTimeout(() => {\n setIsOpen(false);\n }, resolvedExitDelay);\n }\n\n // We only want listeners from the tooltip if its open in the first place\n if (isOpen) {\n documentBody.addEventListener(\"keydown\", onEsc, { capture: true });\n }\n return () => {\n documentBody.removeEventListener(\"keydown\", onEsc, { capture: true });\n clearTimeout(timeout);\n };\n }, [isOpen, setShouldShow, shouldShow, enterDelay, resolvedExitDelay]);\n\n /** The wrapped content of whats inside the Tooltip */\n const TooltipContent = () => (\n <TooltipBubble\n appearance={defaultAppearance}\n onFocus={show}\n onBlur={hide}\n legacyMouseInteraction={legacyMouseInteraction}\n aria-expanded={isOpen}\n id={id}\n {...rest}\n >\n {content}\n </TooltipBubble>\n );\n\n return (\n <Popout\n content={!isInvalidContent ? TooltipContent : undefined}\n isOpen={isOpen}\n placement={placement}\n qa={{\n \"data-qa-tooltip\": id,\n ...qa,\n }}\n id={id + \"-wrapper\"}\n focusOnContent={false}\n zIndex={zIndex}\n aria-haspopup=\"false\"\n display={truncated ? \"flex\" : undefined}\n disableWrapperAria={true} // required so that the child span doesnt take in redundant aria props\n {...popoutProps}\n >\n <span\n onBlur={hide}\n onFocus={show}\n onMouseEnter={show}\n onMouseLeave={hide}\n style={\n truncated\n ? {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }\n : {}\n }\n >\n {React.isValidElement(children)\n ? React.cloneElement(children as React.ReactElement, {\n //** There may be cases where the Tooltip's child needs to properly describe its role as expanding a drawer, in which case that property takes priority */\n \"aria-expanded\": hasAttribute(children, \"aria-expanded\")\n ? children.props[\"aria-expanded\"]\n : undefined,\n \"aria-describedby\": isOpen ? id : undefined,\n })\n : children}\n </span>\n </Popout>\n );\n};\n\nexport default Tooltip;\n","import styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport type { TypeTooltipContent } from \"./TooltipTypes\";\n\nexport const StyledTooltipContent = styled(Box)<\n Pick<TypeTooltipContent, \"appearance\">\n>`\n font-family: ${(props) => props.theme.fontFamily};\n ${(props) => props.theme.typography[200]}\n text-align: ${(props) => (props.appearance === \"box\" ? \"left\" : \"center\")};\n`;\n","import * as React from \"react\";\nimport type { TypePopoutProps } from \"@sproutsocial/seeds-react-popout\";\nimport type { TypeBoxProps } from \"@sproutsocial/seeds-react-box\";\n\nexport interface TypeTooltipProps\n extends Omit<\n TypeBoxProps,\n \"children\" | \"content\" | \"onMouseEnter\" | \"onMouseLeave\"\n > {\n /** The content that the tooltip should be attached to. Hovering or focusing this element will cause the tooltip to appear */\n children: React.ReactNode;\n\n /** The content to be displayed within the tooltip. If there is no content, just the children are rendered */\n content: React.ReactNode;\n\n /** The placement of the tooltip in relation to the children */\n placement?: TypePopoutProps[\"placement\"];\n\n /** The time (in ms) that a user has to be hovered/focused before the tooltip will appear */\n enterDelay?: number;\n\n /** The time (in ms) that a user has to leave hovered/focused before the tooltip will disappear */\n exitDelay?: number;\n\n /**\n * When true, enables mouse interaction on tooltip content and sets exitDelay\n * to MOTION_DURATION_FAST * 1000 by default (instead of 0).\n */\n legacyMouseInteraction?: boolean;\n\n /** Used to override the appearance of the Tooltip content. By default, strings will have the 'pill' appearance, and more complex content will have the 'box' appearance. You can change those defaults by setting this prop. */\n appearance?: \"pill\" | \"box\";\n qa?: object;\n zIndex?: number;\n\n /** Props to be spread onto the underlying Popout component */\n popoutProps?: Partial<TypePopoutProps>;\n\n /** Truncates text into a single line with ellipsis */\n truncated?: boolean;\n\n ariaProps?: Record<string, string>;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface TypeTooltipContent\n extends Pick<TypeTooltipProps, \"appearance\" | \"children\"> {\n onFocus: (e: React.FocusEvent<HTMLDivElement, FocusEvent>) => void;\n onBlur: (e: React.FocusEvent<HTMLDivElement, FocusEvent>) => void;\n legacyMouseInteraction?: boolean;\n}\n"],"mappings":"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","names":["styled","Box","MOTION","Popout","React"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/Tooltip.tsx","../src/styles.ts","../src/TooltipTypes.ts"],"sourcesContent":["import Tooltip from \"./Tooltip\";\n\nexport default Tooltip;\nexport { Tooltip };\nexport * from \"./TooltipTypes\";\n","import * as React from \"react\";\nimport { useState, useRef, useEffect, useContext } from \"react\";\nimport MOTION from \"@sproutsocial/seeds-motion/unitless\";\nimport { Tooltip as BaseTooltip } from \"@base-ui/react/tooltip\";\nimport { DisablePortalToBodyContext } from \"@sproutsocial/seeds-react-portal\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport { StyledTooltipContent } from \"./styles\";\nimport type { TypeTooltipProps } from \"./TooltipTypes\";\n\nlet idCounter = 0;\n\nconst hasAttribute = (child: React.ReactNode, attribute: string) => {\n return React.isValidElement(child) && child.props[attribute] !== undefined;\n};\n\ntype Side = \"top\" | \"bottom\" | \"left\" | \"right\";\ntype Align = \"start\" | \"center\" | \"end\";\n\n// `auto`, `auto-start`, and `auto-end` resolve to `side: \"top\"` (with align\n// taken from the suffix) and rely on base-ui's Positioner collision flipping at\n// runtime, rather than Popper's old best-initial-side selection. Exported for\n// unit testing of this mapping.\nexport function mapPlacement(placement: string): { side: Side; align: Align } {\n const parts = placement.split(\"-\");\n let side: Side;\n let align: Align = \"center\";\n\n switch (parts[0]) {\n case \"bottom\":\n side = \"bottom\";\n break;\n case \"left\":\n side = \"left\";\n break;\n case \"right\":\n side = \"right\";\n break;\n case \"top\":\n case \"auto\":\n default:\n side = \"top\";\n break;\n }\n\n if (parts[1] === \"start\") {\n align = \"start\";\n } else if (parts[1] === \"end\") {\n align = \"end\";\n }\n\n return { side, align };\n}\n\nconst Tooltip = ({\n content,\n children,\n enterDelay = MOTION.MOTION_DURATION_FAST * 1000,\n exitDelay,\n placement = \"auto\",\n appearance,\n zIndex = 7,\n qa,\n popoutProps,\n triggerProps,\n truncated = false,\n onFocus,\n onBlur,\n legacyMouseInteraction,\n ...rest\n}: TypeTooltipProps) => {\n const [open, setOpen] = useState(false);\n const [id] = useState(`Racine-tooltip-${idCounter++}`);\n const triggerRef = useRef<HTMLSpanElement>(null);\n const isInvalidContent = content === null || content === undefined;\n const disablePortalToBody = useContext(DisablePortalToBodyContext);\n const [portalContainer, setPortalContainer] = useState<\n HTMLElement | undefined\n >(undefined);\n\n const resolvedExitDelay =\n exitDelay !== undefined\n ? exitDelay\n : legacyMouseInteraction\n ? MOTION.MOTION_DURATION_FAST * 1000\n : 0;\n\n const defaultAppearance =\n appearance || (typeof content === \"object\" ? \"box\" : \"pill\");\n\n const { side, align } = mapPlacement(placement);\n\n const mergedWrapperProps = {\n ...popoutProps,\n ...triggerProps,\n };\n\n const hasWrapperProps = Object.keys(mergedWrapperProps).length > 0;\n\n useEffect(() => {\n if (disablePortalToBody && triggerRef.current) {\n const dialogContent =\n triggerRef.current.closest<HTMLElement>(\"[role='dialog']\");\n setPortalContainer(dialogContent ?? undefined);\n }\n }, [disablePortalToBody]);\n\n if (isInvalidContent) {\n return (\n <span\n style={\n truncated\n ? {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }\n : {}\n }\n >\n {children}\n </span>\n );\n }\n\n const tooltipTree = (\n <BaseTooltip.Root\n open={open}\n onOpenChange={setOpen}\n disabled={isInvalidContent}\n disableHoverablePopup={!legacyMouseInteraction}\n >\n <BaseTooltip.Trigger\n delay={enterDelay}\n closeDelay={resolvedExitDelay}\n render={\n <span\n ref={triggerRef}\n onFocus={onFocus}\n onBlur={onBlur}\n data-qa-popout-isopen={open ? \"true\" : \"false\"}\n data-qa-tooltip={id}\n {...(qa || {})}\n style={\n truncated\n ? {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n display: \"inline-flex\",\n }\n : undefined\n }\n />\n }\n >\n {React.isValidElement(children)\n ? React.cloneElement(children as React.ReactElement, {\n \"aria-expanded\": hasAttribute(children, \"aria-expanded\")\n ? children.props[\"aria-expanded\"]\n : undefined,\n \"aria-describedby\": open ? id : undefined,\n })\n : children}\n </BaseTooltip.Trigger>\n <BaseTooltip.Portal container={portalContainer}>\n <BaseTooltip.Positioner\n side={side}\n align={align}\n sideOffset={4}\n style={{ zIndex }}\n >\n <BaseTooltip.Popup\n id={id}\n render={\n <StyledTooltipContent\n role=\"tooltip\"\n appearance={defaultAppearance}\n borderRadius={defaultAppearance === \"box\" ? 500 : \"5000em\"}\n px={400}\n py={defaultAppearance === \"box\" ? 400 : 200}\n m={200}\n color=\"text.body\"\n bg=\"container.background.base\"\n boxShadow=\"medium\"\n border={500}\n borderColor=\"container.border.base\"\n tabIndex={legacyMouseInteraction ? 0 : undefined}\n {...rest}\n />\n }\n >\n {content}\n </BaseTooltip.Popup>\n </BaseTooltip.Positioner>\n </BaseTooltip.Portal>\n </BaseTooltip.Root>\n );\n\n return hasWrapperProps ? (\n <Box {...mergedWrapperProps}>{tooltipTree}</Box>\n ) : (\n tooltipTree\n );\n};\n\nexport default Tooltip;\n","import styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport type { TypeTooltipContent } from \"./TooltipTypes\";\n\nexport const StyledTooltipContent = styled(Box)<\n Pick<TypeTooltipContent, \"appearance\">\n>`\n font-family: ${(props) => props.theme.fontFamily};\n ${(props) => props.theme.typography[200]}\n text-align: ${(props) => (props.appearance === \"box\" ? \"left\" : \"center\")};\n`;\n","import * as React from \"react\";\nimport type { TypeBoxProps } from \"@sproutsocial/seeds-react-box\";\n\nexport type TypeTooltipPlacement =\n | \"auto\"\n | \"auto-start\"\n | \"auto-end\"\n | \"top\"\n | \"top-start\"\n | \"top-end\"\n | \"bottom\"\n | \"bottom-start\"\n | \"bottom-end\"\n | \"left\"\n | \"left-start\"\n | \"left-end\"\n | \"right\"\n | \"right-start\"\n | \"right-end\";\n\nexport interface TypeTooltipProps\n extends Omit<\n TypeBoxProps,\n \"children\" | \"content\" | \"onMouseEnter\" | \"onMouseLeave\"\n > {\n /** The content that the tooltip should be attached to. Hovering or focusing this element will cause the tooltip to appear */\n children: React.ReactNode;\n\n /** The content to be displayed within the tooltip. If there is no content, just the children are rendered */\n content: React.ReactNode;\n\n /**\n * The placement of the tooltip in relation to the children.\n *\n * Note: `auto`, `auto-start`, and `auto-end` resolve to the `top` side (with\n * the requested alignment) and rely on base-ui's runtime collision flipping,\n * rather than the legacy Popper.js best-initial-side selection.\n */\n placement?: TypeTooltipPlacement;\n\n /** The time (in ms) that a user has to be hovered/focused before the tooltip will appear */\n enterDelay?: number;\n\n /** The time (in ms) that a user has to leave hovered/focused before the tooltip will disappear */\n exitDelay?: number;\n\n /**\n * When true, enables mouse interaction on tooltip content and sets exitDelay\n * to MOTION_DURATION_FAST * 1000 by default (instead of 0).\n */\n legacyMouseInteraction?: boolean;\n\n /** Used to override the appearance of the Tooltip content. By default, strings will have the 'pill' appearance, and more complex content will have the 'box' appearance. You can change those defaults by setting this prop. */\n appearance?: \"pill\" | \"box\";\n qa?: object;\n zIndex?: number;\n\n /**\n * @deprecated Use `triggerProps` instead. The Tooltip no longer uses Popout internally. This prop is accepted and merged with triggerProps\n */\n popoutProps?: Record<string, unknown>;\n\n /** Props spread onto an outer wrapper Box rendered around the tooltip. Use this to apply layout styles (e.g. `display`, `width`) or other Box props to the element that wraps the tooltip's children. */\n triggerProps?: TypeBoxProps;\n\n /** Truncates text into a single line with ellipsis */\n truncated?: boolean;\n\n ariaProps?: Record<string, string>;\n}\n\nexport interface TypeTooltipContent\n extends Pick<TypeTooltipProps, \"appearance\" | \"children\"> {\n onFocus: (e: React.FocusEvent<HTMLDivElement, FocusEvent>) => void;\n onBlur: (e: React.FocusEvent<HTMLDivElement, FocusEvent>) => void;\n legacyMouseInteraction?: boolean;\n}\n"],"mappings":"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","names":["import_seeds_react_box","styled","Box","MOTION","BaseTooltip","Box","React"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutsocial/seeds-react-tooltip",
3
- "version": "1.1.20",
3
+ "version": "1.1.27",
4
4
  "description": "Seeds React Tooltip",
5
5
  "author": "Sprout Social, Inc.",
6
6
  "license": "MIT",
@@ -18,10 +18,11 @@
18
18
  "test:watch": "jest --watch --coverage=false"
19
19
  },
20
20
  "dependencies": {
21
- "@sproutsocial/seeds-react-theme": "^3.6.2",
22
- "@sproutsocial/seeds-react-system-props": "^3.0.1",
23
- "@sproutsocial/seeds-react-popout": "^2.4.38",
24
- "@sproutsocial/seeds-react-box": "^1.1.16",
21
+ "@base-ui/react": "^1.3.0",
22
+ "@sproutsocial/seeds-react-theme": "^4.1.0",
23
+ "@sproutsocial/seeds-react-system-props": "^3.1.1",
24
+ "@sproutsocial/seeds-react-box": "^1.1.21",
25
+ "@sproutsocial/seeds-react-portal": "^1.2.0",
25
26
  "@sproutsocial/seeds-motion": "^1.8.2"
26
27
  },
27
28
  "devDependencies": {
@@ -35,11 +36,10 @@
35
36
  "@sproutsocial/seeds-tsconfig": "*",
36
37
  "@sproutsocial/seeds-testing": "*",
37
38
  "@sproutsocial/seeds-react-testing-library": "*",
38
- "@sproutsocial/seeds-react-icon": "^2.3.7",
39
- "@sproutsocial/seeds-react-banner": "^1.1.12",
40
- "@sproutsocial/seeds-react-button": "^2.0.5",
41
- "@sproutsocial/seeds-react-text": "^1.4.0",
42
- "@sproutsocial/seeds-react-portal": "^1.2.0"
39
+ "@sproutsocial/seeds-react-icon": "^2.4.0",
40
+ "@sproutsocial/seeds-react-banner": "^1.1.22",
41
+ "@sproutsocial/seeds-react-button": "^2.2.1",
42
+ "@sproutsocial/seeds-react-text": "^1.4.3"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "styled-components": "^5.2.3"
@@ -1,3 +1,4 @@
1
+ import React, { useState } from "react";
1
2
  import type { Meta, StoryObj } from "@storybook/react";
2
3
  import Banner from "@sproutsocial/seeds-react-banner";
3
4
  import Box from "@sproutsocial/seeds-react-box";
@@ -185,3 +186,127 @@ export const WithLegacyMouseInteraction: Story = {
185
186
  </Box>
186
187
  ),
187
188
  };
189
+
190
+ const InModalV1Template = () => {
191
+ const [isOpen, setIsOpen] = useState(true);
192
+ // Lazy-load Modal V1 to avoid circular deps in storybook
193
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
194
+ const Modal = require("@sproutsocial/seeds-react-modal").default;
195
+
196
+ return (
197
+ <Box>
198
+ <Button appearance="primary" onClick={() => setIsOpen(true)}>
199
+ Open Modal
200
+ </Button>
201
+ <Modal
202
+ appElementSelector="#storybook-root"
203
+ isOpen={isOpen}
204
+ onClose={() => setIsOpen(false)}
205
+ closeButtonLabel="Close modal"
206
+ label="Modal with Tooltip"
207
+ >
208
+ <Modal.Header title="Tooltip in Modal V1" />
209
+ <Modal.Content>
210
+ <Box p={400} display="flex" justifyContent="center">
211
+ <Tooltip content="This tooltip renders inside the Modal V1">
212
+ <Button appearance="primary">Hover me</Button>
213
+ </Tooltip>
214
+ </Box>
215
+ </Modal.Content>
216
+ </Modal>
217
+ </Box>
218
+ );
219
+ };
220
+
221
+ export const InModal: Story = {
222
+ render: () => <InModalV1Template />,
223
+ };
224
+
225
+ const InModalV2Template = () => {
226
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
227
+ const { ModalV2, ModalHeader, ModalBody } = require("@sproutsocial/seeds-react-modal");
228
+
229
+ return (
230
+ <ModalV2
231
+ aria-label="Modal V2 with Tooltip"
232
+ closeButtonAriaLabel="Close Modal"
233
+ modalTrigger={<Button appearance="primary">Open Modal V2</Button>}
234
+ >
235
+ <ModalHeader title="Tooltip in Modal V2" />
236
+ <ModalBody>
237
+ <Box p={400} display="flex" justifyContent="center">
238
+ <Tooltip content="This tooltip renders inside Modal V2">
239
+ <Button appearance="primary">Hover me</Button>
240
+ </Tooltip>
241
+ </Box>
242
+ </ModalBody>
243
+ </ModalV2>
244
+ );
245
+ };
246
+
247
+ export const InModalV2: Story = {
248
+ render: () => <InModalV2Template />,
249
+ };
250
+
251
+ const InPopoutTemplate = () => {
252
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
253
+ const Popout = require("@sproutsocial/seeds-react-popout").default;
254
+ const [isOpen, setIsOpen] = useState(true);
255
+
256
+ return (
257
+ <Box p={600} display="flex" justifyContent="center">
258
+ <Popout
259
+ content={() => (
260
+ <Box p={400}>
261
+ <Tooltip content="This tooltip renders inside a Popout">
262
+ <Button appearance="secondary">Hover me</Button>
263
+ </Tooltip>
264
+ </Box>
265
+ )}
266
+ isOpen={isOpen}
267
+ placement="bottom"
268
+ >
269
+ <Button appearance="primary" onClick={() => setIsOpen(!isOpen)}>
270
+ Toggle Popout
271
+ </Button>
272
+ </Popout>
273
+ </Box>
274
+ );
275
+ };
276
+
277
+ export const InPopout: Story = {
278
+ render: () => <InPopoutTemplate />,
279
+ };
280
+
281
+ const InDrawerTemplate = () => {
282
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
283
+ const Drawer = require("@sproutsocial/seeds-react-drawer").default;
284
+ const [isOpen, setIsOpen] = useState(true);
285
+
286
+ return (
287
+ <Box>
288
+ <Button appearance="primary" onClick={() => setIsOpen(true)}>
289
+ Open Drawer
290
+ </Button>
291
+ <Drawer
292
+ isOpen={isOpen}
293
+ onClose={() => setIsOpen(false)}
294
+ closeButtonLabel="Close drawer"
295
+ id="tooltip-drawer"
296
+ >
297
+ <Box p={400}>
298
+ <Text as="h3" fontSize={400} fontWeight="bold" mb={400}>
299
+ Tooltip in Drawer
300
+ </Text>
301
+ <Tooltip content="This tooltip renders inside a Drawer">
302
+ <Button appearance="primary">Hover me</Button>
303
+ </Tooltip>
304
+ </Box>
305
+ </Drawer>
306
+ </Box>
307
+ );
308
+ };
309
+
310
+ export const InDrawer: Story = {
311
+ render: () => <InDrawerTemplate />,
312
+ };