diff --git a/platform/wab/src/wab/client/components/canvas/CanvasActions/CanvasActions.tsx b/platform/wab/src/wab/client/components/canvas/CanvasActions/CanvasActions.tsx index 38a9783eaef..395c8709609 100644 --- a/platform/wab/src/wab/client/components/canvas/CanvasActions/CanvasActions.tsx +++ b/platform/wab/src/wab/client/components/canvas/CanvasActions/CanvasActions.tsx @@ -6,13 +6,17 @@ import { globalHookCtx } from "@/wab/client/react-global-hook/globalHook"; import { RightTabKey, useStudioCtx } from "@/wab/client/studio-ctx/StudioCtx"; import { ViewCtx } from "@/wab/client/studio-ctx/view-ctx"; import { AnyArena } from "@/wab/shared/Arenas"; +import { getTplComponentArg } from "@/wab/shared/TplMgr"; +import { ensureBaseVariantSetting } from "@/wab/shared/Variants"; import { maybePropTypeToDisplayName } from "@/wab/shared/code-components/code-components"; -import { assert } from "@/wab/shared/common"; +import { assert, last } from "@/wab/shared/common"; import { CodeComponent, getComponentDisplayName, + getParamForVar, isCodeComponent, } from "@/wab/shared/core/components"; +import { getTplOwnerComponent } from "@/wab/shared/core/tpls"; import { InvalidArgMeta, ValComponent, @@ -20,7 +24,7 @@ import { getInvalidArgErrorMessage, isValComponent, } from "@/wab/shared/core/val-nodes"; -import { ArenaFrame } from "@/wab/shared/model/classes"; +import { ArenaFrame, isKnownVarRef } from "@/wab/shared/model/classes"; import { Tooltip } from "antd"; import $ from "jquery"; import { observer } from "mobx-react"; @@ -89,13 +93,57 @@ function _CanvasAction(props: { left: -10, }} onClick={(e) => { - viewCtx.studioCtx.rightTabKey = RightTabKey.settings; - viewCtx.highlightParam = { - param: invalidArgs[0].param, - tpl: valComponent.tpl, - }; - viewCtx.selectNewTpl(valComponent.tpl); e.stopPropagation(); + + // We start enforcing the settings tab, so that it's clear where the user should change something + viewCtx.studioCtx.rightTabKey = RightTabKey.settings; + + const invalidTpl = valComponent.tpl; + const invalidTplOwner = getTplOwnerComponent(invalidTpl); + const invalidParam = invalidArgs[0].param; + + // If the invalid component is owned by the current component, we can just hightlight the tpl and param + if (invalidTplOwner === viewCtx.currentComponent()) { + viewCtx.highlightParam = { + param: invalidParam, + tpl: invalidTpl, + }; + viewCtx.selectNewTpl(invalidTpl); + } else { + const valOwners = viewCtx.valState().valOwners(valComponent); + assert( + valOwners.length >= 1, + "There should be at least one val owners in the path from valComponent to root" + ); + + // This is the tpl in the current view that owns the invalid tpl, we will highlight it + const visibleTplOwner = last(valOwners).tpl; + + if (valOwners.length === 1) { + // If there is only one val owners, it means that the we are one wrapping away from the current view, + // we will check for linked props as a best effort to highlight the correct param + const arg = getTplComponentArg( + invalidTpl, + ensureBaseVariantSetting(invalidTpl), + invalidParam.variable + ); + + if (arg && isKnownVarRef(arg.expr)) { + // If it's a linked prop we highlight will get the respective param in the component + const linkedParam = getParamForVar( + visibleTplOwner.component, + arg.expr.variable + ); + + viewCtx.highlightParam = { + param: linkedParam, + tpl: visibleTplOwner, + }; + } + } + + viewCtx.selectNewTpl(visibleTplOwner); + } }} >