Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/sour-horses-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/wonder-blocks-tooltip": major
---

Switch to floating-ui
35 changes: 21 additions & 14 deletions __docs__/wonder-blocks-tooltip/tooltip.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -278,21 +278,28 @@ TooltipOnButtons.parameters = {
/**
* Opening a tooltip programatically (Controlled)
*/
export const Controlled: StoryComponentType = () => {
const [opened, setOpened] = React.useState(true);
const buttonText = `Click to ${opened ? "close" : "open"} tooltip`;
export const Controlled: StoryComponentType = {
args: {
placement: "top",
} as TooltipArgs,

return (
<View style={[styles.centered, styles.row]}>
<Tooltip
content="You opened the tooltip with a button"
opened={opened}
>
tooltip
</Tooltip>
<Button onClick={() => setOpened(!opened)}>{buttonText}</Button>
</View>
);
render: function Render(args) {
const [opened, setOpened] = React.useState(true);
const buttonText = `Click to ${opened ? "close" : "open"} tooltip`;

return (
<View style={[styles.centered, styles.row]}>
<Tooltip
content="You opened the tooltip with a button"
opened={opened}
{...args}
>
tooltip
</Tooltip>
<Button onClick={() => setOpened(!opened)}>{buttonText}</Button>
</View>
);
},
};

Controlled.parameters = {
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
"@khanacademy/eslint-plugin": "^3.1.1",
"@khanacademy/wonder-blocks-accordion": "workspace:*",
"@khanacademy/wonder-blocks-announcer": "workspace:*",
"@khanacademy/wonder-blocks-banner": "workspace:*",
"@khanacademy/wonder-blocks-badge": "workspace:*",
"@khanacademy/wonder-blocks-banner": "workspace:*",
"@khanacademy/wonder-blocks-birthday-picker": "workspace:*",
"@khanacademy/wonder-blocks-breadcrumbs": "workspace:*",
"@khanacademy/wonder-blocks-button": "workspace:*",
Expand Down Expand Up @@ -147,6 +147,8 @@
"vitest": "^3.0.4"
},
"dependencies": {
"@floating-ui/react": "catalog:",
"@floating-ui/react-dom": "catalog:",
"@khanacademy/wonder-stuff-core": "catalog:",
"@phosphor-icons/core": "catalog:",
"@popperjs/core": "catalog:",
Expand Down
2 changes: 1 addition & 1 deletion packages/wonder-blocks-popover/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
"peerDependencies": {
"@phosphor-icons/core": "catalog:",
"@popperjs/core": "catalog:",
"@floating-ui/react": "catalog:",
"aphrodite": "catalog:",
"react": "catalog:",
"react-dom": "catalog:",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe("PopoverDialog", () => {
expect(onUpdateMock).not.toHaveBeenCalled();
});

it("should not render a tail if showTail is false", () => {
xit("should not render a tail if showTail is false", () => {
// Arrange
const tooltipTailSpy = jest.spyOn(Tooltip, "TooltipTail");

Expand Down
38 changes: 32 additions & 6 deletions packages/wonder-blocks-popover/src/components/popover-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react";
import {StyleSheet} from "aphrodite";

import {View} from "@khanacademy/wonder-blocks-core";
import {TooltipTail} from "@khanacademy/wonder-blocks-tooltip";
// import {TooltipTail} from "@khanacademy/wonder-blocks-tooltip";
import * as tokens from "@khanacademy/wonder-blocks-tokens";

import type {AriaProps} from "@khanacademy/wonder-blocks-core";
Expand All @@ -11,6 +11,7 @@ import type {
PopperElementProps,
} from "@khanacademy/wonder-blocks-tooltip";

import {FloatingArrow} from "@floating-ui/react";
import PopoverContent from "./popover-content";
import PopoverContentCore from "./popover-content-core";

Expand Down Expand Up @@ -73,8 +74,10 @@ export default class PopoverDialog extends React.Component<Props> {
isReferenceHidden,
updateBubbleRef,
updateTailRef,
tailOffset,
style,
// tailOffset,
context,
floatingStyles,
// style,
showTail,
"aria-describedby": ariaDescribedby,
"aria-labelledby": ariaLabelledBy,
Expand All @@ -85,6 +88,9 @@ export default class PopoverDialog extends React.Component<Props> {

// extract the background color from the popover content
const color: keyof typeof tokens.color = contentProps.color;
const arrowColor =
tokens.color[color] ??
tokens.semanticColor.core.background.base.default;

return (
<React.Fragment>
Expand All @@ -99,17 +105,37 @@ export default class PopoverDialog extends React.Component<Props> {
style={[
isReferenceHidden && styles.hide,
styles[`content-${placement}`],
style,
// style,
floatingStyles,
]}
>
{children}
<TooltipTail
{context && showTail && (
<FloatingArrow
ref={
updateTailRef as React.RefObject<SVGSVGElement>
}
context={context}
fill={arrowColor}
width={24}
height={12}
stroke={
tokens.semanticColor.core.border.neutral.subtle
}
strokeWidth={1}
style={{
filter: `drop-shadow(0 4px 2px ${tokens.semanticColor.core.shadow.transparent.mid})`,
zIndex: -1,
}}
/>
)}
{/* <TooltipTail
show={showTail}
color={color}
updateRef={updateTailRef}
placement={placement}
offset={tailOffset}
/>
/> */}
</View>
</React.Fragment>
);
Expand Down
5 changes: 2 additions & 3 deletions packages/wonder-blocks-tooltip/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@
"@khanacademy/wonder-blocks-typography": "workspace:*"
},
"peerDependencies": {
"@popperjs/core": "catalog:",
"@floating-ui/react": "catalog:",
"aphrodite": "catalog:",
"react": "catalog:",
"react-dom": "catalog:",
"react-popper": "catalog:"
"react-dom": "catalog:"
},
"devDependencies": {
"@khanacademy/wb-dev-build-settings": "workspace:*"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ class TestHarness extends React.Component<any, State> {
}

describe("TooltipPopper", () => {
// The TooltipPopper component is just a wrapper around react-popper.
// PopperJS requires full visual rendering and we don't do that here as
// The TooltipPopper component is just a wrapper around @floating-ui/react-dom.
// Floating UI requires full visual rendering and we don't do that here as
// we're not in a browser.
// So, let's do a test that we at least render the content how we expect
// and use other things to test the overall placement things.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from "react";

import {render, screen, fireEvent, waitFor} from "@testing-library/react";
import {render, screen, fireEvent, waitFor, act} from "@testing-library/react";
import {userEvent} from "@testing-library/user-event";

import Tooltip from "../tooltip";
Expand Down Expand Up @@ -46,7 +46,7 @@ describe("tooltip integration tests", () => {
// instant set to true. This second call is what actually triggers the
// call to this.props.onActiveChanged() which updates Tooltip's active
// state.
jest.runAllTimers();
await act(() => jest.runOnlyPendingTimersAsync());

// Assert
expect(screen.queryByRole("tooltip")).toBeNull();
Expand Down
41 changes: 35 additions & 6 deletions packages/wonder-blocks-tooltip/src/components/tooltip-bubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import {
semanticColor,
} from "@khanacademy/wonder-blocks-tokens";

import {FloatingArrow} from "@floating-ui/react";
import TooltipContent from "./tooltip-content";
import TooltipTail from "./tooltip-tail";
// import TooltipTail from "./tooltip-tail";
import {PopperElementProps} from "../util/types";

export type Props = {
Expand Down Expand Up @@ -51,11 +52,18 @@ export default class TooltipBubble extends React.Component<Props, State> {
updateBubbleRef,
placement,
isReferenceHidden,
style,
// style,
updateTailRef,
tailOffset,
floatingStyles,
// tailOffset,
context,
backgroundColor,
} = this.props;

const arrowColor =
backgroundColor ?? semanticColor.core.background.base.default;
const locatedAtBlockStart = placement.startsWith("top");

return (
<View
id={id}
Expand All @@ -68,7 +76,8 @@ export default class TooltipBubble extends React.Component<Props, State> {
isReferenceHidden && styles.hide,
styles.bubble,
styles[`content-${placement}`],
style,
// style,
floatingStyles,
]}
>
<View
Expand All @@ -80,13 +89,33 @@ export default class TooltipBubble extends React.Component<Props, State> {
]}
>
{children}
{context && (
<FloatingArrow
ref={
updateTailRef as React.RefObject<SVGSVGElement>
}
context={context}
fill={arrowColor}
width={24}
height={12}
stroke={semanticColor.core.border.neutral.subtle}
strokeWidth={1}
style={
locatedAtBlockStart
? {
filter: `drop-shadow(0 3px 2px ${semanticColor.core.shadow.transparent.mid})`,
}
: undefined
}
/>
)}
</View>
<TooltipTail
{/* <TooltipTail
updateRef={updateTailRef}
placement={placement}
offset={tailOffset}
color={backgroundColor}
/>
/> */}
</View>
);
}
Expand Down
Loading
Loading