Conversation
|
Warning: Component files have been updated but no migrations have been added. See https://github.com/yext/visual-editor/blob/main/packages/visual-editor/src/components/migrations/README.md for more information. |
commit: |
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes. 💤 Files selected but had no reviewable changes (1)
You can disable this status message by setting the
WalkthroughAdds responsive header link overflow and collapse behavior with editor preview measurement. HeaderLinks gains a new Sequence Diagram(s)sequenceDiagram
participant Editor as Editor/Client
participant HeaderLinks as HeaderLinks Component
participant Measure as Measurement Scaffolding
participant Overflow as useOverflow Hook
participant Renderer as Link Renderer
Editor->>HeaderLinks: Mount with data (links, collapsedLinks, parentData)
activate HeaderLinks
HeaderLinks->>Measure: create hidden measurement divs (containerRef, contentRef)
Note right of Measure: hidden/absolute divs provide widths
Measure->>Overflow: computeOverflow(containerRef, contentRef, containerAdjustment)
activate Overflow
Overflow->>Overflow: adjustedWidth = container.width - containerAdjustment
Overflow->>Overflow: overflow = content.scrollWidth > adjustedWidth
Overflow-->>Measure: return visibleItems and overflowItems
deactivate Overflow
alt Overflow detected
HeaderLinks->>Renderer: render visibleItems + overflow dropdown (populate with overflowItems)
else No overflow
HeaderLinks->>Renderer: render all links inline
end
Renderer->>Editor: display links (apply collapsedLinks rules based on parentData.type)
deactivate HeaderLinks
Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ❌ 2❌ Failed checks (2 inconclusive)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/visual-editor/src/internal/utils/removeDuplicateImageActionBars.ts (1)
3-38: Hide all duplicates, not just the first match.
findTargetDivreturns a single node, so only one duplicate per target gets hidden. If multiple duplicates exist for the same translatedTarget, the extras remain visible. Consider returning all matches and hiding them all.✅ Suggested fix
-const findTargetDiv = ( - iframe: HTMLIFrameElement, - translatedTarget: string -): HTMLDivElement | null => { +const findTargetDivs = ( + iframe: HTMLIFrameElement, + translatedTarget: string +): HTMLDivElement[] => { // Get all action bar divs const targets = iframe?.contentDocument?.querySelectorAll( 'div[class^="_ActionBar"]' ); if (!targets) { - return null; + return []; } // For each div, check the great-grandparent and grandchild for specific criteria + const matches: HTMLDivElement[] = []; for (const targetDiv of targets) { const greatGrandparent = targetDiv.parentElement?.parentElement?.parentElement; // The great-grandparent of the duplicate bar will have a height of 0px if ( greatGrandparent && greatGrandparent.tagName === "DIV" && greatGrandparent.style.height === "0px" ) { const grandchild = targetDiv.querySelector( "div[class^='_ActionBar-label']" ); // The grandchild of the duplicate bar will have the translation of "Image" if (grandchild && grandchild.textContent.includes(translatedTarget)) { - return targetDiv as HTMLDivElement; + matches.push(targetDiv as HTMLDivElement); } } } - return null; + return matches; }; @@ - targets.forEach((target) => { - const targetDiv = findTargetDiv(iframe, target); - - // Hide the duplicate action bar if found - if (targetDiv) { - targetDiv.style.display = "none"; - } - }); + targets.forEach((target) => { + const targetDivs = findTargetDivs(iframe, target); + targetDivs.forEach((div) => { + div.style.display = "none"; + }); + });Also applies to: 63-69
🤖 Fix all issues with AI agents
In `@packages/visual-editor/src/components/header/HeaderLinks.tsx`:
- Around line 151-154: The effect uses hamburgerButtonRef.current in its
dependency array which won't trigger re-runs because React doesn't track
ref.current; replace this with a callback/state ref: add state like
[hamburgerButton, setHamburgerButton], change the element's ref to
ref={setHamburgerButton} (or implement a callback ref) and update the useEffect
to call registerOverlayPortal(hamburgerButton) with hamburgerButton in its
dependency array; ensure you also handle any necessary cleanup (e.g.,
unregisterOverlayPortal) inside the effect if applicable.
In `@packages/visual-editor/src/components/header/PrimaryHeaderSlot.tsx`:
- Around line 130-134: The effect currently calls
registerOverlayPortal(hamburgerButtonRef.current) but does not return its
cleanup and incorrectly uses hamburgerButtonRef.current in the dependency array;
update the React.useEffect that references registerOverlayPortal and
hamburgerButtonRef so it returns the cleanup function from registerOverlayPortal
(e.g., const cleanup = registerOverlayPortal(hamburgerButtonRef.current); return
cleanup;) and use hamburgerButtonRef (the ref object) in the dependency array
instead of hamburgerButtonRef.current to avoid unnecessary re-runs—locate the
effect in PrimaryHeaderSlot.tsx where React.useEffect, registerOverlayPortal,
and hamburgerButtonRef are used and apply these changes.
In `@packages/visual-editor/src/hooks/useOverflow.ts`:
- Around line 25-28: The ResizeObserver callback in useOverflow computes
hasOverflow using container.clientWidth - containerAdjustment which can go
negative; clamp the adjusted width to a minimum of 0 before comparing to
content.scrollWidth. Inside the ResizeObserver callback (in useOverflow),
compute const adjustedWidth = Math.max(0, container.clientWidth -
containerAdjustment) and then set hasOverflow = content.scrollWidth >
adjustedWidth before calling setIsOverflowing; update any related variable names
accordingly to ensure no negative values are used in the comparison.
In `@packages/visual-editor/src/internal/utils/removeDuplicateImageActionBars.ts`:
- Around line 56-60: The targets array in removeDuplicateImageActionBars.ts uses
pt("callToAction", "callToAction") which provides a non-user-facing fallback
label; change the fallback to a human-readable string (e.g., "Call to Action" or
"Call to action") so the pt helper and the duplicate-removal logic in
removeDuplicateImageActionBars (targets array) will match rendered labels when
translations are missing; update the second argument of pt for the
"callToAction" key accordingly.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/visual-editor/locales/platform/cs/visual-editor.json`:
- Line 193: Update the Czech translation value for the key
"alwaysCollapsedLinks" to use an imperative phrasing for consistency (e.g.,
change "Vždy sbalené odkazy" to an imperative like "Vždy sbalit odkazy" or "Vždy
sbalovat odkazy"); locate the "alwaysCollapsedLinks" entry in
packages/visual-editor/locales/platform/cs/visual-editor.json and replace the
string value with the chosen imperative form.
🧹 Nitpick comments (2)
packages/visual-editor/locales/platform/nb/visual-editor.json (1)
188-189: Consider aligning “koblinger” with the existing “lenker” terminology.Most “links” strings in this locale file use “lenker”. For UI consistency, you may want to align these two new labels with the prevailing term.
♻️ Suggested copy alignment
- "alwaysCollapsedLinks": "Alltid skjulte koblinger", + "alwaysCollapsedLinks": "Alltid skjulte lenker", ... - "linksTooltip": "Koblinger vil automatisk kollapse hvis visningsporten er for smal", + "linksTooltip": "Lenker vil automatisk kollapse hvis visningsporten er for smal",Also applies to: 296-296
packages/visual-editor/locales/platform/ro/visual-editor.json (1)
296-296: Minor grammatical polish suggestion.The translation uses "Linkuri" (indefinite), but "Linkurile" (with the definite article) would be more natural in Romanian when referring to specific links in context.
✏️ Suggested improvement
- "linksTooltip": "Linkuri se vor restrânge automat dacă fereastra de vizualizare este prea îngustă", + "linksTooltip": "Linkurile se vor restrânge automat dacă fereastra de vizualizare este prea îngustă",
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@packages/visual-editor/src/components/header/HeaderLinks.tsx`:
- Around line 161-168: windowWidth is computed once per render via
getWindow()?.innerWidth which doesn't update on window resize causing stale
collapsed-links visibility; change it to a stateful, reactive value: create a
state like const [windowWidth, setWindowWidth] = useState(() =>
getWindow()?.innerWidth || 1024) and add a useEffect that listens to window
'resize' events and calls setWindowWidth(getWindow()?.innerWidth || 1024) (with
optional debounce) and cleans up the listener; update every place that currently
computes getWindow()?.innerWidth (including other occurrences around the header
logic that affect collapsed links and breakpoints) to use this stateful
windowWidth so isOverflow and conditional UI react to resizes (references:
windowWidth, getWindow, useOverflow, navRef, measureContainerRef, isSecondary,
validAlwaysCollapsedLinks).
- Around line 158-160: The code currently always computes
validAlwaysCollapsedLinks from data.collapsedLinks which leaves collapsed links
present when the header switches to Primary; update the logic so
validAlwaysCollapsedLinks is only derived when the header is in Secondary mode
(e.g., check the component’s isSecondary/headerType prop or data.headerType) and
otherwise set it to an empty array; similarly apply this guard wherever
collapsedLinks are used later (the block that handles links at lines ~190-209)
so empty-state early returns for Primary work correctly.
In `@packages/visual-editor/src/internal/utils/removeDuplicateActionBars.ts`:
- Around line 31-34: In removeDuplicateActionBars, guard against
grandchild.textContent being null before calling .includes: change the condition
that currently reads "if (grandchild &&
grandchild.textContent.includes(translatedTarget))" to first ensure
grandchild.textContent is non-null (e.g., grandchild && grandchild.textContent
!= null && grandchild.textContent.includes(translatedTarget) or use optional
chaining like grandchild?.textContent?.includes(translatedTarget)); keep
returning targetDiv as HTMLDivElement when the guard passes.
🧹 Nitpick comments (1)
packages/visual-editor/src/internal/components/InternalLayoutEditor.tsx (1)
420-427: Pre-existing: Hooks called inside nestedactionBarfunction.Static analysis correctly flags that hooks (
useGetPuck,usePuck,React.useEffect) are called inside a nested function. While Puck likely treatsactionBaras a component internally, this pattern can cause issues if React doesn't recognize it as a stable component identity.The function rename on line 427 is correct. However, consider extracting
actionBarto a standalone component defined at module level to satisfy the Rules of Hooks and improve maintainability:const ActionBarOverride = ({ children, label }: { children: React.ReactNode; label: string }) => { // hooks called at top level of component ... }; // Then in overrides: actionBar: ActionBarOverride,This is a pre-existing pattern, so addressing it can be deferred.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@packages/visual-editor/src/components/header/ExpandedHeader.tsx`:
- Around line 213-219: Remove the debug console.log call in ExpandedHeader.tsx:
delete the console.log("EH data", data) statement after the setDeep(...) call
(the debug line that references variable data), ensuring no stray
console.debug/console.log remains in the ExpandedHeader component; if structured
logging is required instead, replace it with the app's logger utility rather
than leaving a console call.
In `@packages/visual-editor/src/components/header/HeaderLinks.tsx`:
- Line 141: Remove the debug console.log call in the HeaderLinks component:
delete the line console.log("render", data, parentData) found in HeaderLinks.tsx
(inside the HeaderLinks render/function body) before merging; if you need
telemetry keep a proper logger or use conditional debug logging instead and scan
the component for any other stray console.* calls to remove or replace.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/visual-editor/src/components/header/ExpandedHeader.tsx`:
- Around line 213-217: The setDeep call on the data variable is using an
incorrect path that includes a non-existent nested SecondaryHeaderSlot[0];
update the path passed to setDeep from
"props.slots.SecondaryHeaderSlot[0].props.slots.SecondaryHeaderSlot[0].props.slots.LinksSlot[0].props.parentData.type"
to
"props.slots.SecondaryHeaderSlot[0].props.slots.LinksSlot[0].props.parentData.type"
(referencing the setDeep call itself), and if the default layout already seeds
parentData.type as "Secondary" remove the entire setDeep invocation to avoid a
redundant mutation.
🧹 Nitpick comments (1)
packages/visual-editor/src/components/header/HeaderLinks.tsx (1)
219-235: Measurement div approach is correct, butlinkRefsappear unused.The hidden measurement div pattern is appropriate for calculating overflow. However,
linkRefsis populated at line 228 but doesn't appear to be read anywhere in the component. If this is for future use, consider adding a comment; otherwise, it can be removed to reduce unnecessary ref tracking.♻️ If unused, remove the ref assignment
- <li - key={`${type.toLowerCase()}.${index}`} - ref={(el) => (linkRefs.current[index] = el)} - className={themeManagerCn("py-4 md:py-0")} - > + <li + key={`${type.toLowerCase()}.${index}`} + className={themeManagerCn("py-4 md:py-0")} + >And remove line 146:
- const linkRefs = React.useRef<Array<HTMLLIElement | null>>([]);
|
Was hoping to avoid migration but the resolveData for HeaderLinks was being weird and so it was just easier to set the primary/secondary value in a migration |
asanehisa
left a comment
There was a problem hiding this comment.
did u wanna update the version in defaultLayoutData?
Good call, updated with the new defaults for photo gallery/product section too |
https://www.yext.com/s/4259018/yextsites/159383/pagesets