From 3c6c5943ed0ca5cf99719bec93feab412d6e31e1 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 30 Mar 2026 23:59:52 -0400 Subject: [PATCH 1/4] wip --- .../Toolbar/V2/GuideContextDetails.tsx | 30 ++++++++++++++++++- .../guide/components/Toolbar/V2/V2.tsx | 25 ++++++++++++++-- 2 files changed, 51 insertions(+), 4 deletions(-) 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..3fb26d52e 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 GuideContextDetailsProps = { + activeOnly: boolean; + onActiveOnlyChange: (value: boolean) => void; +}; + +export const GuideContextDetails = ({ + activeOnly, + onActiveOnlyChange, +}: GuideContextDetailsProps) => { 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..64825f770 100644 --- a/packages/react/src/modules/guide/components/Toolbar/V2/V2.tsx +++ b/packages/react/src/modules/guide/components/Toolbar/V2/V2.tsx @@ -33,6 +33,10 @@ const HOTKEY_TOGGLE_IS_COLLAPSED = "Control"; const TOOLBAR_WIDTH = "540px"; +// XXX: +// Empty state message in the list +// Order index number + const Kbd = ({ children }: { children: React.ReactNode }) => { return ( { const filterGuides = ( guides: InspectionResultOk["guides"], displayOption: DisplayOption, + opts?: { activeOnly?: boolean }, ) => { return guides.filter((guide) => { const { isEligible, isQualified } = guide.annotation; const isDisplayable = isEligible && isQualified; + if (opts?.activeOnly) { + // XXX + const isActive = + "active" in guide.annotation + ? guide.annotation.active.status + : guide.active; + if (!isActive) return false; + } if (displayOption === "only-displayable" && !isDisplayable) { return false; } @@ -72,6 +85,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 +157,9 @@ export const V2 = () => { } const guides = - result.status === "ok" ? filterGuides(result.guides, displayOption) : []; + result.status === "ok" + ? filterGuides(result.guides, displayOption, { activeOnly }) + : []; return ( { }} > - All guides + {activeOnly ? "All active" : "All guides"} Eligible @@ -349,7 +365,10 @@ export const V2 = () => { {/* Collapsible panel to show context data */} {isContextPanelOpen && ( - + )} From 1a5b9df85e84a0935cdfc21f888146f8bdd2a8d5 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 31 Mar 2026 15:59:42 -0400 Subject: [PATCH 2/4] clean up --- .../Toolbar/V2/GuideContextDetails.tsx | 4 ++-- .../modules/guide/components/Toolbar/V2/V2.tsx | 16 ++++------------ .../Toolbar/V2/useInspectGuideClientStore.ts | 6 ++++++ 3 files changed, 12 insertions(+), 14 deletions(-) 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 3fb26d52e..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,7 @@ import { Toggle } from "@telegraph/toggle"; import { Tooltip } from "@telegraph/tooltip"; import { Text } from "@telegraph/typography"; -type GuideContextDetailsProps = { +type Props = { activeOnly: boolean; onActiveOnlyChange: (value: boolean) => void; }; @@ -12,7 +12,7 @@ type GuideContextDetailsProps = { export const GuideContextDetails = ({ activeOnly, onActiveOnlyChange, -}: GuideContextDetailsProps) => { +}: Props) => { const { client } = useGuideContext(); const { debugSettings } = useStore(client.store, (state) => ({ debugSettings: state.debug || {}, 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 64825f770..22d77156e 100644 --- a/packages/react/src/modules/guide/components/Toolbar/V2/V2.tsx +++ b/packages/react/src/modules/guide/components/Toolbar/V2/V2.tsx @@ -33,10 +33,6 @@ const HOTKEY_TOGGLE_IS_COLLAPSED = "Control"; const TOOLBAR_WIDTH = "540px"; -// XXX: -// Empty state message in the list -// Order index number - const Kbd = ({ children }: { children: React.ReactNode }) => { return ( { return guides.filter((guide) => { + if (opts?.activeOnly && !guide.annotation.active.status) { + return false; + } + const { isEligible, isQualified } = guide.annotation; const isDisplayable = isEligible && isQualified; - if (opts?.activeOnly) { - // XXX - const isActive = - "active" in guide.annotation - ? guide.annotation.active.status - : guide.active; - if (!isActive) return false; - } if (displayOption === "only-displayable" && !isDisplayable) { return false; } 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, }, From 76cec6732d0bfb4aa7bc8cb1785e03930cbb654f Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 31 Mar 2026 16:02:40 -0400 Subject: [PATCH 3/4] changeset --- .changeset/tired-bats-rescue.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tired-bats-rescue.md 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 From c98ae3347a15ce3cbf8338f7d69bd513394b9d97 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 31 Mar 2026 16:20:45 -0400 Subject: [PATCH 4/4] cursor review feedback --- .../guide/components/Toolbar/V2/V2.tsx | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) 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 22d77156e..823ea7422 100644 --- a/packages/react/src/modules/guide/components/Toolbar/V2/V2.tsx +++ b/packages/react/src/modules/guide/components/Toolbar/V2/V2.tsx @@ -153,6 +153,27 @@ export const V2 = () => { ? 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); }} > @@ -359,7 +358,10 @@ export const V2 = () => { { + maybeClearStaleFocus(displayOption, nextActiveOnly); + setActiveOnly(nextActiveOnly); + }} /> )}