From 232f55f2b1ddf84895876a828a64662bd60bd845 Mon Sep 17 00:00:00 2001 From: ap-justin <89639563+ap-justin@users.noreply.github.com> Date: Tue, 3 Sep 2024 19:10:04 +0800 Subject: [PATCH] update tooltip component --- package.json | 1 + src/components/BookmarkBtn.tsx | 16 +- src/components/Icon/Icon.tsx | 10 +- src/components/Tooltip.tsx | 86 ++--- src/components/VerifiedIcon.tsx | 35 +- .../Admin/Charity/Dashboard/Dashboard.tsx | 28 +- src/pages/Admin/Charity/Dashboard/Figure.tsx | 19 +- .../Charity/Dashboard/Schedule/Schedule.tsx | 23 +- src/pages/Registration/Steps/Reference.tsx | 36 +- yarn.lock | 347 ++++++++++++++++++ 10 files changed, 468 insertions(+), 133 deletions(-) diff --git a/package.json b/package.json index 38cbac1c34..729fea3aeb 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "@keplr-wallet/wc-qrcode-modal": "0.12.83", "@paypal/react-paypal-js": "8.3.0", "@radix-ui/react-slider": "1.1.2", + "@radix-ui/react-tooltip": "1.1.2", "@reduxjs/toolkit": "2.2.3", "@sentry/react": "8.22.0", "@stripe/react-stripe-js": "2.7.1", diff --git a/src/components/BookmarkBtn.tsx b/src/components/BookmarkBtn.tsx index 3a4a890813..2b724dec47 100644 --- a/src/components/BookmarkBtn.tsx +++ b/src/components/BookmarkBtn.tsx @@ -1,5 +1,5 @@ import Icon from "components/Icon"; -import Tooltip from "components/Tooltip"; +import { Arrow, Content, Tooltip } from "components/Tooltip"; import { useErrorContext } from "contexts/ErrorContext"; import { type PropsWithChildren, useRef } from "react"; import { @@ -50,8 +50,16 @@ export default function BookmarkBtn({ } return ( - <> - {!isBookmarked && } + + Add to favorites + + + ) : null + } + > - + ); } diff --git a/src/components/Icon/Icon.tsx b/src/components/Icon/Icon.tsx index 4da658c0ee..be520c01ce 100644 --- a/src/components/Icon/Icon.tsx +++ b/src/components/Icon/Icon.tsx @@ -1,12 +1,16 @@ import type { LucideProps } from "lucide-react"; +import { forwardRef } from "react"; import { type IconType, icons } from "./icons"; interface IconProps extends LucideProps { type: IconType; } -export default function Icon(props: IconProps) { +type El = SVGSVGElement; +const Icon = forwardRef((props, ref) => { const { type, ...rest } = props; const Icon = icons[type]; - return ; -} + return ; +}); + +export default Icon; diff --git a/src/components/Tooltip.tsx b/src/components/Tooltip.tsx index 0e91c81cd2..5a8dcaf3a7 100644 --- a/src/components/Tooltip.tsx +++ b/src/components/Tooltip.tsx @@ -1,65 +1,25 @@ -import { Transition } from "@headlessui/react"; -import { useEffect, useState } from "react"; -import type { RefObject } from "react"; -import { createPortal } from "react-dom"; - -type Props = { - content: string; - anchorRef?: RefObject; -}; - -export default function Tooltip({ - content, - anchorRef, -}: Props) { - const [top, setTop] = useState(0); - const [left, setLeft] = useState(0); - const [isHovered, setHovered] = useState(false); - - useEffect(() => { - const element = anchorRef?.current; - if (!element) return; - - function handleMouseEnter(this: HTMLElement) { - const rect = this.getBoundingClientRect(); - setTop(rect.top); - setLeft(rect.left); - setHovered(true); - } - - function handleMouseLeave(this: HTMLElement) { - setHovered(false); - } - - element.addEventListener("mouseenter", handleMouseEnter); - element.addEventListener("mouseleave", handleMouseLeave); - - return () => { - element.removeEventListener("mouseenter", handleMouseEnter); - element.removeEventListener("mouseleave", handleMouseLeave); - }; - }, [anchorRef]); - - return createPortal( - - {content} - , - document.body +import type { ReactNode } from "react"; + +import { + Portal, + Root, + TooltipProvider, + Trigger, +} from "@radix-ui/react-tooltip"; +export { Content, TooltipArrow as Arrow } from "@radix-ui/react-tooltip"; + +interface Props { + children: ReactNode; + /** must be wrapped by Content */ + content: ReactNode; +} +export function Tooltip(props: Props) { + return ( + + + {props.children} + {props.content} + + ); } diff --git a/src/components/VerifiedIcon.tsx b/src/components/VerifiedIcon.tsx index 78377c5f5e..d76d20f126 100644 --- a/src/components/VerifiedIcon.tsx +++ b/src/components/VerifiedIcon.tsx @@ -1,23 +1,22 @@ -import { useRef } from "react"; import Icon from "./Icon"; -import Tooltip from "./Tooltip"; -type Props = { - classes?: string; - size: number; -}; +import { Arrow, Content, Tooltip } from "./Tooltip"; +type Props = { size: number }; -export default function VerifiedIcon({ classes = "", size }: Props) { - const ref = useRef(null); +export default function VerifiedIcon({ size }: Props) { return ( - <> - -
- -
- + + Verified + + + } + > + + ); } diff --git a/src/pages/Admin/Charity/Dashboard/Dashboard.tsx b/src/pages/Admin/Charity/Dashboard/Dashboard.tsx index 8b864f1ee3..facfb572c7 100644 --- a/src/pages/Admin/Charity/Dashboard/Dashboard.tsx +++ b/src/pages/Admin/Charity/Dashboard/Dashboard.tsx @@ -1,9 +1,9 @@ +import { skipToken } from "@reduxjs/toolkit/query"; import ContentLoader from "components/ContentLoader"; +import Icon from "components/Icon"; import QueryLoader from "components/QueryLoader"; +import { Arrow, Content } from "components/Tooltip"; import { humanize } from "helpers"; - -import { skipToken } from "@reduxjs/toolkit/query"; -import Icon from "components/Icon"; import { useEndowBalanceQuery } from "services/apes"; import type { EndowmentBalances } from "types/aws"; import { useAdminContext } from "../../Context"; @@ -44,13 +44,31 @@ function Loaded({
+ Funds held in Fidelity Government Money Market (SPAXX) + + + } icon={} amount={`$ ${humanize(props.donationsBal - props.payoutsMade, 2)}`} />
+ + Funds invested in a diversified portfolio comprising + +
+

50% - domestic and international equities

+

30% - fixed income

+

15% - crypto

+

10% - cash

+
+ + + } icon={} amount={`$ ${humanize(props.sustainabilityFundBal, 2)}`} /> diff --git a/src/pages/Admin/Charity/Dashboard/Figure.tsx b/src/pages/Admin/Charity/Dashboard/Figure.tsx index 9f0e5cae2d..16ad637737 100644 --- a/src/pages/Admin/Charity/Dashboard/Figure.tsx +++ b/src/pages/Admin/Charity/Dashboard/Figure.tsx @@ -1,29 +1,28 @@ import Icon from "components/Icon"; -import Tooltip from "components/Tooltip"; -import { type ReactNode, useRef } from "react"; +import { Tooltip } from "components/Tooltip"; +import type { ReactNode } from "react"; type Props = { title: string; icon: ReactNode; /** e.g. $100,000 */ amount: string; - tooltip?: string; + /** must be wrapped by tooltip content */ + tooltip?: ReactNode; }; export default function Figure(props: Props) { - const ref = useRef(null); return (

{props.title}

+ {props.tooltip && ( - <> - -
- -
- + + + )} + {props.icon}

{props.amount}

diff --git a/src/pages/Admin/Charity/Dashboard/Schedule/Schedule.tsx b/src/pages/Admin/Charity/Dashboard/Schedule/Schedule.tsx index 54547387a0..84f53ec6bf 100644 --- a/src/pages/Admin/Charity/Dashboard/Schedule/Schedule.tsx +++ b/src/pages/Admin/Charity/Dashboard/Schedule/Schedule.tsx @@ -1,11 +1,10 @@ import leaf from "assets/icons/leaf.png"; import sendMoney from "assets/icons/send-money.png"; import Icon from "components/Icon"; -import Tooltip from "components/Tooltip"; +import { Arrow, Content, Tooltip } from "components/Tooltip"; import { useModalContext } from "contexts/ModalContext"; import { humanize } from "helpers"; import { useAdminContext } from "pages/Admin/Context"; -import { useRef } from "react"; import { useEndowmentQuery } from "services/aws/aws"; import { Edit } from "./Edit"; @@ -26,8 +25,6 @@ export function Schedule(props: Props) { const val = (pct?: number) => pct || pct === 0 ? `$ ${humanize((pct / 100) * props.amount)}` : "---"; - const grantRef = useRef(null); - return (
@@ -58,16 +55,22 @@ export function Schedule(props: Props) {
+
Grants -
- -
+ content={ + + Donations received through Better Giving that will distributed + to your bank account. + + + } + > + +
+ {endow?.allocation?.cash ?? 0} % diff --git a/src/pages/Registration/Steps/Reference.tsx b/src/pages/Registration/Steps/Reference.tsx index c1fff39df9..6928533db9 100644 --- a/src/pages/Registration/Steps/Reference.tsx +++ b/src/pages/Registration/Steps/Reference.tsx @@ -1,5 +1,6 @@ import Icon, { DrawerIcon } from "components/Icon"; -import { type ReactElement, cloneElement, useState } from "react"; +import { Arrow, Content, Tooltip } from "components/Tooltip"; +import { useState } from "react"; type Props = { id: string; @@ -17,11 +18,20 @@ export default function Reference({ id, classes = "" }: Props) { Your registration number: {id} - - - - - + + {tooltip} + + + } + > + +