diff --git a/.changeset/tired-bats-rescue.md b/.changeset/tired-bats-rescue.md new file mode 100644 index 000000000..589a646bd --- /dev/null +++ b/.changeset/tired-bats-rescue.md @@ -0,0 +1,5 @@ +--- +"@knocklabs/react": patch +--- + +[Guides] Add a settings toggle to filter only active guies in the guide toolbar v2 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 4963064c3..cc88ce238 100644 --- a/packages/react/src/modules/guide/components/Toolbar/V2/GuideContextDetails.tsx +++ b/packages/react/src/modules/guide/components/Toolbar/V2/GuideContextDetails.tsx @@ -4,7 +4,15 @@ import { Toggle } from "@telegraph/toggle"; import { Tooltip } from "@telegraph/tooltip"; import { Text } from "@telegraph/typography"; -export const GuideContextDetails = () => { +type Props = { + activeOnly: boolean; + onActiveOnlyChange: (value: boolean) => void; +}; + +export const GuideContextDetails = ({ + activeOnly, + onActiveOnlyChange, +}: Props) => { const { client } = useGuideContext(); const { debugSettings } = useStore(client.store, (state) => ({ debugSettings: state.debug || {}, @@ -67,6 +75,26 @@ export const GuideContextDetails = () => { }} /> + + + + Active only + + + + diff --git a/packages/react/src/modules/guide/components/Toolbar/V2/V2.tsx b/packages/react/src/modules/guide/components/Toolbar/V2/V2.tsx index c40921ed9..823ea7422 100644 --- a/packages/react/src/modules/guide/components/Toolbar/V2/V2.tsx +++ b/packages/react/src/modules/guide/components/Toolbar/V2/V2.tsx @@ -52,8 +52,13 @@ const Kbd = ({ children }: { children: React.ReactNode }) => { const filterGuides = ( guides: InspectionResultOk["guides"], displayOption: DisplayOption, + opts?: { activeOnly?: boolean }, ) => { return guides.filter((guide) => { + if (opts?.activeOnly && !guide.annotation.active.status) { + return false; + } + const { isEligible, isQualified } = guide.annotation; const isDisplayable = isEligible && isQualified; @@ -72,6 +77,7 @@ export const V2 = () => { const [displayOption, setDisplayOption] = React.useState("only-eligible"); + const [activeOnly, setActiveOnly] = React.useState(false); const [runConfig, setRunConfig] = React.useState(() => getRunConfig()); const [isCollapsed, setIsCollapsed] = React.useState(false); const [isContextPanelOpen, setIsContextPanelOpen] = React.useState(false); @@ -143,7 +149,30 @@ export const V2 = () => { } const guides = - result.status === "ok" ? filterGuides(result.guides, displayOption) : []; + result.status === "ok" + ? filterGuides(result.guides, displayOption, { activeOnly }) + : []; + + // Clear focus lock if the focused guide would be hidden under the given + // filter combination. + const maybeClearStaleFocus = ( + nextDisplayOption: DisplayOption, + nextActiveOnly: boolean, + ) => { + if (result?.status !== "ok") return; + + const debugSettings = client.store.state.debug; + const focusedKeys = Object.keys(debugSettings?.focusedGuideKeys || {}); + if (focusedKeys.length === 0) return; + + const stillVisible = filterGuides(result.guides, nextDisplayOption, { + activeOnly: nextActiveOnly, + }).find((g) => g.key === focusedKeys[0]); + + if (!stillVisible) { + client.setDebug({ ...debugSettings, focusedGuideKeys: {} }); + } + }; return ( { value={displayOption} onValueChange={(val: DisplayOption) => { if (!val) return; - - const debugSettings = client.store.state.debug; - - const focusedGuideKeys = Object.keys( - debugSettings?.focusedGuideKeys || {}, - ); - - // Exit out of focus if the currently focused guide is not - // part of the selected list filter. - if (result.status === "ok" && focusedGuideKeys.length > 0) { - const currFocusedGuide = filterGuides( - result.guides, - val, - ).find((g) => g.key === focusedGuideKeys[0]); - - if (!currFocusedGuide) { - client.setDebug({ - ...debugSettings, - focusedGuideKeys: {}, - }); - } - } - + maybeClearStaleFocus(val, activeOnly); setDisplayOption(val); }} > - All guides + {activeOnly ? "All active" : "All guides"} Eligible @@ -349,7 +356,13 @@ export const V2 = () => { {/* Collapsible panel to show context data */} {isContextPanelOpen && ( - + { + maybeClearStaleFocus(displayOption, nextActiveOnly); + setActiveOnly(nextActiveOnly); + }} + /> )} diff --git a/packages/react/src/modules/guide/components/Toolbar/V2/useInspectGuideClientStore.ts b/packages/react/src/modules/guide/components/Toolbar/V2/useInspectGuideClientStore.ts index edbbdf4ee..c9c044ef3 100644 --- a/packages/react/src/modules/guide/components/Toolbar/V2/useInspectGuideClientStore.ts +++ b/packages/react/src/modules/guide/components/Toolbar/V2/useInspectGuideClientStore.ts @@ -111,6 +111,9 @@ export type UncommittedGuide = { annotation: { isEligible: false; isQualified: false; + active: { + status: false; + }; selectable: { status: undefined; }; @@ -407,6 +410,9 @@ const newUncommittedGuide = (key: KnockGuide["key"], orderIndex: number) => annotation: { isEligible: false, isQualified: false, + active: { + status: false, + }, selectable: { status: undefined, },