Skip to content

Commit

Permalink
14.6.8 - pricing card title tooltips, support for multiple tooltip or…
Browse files Browse the repository at this point in the history
…ientations
  • Loading branch information
jamiehenson committed Oct 10, 2024
1 parent 028abfd commit 8ff30a8
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 13 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
24 changes: 18 additions & 6 deletions src/core/Pricing/PricingCards.tsx
Original file line number Diff line number Diff line change
@@ -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[];
Expand Down Expand Up @@ -105,11 +106,22 @@ const PricingCards = ({
className={`relative z-10 flex flex-col gap-24 ${delimiter ? "@[520px]:flex-1 @[920px]:flex-none" : ""}`}
>
<div>
<p
className={`mb-12 ${title.className ?? ""} ${t(title.color ?? "text-neutral-000")}`}
>
{title.content}
</p>
<div className="flex items-center mb-12">
<p
className={`${title.className ?? ""} ${t(title.color ?? "text-neutral-000")}`}
>
{title.content}
</p>
{title.tooltip ? (
<Tooltip
className="-mt-4"
theme={theme}
interactive={typeof title.tooltip !== "string"}
>
{title.tooltip}
</Tooltip>
) : null}
</div>
<p
className={`ui-text-p1 ${description.className ?? ""} ${t(description.color ?? "text-neutral-000")} min-h-20`}
style={{ height: descriptionHeight }}
Expand Down
19 changes: 19 additions & 0 deletions src/core/Pricing/data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,16 @@ export const consumptionData: PricingDataFeature[] = [
content: "Channels",
className: "ui-text-h3",
color: "text-neutral-000",
tooltip: (
<p>
Ably aggregates all its data into named units of distribution,
referred to as “channels”. These are used to transmit from one device
to another.{" "}
<a href="/docs/channels" className="ui-link">
Find out more.
</a>
</p>
),
},
description: {
content:
Expand Down Expand Up @@ -255,6 +265,15 @@ export const consumptionData: PricingDataFeature[] = [
content: "Connections",
className: "ui-text-h3",
color: "text-neutral-000",
tooltip: (
<p>
Clients establish and maintain a connection to the Ably service using
the most efficient transport available, typically WebSockets.{" "}
<a href="/docs/connect" className="ui-link">
Find out more.
</a>
</p>
),
},
description: {
content:
Expand Down
1 change: 1 addition & 0 deletions src/core/Pricing/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type PricingDataHeader = {
content: string;
className?: string;
color?: ColorClass;
tooltip?: string | ReactNode;
};

type PricingDataFeatureCta = {
Expand Down
26 changes: 20 additions & 6 deletions src/core/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const Tooltip = ({
}: PropsWithChildren<TooltipProps>) => {
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<HTMLButtonElement>(null);
const floating = useRef<HTMLDivElement>(null);
Expand All @@ -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 =
Expand All @@ -60,27 +61,30 @@ 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
if (y + floatingRect.height > viewportHeight + window.scrollY) {
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 () => {
Expand All @@ -98,14 +102,24 @@ const Tooltip = ({
}, 250);
};

const cursorHeadsNorth = (
const cursorTowardsTooltip = (
event: MouseEvent,
ref: RefObject<HTMLButtonElement>,
) => {
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;
Expand All @@ -121,7 +135,7 @@ const Tooltip = ({
<button
onMouseEnter={() => setOpen(true)}
onMouseLeave={(event) => {
if (!interactive || !cursorHeadsNorth(event, reference)) {
if (!interactive || !cursorTowardsTooltip(event, reference)) {
initiateFadeOut();
}
}}
Expand Down

0 comments on commit 8ff30a8

Please sign in to comment.