From 8ff30a817de0df2357d81626941ccbf26ecab3d4 Mon Sep 17 00:00:00 2001 From: Jamie Henson Date: Thu, 10 Oct 2024 15:56:11 +0100 Subject: [PATCH] 14.6.8 - pricing card title tooltips, support for multiple tooltip orientations --- package.json | 2 +- src/core/Pricing/PricingCards.tsx | 24 ++++++++++++++++++------ src/core/Pricing/data.tsx | 19 +++++++++++++++++++ src/core/Pricing/types.ts | 1 + src/core/Tooltip.tsx | 26 ++++++++++++++++++++------ 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 76b7bc97..34643177 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ably/ui", - "version": "14.6.7", + "version": "14.6.8", "description": "Home of the Ably design system library ([design.ably.com](https://design.ably.com)). It provides a showcase, development/test environment and a publishing pipeline for different distributables.", "repository": { "type": "git", diff --git a/src/core/Pricing/PricingCards.tsx b/src/core/Pricing/PricingCards.tsx index 0a9b6fe2..ce0959d1 100644 --- a/src/core/Pricing/PricingCards.tsx +++ b/src/core/Pricing/PricingCards.tsx @@ -1,11 +1,12 @@ import React, { Fragment, useEffect, useRef, useState } from "react"; +import throttle from "lodash.throttle"; import type { PricingDataFeature } from "./types"; import { determineThemeColor } from "../styles/colors/utils"; import { ColorClass, Theme } from "../styles/colors/types"; import Icon from "../Icon"; import FeaturedLink from "../FeaturedLink"; import { IconName } from "../Icon/types"; -import throttle from "lodash.throttle"; +import Tooltip from "../Tooltip"; export type PricingCardsProps = { data: PricingDataFeature[]; @@ -105,11 +106,22 @@ const PricingCards = ({ className={`relative z-10 flex flex-col gap-24 ${delimiter ? "@[520px]:flex-1 @[920px]:flex-none" : ""}`} >
-

- {title.content} -

+
+

+ {title.content} +

+ {title.tooltip ? ( + + {title.tooltip} + + ) : null} +

+ Ably aggregates all its data into named units of distribution, + referred to as “channels”. These are used to transmit from one device + to another.{" "} + + Find out more. + +

+ ), }, description: { content: @@ -255,6 +265,15 @@ export const consumptionData: PricingDataFeature[] = [ content: "Connections", className: "ui-text-h3", color: "text-neutral-000", + tooltip: ( +

+ Clients establish and maintain a connection to the Ably service using + the most efficient transport available, typically WebSockets.{" "} + + Find out more. + +

+ ), }, description: { content: diff --git a/src/core/Pricing/types.ts b/src/core/Pricing/types.ts index f0f56907..028970fb 100644 --- a/src/core/Pricing/types.ts +++ b/src/core/Pricing/types.ts @@ -5,6 +5,7 @@ type PricingDataHeader = { content: string; className?: string; color?: ColorClass; + tooltip?: string | ReactNode; }; type PricingDataFeatureCta = { diff --git a/src/core/Tooltip.tsx b/src/core/Tooltip.tsx index 38d8abd8..33c8b448 100644 --- a/src/core/Tooltip.tsx +++ b/src/core/Tooltip.tsx @@ -33,7 +33,7 @@ const Tooltip = ({ }: PropsWithChildren) => { const [open, setOpen] = useState(false); const [fadeOut, setFadeOut] = useState(false); - const [position, setPosition] = useState({ x: 0, y: 0 }); + const [position, setPosition] = useState({ x: 0, y: 0, orientation: "top" }); const offset = 8; const reference = useRef(null); const floating = useRef(null); @@ -47,6 +47,7 @@ const Tooltip = ({ const referenceRect = reference.current?.getBoundingClientRect(); const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; + let orientation = "top"; if (floatingRect && referenceRect) { let x = @@ -60,16 +61,19 @@ const Tooltip = ({ // Adjust if tooltip goes off the right edge if (x + floatingRect.width > viewportWidth + window.scrollX) { x = viewportWidth + window.scrollX - floatingRect.width - offset; + orientation = "left"; } // Adjust if tooltip goes off the left edge if (x < window.scrollX) { x = window.scrollX + offset; + orientation = "right"; } // Adjust if tooltip goes off the top edge if (y < window.scrollY) { y = referenceRect.bottom + offset + window.scrollY; + orientation = "bottom"; } // Adjust if tooltip goes off the bottom edge @@ -77,10 +81,10 @@ const Tooltip = ({ y = referenceRect.top - floatingRect.height - offset + window.scrollY; } - setPosition({ x, y }); + setPosition({ x, y, orientation }); } } else { - setPosition({ x: 0, y: 0 }); + setPosition({ x: 0, y: 0, orientation: "top" }); } return () => { @@ -98,14 +102,24 @@ const Tooltip = ({ }, 250); }; - const cursorHeadsNorth = ( + const cursorTowardsTooltip = ( event: MouseEvent, ref: RefObject, ) => { if (ref.current) { const { clientX, clientY } = event; const { x, y, width } = ref.current.getBoundingClientRect(); - return clientX >= x && clientX <= x + width && clientY < y; + const { orientation } = position; + + if (orientation === "top") { + return clientX >= x && clientX <= x + width && clientY < y; + } else if (orientation === "left") { + return clientY >= y && clientY <= y + width && clientX < x; + } else if (orientation === "right") { + return clientY >= y && clientY <= y + width && clientX > x + width; + } else if (orientation === "bottom") { + return clientX >= x && clientX <= x + width && clientY > y + width; + } } return false; @@ -121,7 +135,7 @@ const Tooltip = ({