diff --git a/packages/react/src/modules/guide/components/Toolbar/V2/GuideContextDetails.tsx b/packages/react/src/modules/guide/components/Toolbar/V2/GuideContextDetails.tsx index 37f64777d..d78633d81 100644 --- a/packages/react/src/modules/guide/components/Toolbar/V2/GuideContextDetails.tsx +++ b/packages/react/src/modules/guide/components/Toolbar/V2/GuideContextDetails.tsx @@ -1,5 +1,6 @@ import { useGuideContext } from "@knocklabs/react-core"; import { Box, Stack } from "@telegraph/layout"; +import { Tooltip } from "@telegraph/tooltip"; import { Text } from "@telegraph/typography"; export const GuideContextDetails = () => { @@ -7,9 +8,30 @@ export const GuideContextDetails = () => { return ( - - Target params - + + The tenant and data payload passed to the guide client that are used + for targeting +
+ (via the `targetParams` prop to `KnockGuideProvider`) + + } + delayDuration={500} + > + + Target params + +
{ @@ -63,7 +61,7 @@ const getStatusSummary = ( return { color: "red", label: "Inactive", - tooltip: "This guide has never been committed and published yet", + description: "This guide has never been committed and published yet", }; } @@ -73,61 +71,49 @@ const getStatusSummary = ( return { color: "red", label: "Inactive", - tooltip: "This guide is inactive", + description: "This guide is inactive", }; } if (annotation.archived.status) { return { color: "red", label: "Archived", - tooltip: "User has already dismissed this guide", + description: "User has already dismissed this guide", }; } if (!annotation.targetable.status) { return { color: "red", label: "Not targeted", - tooltip: annotation.targetable.message, + description: annotation.targetable.message, }; } + + const selectableStatusSummary = getSelectableStatusSummary( + annotation.selectable.status, + ); + + // Prioritize an undefined selectable status ahead of activatable status. if (annotation.selectable.status === undefined) { - return { - color: "red", - label: "Not found", - tooltip: "No component that can query this guide was found", - }; + return selectableStatusSummary; } + if (!annotation.activatable.status) { return { color: "red", label: "Not activated", - tooltip: "This guide cannot be activated in the current location", - }; - } - if (annotation.selectable.status === "queried") { - return { - color: "gray", - label: "Queued", - tooltip: "This guide is queried but is not ready to display", + description: "This guide cannot be activated in the current location", }; } - if (annotation.selectable.status === "throttled") { - return { - color: "yellow", - label: "Throttled", - tooltip: - "This guide is queried and ready to display, but throttled currently", - }; - } - if (annotation.selectable.status === "returned") { - return { - color: "blue", - label: "Display", - tooltip: "This guide is queried and ready to display", - }; - } - // Should never happen though. - return { color: "red", label: "Unknown status", tooltip: "Unknown status" }; + + return { + ...selectableStatusSummary, + + // Shorten the label we display here for space. + ...(annotation.selectable.status === "returned" + ? { label: "Display" } + : undefined), + }; }; type StatusDot = { @@ -156,13 +142,13 @@ const getStatusDots = ( }; const archived: StatusDot = { - color: !annotation.archived.status ? "blue" : "red", - tooltip: `Not archived: ${!annotation.archived.status ? "Yes" : "No"}`, + color: annotation.archived.status ? "red" : "blue", + tooltip: `Archived: ${annotation.archived.status ? "Yes" : "No"}`, }; const targetable: StatusDot = { color: annotation.targetable.status ? "blue" : "red", - tooltip: `Targeted: ${annotation.targetable.status ? "Yes" : "No"}`, + tooltip: `Targeting: ${annotation.targetable.status ? "Yes" : "No"}`, }; const activatable: StatusDot = { @@ -170,25 +156,14 @@ const getStatusDots = ( tooltip: `Activated: ${annotation.activatable.status ? "Yes" : "No"}`, }; - let selectable: StatusDot; - switch (annotation.selectable.status) { - case "returned": - selectable = { color: "blue", tooltip: "Ready for display" }; - break; - - case "throttled": - selectable = { color: "yellow", tooltip: "Throttled" }; - break; - - case "queried": - selectable = { color: "gray", tooltip: "Queued" }; - break; + const selectableStatusSummary = getSelectableStatusSummary( + annotation.selectable.status, + ); - case undefined: - default: - selectable = { color: "red", tooltip: "Not found" }; - break; - } + const selectable = { + color: selectableStatusSummary.color, + tooltip: selectableStatusSummary.label, + }; return { active, archived, targetable, activatable, selectable }; }; @@ -302,7 +277,7 @@ export const GuideRow = ({ guide, orderIndex, isExpanded, onClick }: Props) => { {/* Right section: verdict + pills + focus */} {!hasFocus && ( - + {summary.label} diff --git a/packages/react/src/modules/guide/components/Toolbar/V2/GuideRowDetails.tsx b/packages/react/src/modules/guide/components/Toolbar/V2/GuideRowDetails.tsx index f4ce5efaa..b7385548a 100644 --- a/packages/react/src/modules/guide/components/Toolbar/V2/GuideRowDetails.tsx +++ b/packages/react/src/modules/guide/components/Toolbar/V2/GuideRowDetails.tsx @@ -1,10 +1,12 @@ import { Box, Stack } from "@telegraph/layout"; +import { Tooltip } from "@telegraph/tooltip"; import { Text } from "@telegraph/typography"; import { StatusColor, GuideAnnotatedStatusDot as StatusDot, } from "./GuideAnnotatedStatusDot"; +import { ERROR_MESSAGE } from "./helpers"; import { AnnotatedGuide, UncommittedGuide, @@ -43,34 +45,65 @@ const StatusRow = ({ label, value, color, + tooltip, }: { label: string; value: string; color: StatusColor; -}) => ( - - - - {label}: - - - {value} - - -); + tooltip?: React.ReactNode; +}) => { + return ( + + + + + + {label}: + + + {value} + + + + + ); +}; -const getDisplayValue = ( +export type StatusSummary = { + color: StatusColor; + label: string; + description: string; +}; + +export const getSelectableStatusSummary = ( status: "returned" | "throttled" | "queried" | undefined, -): { value: string; color: StatusColor } => { +): StatusSummary => { switch (status) { case "returned": - return { value: "Ready to display", color: "blue" }; + return { + label: "Ready to display", + color: "blue", + description: "This guide is queried and ready to display", + }; case "throttled": - return { value: "Throttled", color: "yellow" }; + return { + label: "Throttled", + color: "yellow", + description: + "This guide is queried and ready to display, but throttled currently", + }; case "queried": - return { value: "Queued", color: "gray" }; + return { + label: "Queued", + color: "gray", + description: "This guide is queried but is not ready to display", + }; default: - return { value: "Not found", color: "red" }; + return { + label: "Not queried", + color: "red", + description: `This guide is not queried (${ERROR_MESSAGE.focusUnselectableGuide.toLowerCase()})`, + }; } }; @@ -90,7 +123,9 @@ export const GuideRowDetails = ({ } const { annotation } = guide; - const display = getDisplayValue(annotation.selectable.status); + const selectableStatusSummary = getSelectableStatusSummary( + annotation.selectable.status, + ); return ( @@ -99,16 +134,19 @@ export const GuideRowDetails = ({ label="Active" value={annotation.active.status ? "Yes" : "No"} color={annotation.active.status ? "blue" : "red"} + tooltip="Eligible if the guide is currently active" /> @@ -117,11 +155,22 @@ export const GuideRowDetails = ({ label="Activation" value={annotation.activatable.status ? "Yes" : "No"} color={annotation.activatable.status ? "blue" : "red"} + tooltip="Visible when the user's current location matches the guide's activation rules" /> + Visible when the guide is queried via `useGuide(s)` in the current + page, +
+ and ready to display per its position in the display pipeline: +
+ {selectableStatusSummary.description} +
+ } />
diff --git a/packages/react/src/modules/guide/components/Toolbar/V2/helpers.ts b/packages/react/src/modules/guide/components/Toolbar/V2/helpers.ts index 8d096af1a..6547a26d5 100644 --- a/packages/react/src/modules/guide/components/Toolbar/V2/helpers.ts +++ b/packages/react/src/modules/guide/components/Toolbar/V2/helpers.ts @@ -88,5 +88,5 @@ export const clearRunConfigLS = () => { export const ERROR_MESSAGE = { focusUnknownGuide: "No such guide exists", focusUncommittedGuide: "This guide has not been committed", - focusUnselectableGuide: "No component that can render this guide is present", + focusUnselectableGuide: "No component that can display this guide is present", };