Add floating Traffic Boost actions#3445
Conversation
…tes to fire multiple times
…move react-draggable
…ecoming offset during a drag
…ed. Account for existing transformations when redragging.
📝 Walkthrough## Walkthrough
This change introduces a draggable, React-rendered floating actions bar inside the Traffic Boost preview iframe, enabling contextual link actions directly within the preview. The actions bar logic is moved from the footer to the iframe, with new hooks for drag-and-drop, resize handling, and dynamic positioning. Related props and UI are refactored accordingly.
## Changes
| File(s) | Change Summary |
|-----------------------------------------------------------------------------------------------------------------|----------------|
| src/content-helper/common/components/vertical-divider/component.tsx | Added optional `color` prop to `VerticalDivider`; fill color now customizable. |
| src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx | Introduced new `PreviewActions` React component for in-iframe floating action bar. |
| src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-footer.tsx | Removed all link action logic and props; now only renders navigation buttons. |
| src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-header.tsx<br>src/content-helper/dashboard-page/pages/traffic-boost/preview/preview.scss | Renamed CSS class for preview header actions. |
| src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-iframe.tsx | Integrated `PreviewActions` into iframe, added resize handling, new action callbacks, and dynamic bar positioning. |
| src/content-helper/dashboard-page/pages/traffic-boost/preview/components/text-selection-tooltip.tsx | Improved style injection idempotency, word boundary detection, multi-range selection validation, and text sanitization. |
| src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-draggable.ts | Added new `useDraggable` hook for drag-and-drop within iframe. |
| src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts | Enhanced to render React actions bar in highlight, added dynamic popover positioning, and new DOM structure. |
| src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-resize.ts | Added new `useResize` hook for monitoring element resize events. |
| src/content-helper/dashboard-page/pages/traffic-boost/preview/preview.tsx | Moved link action handlers from footer to iframe; refactored props and callbacks. |
| src/content-helper/editor-sidebar/smart-linking/utils.ts | Removed trailing blank line (no functional change). |
| src/@types/assets/window.d.ts | Added and reordered Parsely-related properties on the global `Window` interface. |
| src/UI/class-dashboard-page.php | Refactored inline script injection to consolidate multiple statements. |
| src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-wordpress-component-styles.ts | Added `useWordpressComponentStyles` hook for injecting WP component styles into iframes. |
## Sequence Diagram(s)
```mermaid
sequenceDiagram
participant User
participant PreviewIframe
participant useIframeHighlight
participant PreviewActions
participant useDraggable
User->>PreviewIframe: Interacts with link in iframe
PreviewIframe->>useIframeHighlight: Highlight link, render actions bar
useIframeHighlight->>PreviewActions: Render floating actions bar (React)
PreviewActions-->>User: Display action buttons (Accept, Remove, etc.)
User->>PreviewActions: Clicks action button or drags bar
PreviewActions->>PreviewIframe: Trigger callback (accept, remove, update, etc.)
PreviewActions->>useDraggable: Initiate drag events
useDraggable-->>PreviewActions: Update position within iframe boundaries
PreviewIframe->>useIframeHighlight: On resize, adjust actions bar positionPossibly related PRs
Suggested reviewers
|
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts (2)
431-445:⚠️ Potential issueUnmount React roots before removing DOM elements.
The
removeAndCleanfunction should unmount any React roots before removing the container to prevent memory leaks.Add this before removing the container:
const removeAndClean = ( highlight: Element, container: ParentNode, rootParent: ParentNode ) => { + // Unmount React root if it exists + const actionsContainer = container.querySelector( '.parsely-traffic-boost-popover-actions' ) as any; + if ( actionsContainer?._reactRoot ) { + actionsContainer._reactRoot.unmount(); + } + // Create a document fragment to temporarily hold the children. const fragment = iframeDocument.createDocumentFragment();
395-396:⚠️ Potential issueAdd cleanup for React roots to prevent memory leaks.
React roots created with
createRootmust be unmounted before removing DOM elements to prevent memory leaks. This issue was mentioned in previous reviews but hasn't been addressed.Store the root reference on the container element so it can be unmounted during cleanup.
// Create popover content. const root = createRoot( actionsContainer ); root.render( actionsBar ); + // Store root reference for cleanup + ( actionsContainer as any )._reactRoot = root;
🧹 Nitpick comments (1)
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-wordpress-component-styles.ts (1)
18-18: Add period to line comment.Line comments should end with a period according to WordPress coding standards.
- console.error( 'WordPress component styles URL not found' ); // eslint-disable-line no-console + console.error( 'WordPress component styles URL not found' ); // eslint-disable-line no-console.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
build/content-helper/dashboard-page.asset.phpis excluded by!build/**build/content-helper/dashboard-page.jsis excluded by!build/**
📒 Files selected for processing (5)
src/@types/assets/window.d.ts(1 hunks)src/UI/class-dashboard-page.php(1 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/components/text-selection-tooltip.tsx(5 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts(14 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-wordpress-component-styles.ts(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- src/UI/class-dashboard-page.php
- src/@types/assets/window.d.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{js,ts,tsx,jsx}`: "Perform a detailed review of the provided code with following key aspects in mind: - Review the code to ensure it is well-structured and adheres to best ...
**/*.{js,ts,tsx,jsx}: "Perform a detailed review of the provided code with following key aspects in mind:
- Review the code to ensure it is well-structured and adheres to best practices.
- Verify compliance with WordPress coding standards.
- Ensure the code is well-documented.
- Check for security vulnerabilities and confirm the code is secure.
- Optimize the code for performance, removing any unnecessary elements.
- Validate JSDoc comments for accuracy, currency, and adherence to WordPress coding standards.
- Ensure each line comment concludes with a period.
- Confirm every JSDoc comment includes a @SInCE tag indicating the next version of the plugin to include the code.
- Guarantee compatibility with the latest version of WordPress, avoiding deprecated functions or features."
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-wordpress-component-styles.tssrc/content-helper/dashboard-page/pages/traffic-boost/preview/components/text-selection-tooltip.tsxsrc/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts
⏰ Context from checks skipped due to timeout of 90000ms (10)
- GitHub Check: PHP 8.3
- GitHub Check: PHP 8.1
- GitHub Check: PHP 8.1
- GitHub Check: PHP 8.3
- GitHub Check: Analyze (javascript)
- GitHub Check: build
- GitHub Check: E2E against WordPress latest
- GitHub Check: PHP 8.1
- GitHub Check: Basic CS and QA checks
- GitHub Check: build
🔇 Additional comments (8)
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-wordpress-component-styles.ts (1)
13-37: Well-implemented centralization of WordPress component styles injection!This hook successfully addresses the previous concern about hardcoded paths by retrieving the URL from the global
window.wpParselyDependenciesobject. The implementation includes proper error handling and prevents duplicate style injection.src/content-helper/dashboard-page/pages/traffic-boost/preview/components/text-selection-tooltip.tsx (4)
10-10: Good refactoring to use the centralized style injection hook!The migration to
useWordpressComponentStylesproperly centralizes the WordPress component style injection logic.Also applies to: 20-24
283-283: Improved word boundary detection for contractions!Adding the right single quotation mark (') to the regex patterns properly handles contractions and possessives.
Also applies to: 289-289
417-430: Excellent validation for multi-range selections!The new validation logic properly ensures that multi-range selections remain within the same paragraph or list item, preventing invalid cross-paragraph selections.
481-499: Robust text extraction from complex selections!The implementation properly extracts plain text content from multi-range selections, stripping embedded HTML and handling newlines correctly.
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts (3)
50-51: Good integration of centralized style injection!The migration to use
useWordpressComponentStylesproperly centralizes the WordPress component style injection.Also applies to: 65-65
69-232: Well-structured highlight container and action bar implementation!The new container structure with nested highlight span and actions div provides good separation. The comprehensive styles handle positioning, alignment variants, drag handles, and responsive behavior effectively.
Also applies to: 349-351, 366-367, 386-387, 392-393
737-768: Smart positioning adjustment for action bar!The
adjustActionsBarPositionmethod effectively handles dynamic repositioning during resize events, preventing the action bar from overflowing iframe boundaries.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts (2)
59-59: Excellent resolution of hardcoded CSS path issue.The integration with
useWordpressComponentStylesproperly addresses the previous concern about hardcoded WordPress component CSS paths.Also applies to: 74-74
353-361: Proper React root lifecycle management implemented.The React root creation and cleanup logic correctly addresses the previous memory leak concerns by properly unmounting roots before removal and tracking them globally for cleanup.
Also applies to: 408-412
🧹 Nitpick comments (1)
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts (1)
78-242: Well-structured CSS with minor documentation suggestion.The comprehensive CSS styling is well-organized and handles positioning, alignment, and visual states properly. Consider documenting the z-index choice (1000) to explain overlay hierarchy decisions.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
build/content-helper/dashboard-page.asset.phpis excluded by!build/**build/content-helper/dashboard-page.jsis excluded by!build/**
📒 Files selected for processing (2)
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/text-selection-tooltip.tsx(6 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts(13 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/content-helper/dashboard-page/pages/traffic-boost/preview/components/text-selection-tooltip.tsx
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{js,ts,tsx,jsx}`: "Perform a detailed review of the provided code with following key aspects in mind: - Review the code to ensure it is well-structured and adheres to best ...
**/*.{js,ts,tsx,jsx}: "Perform a detailed review of the provided code with following key aspects in mind:
- Review the code to ensure it is well-structured and adheres to best practices.
- Verify compliance with WordPress coding standards.
- Ensure the code is well-documented.
- Check for security vulnerabilities and confirm the code is secure.
- Optimize the code for performance, removing any unnecessary elements.
- Validate JSDoc comments for accuracy, currency, and adherence to WordPress coding standards.
- Ensure each line comment concludes with a period.
- Confirm every JSDoc comment includes a @SInCE tag indicating the next version of the plugin to include the code.
- Guarantee compatibility with the latest version of WordPress, avoiding deprecated functions or features."
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: build
- GitHub Check: E2E against WordPress latest
- GitHub Check: build
🔇 Additional comments (4)
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts (4)
18-24: LGTM! Proper React root lifecycle management.The global interface extension provides a clean way to track React roots for proper cleanup, addressing the previous memory leak concerns.
38-38: Well-typed React prop addition.The
actionsBarprop is properly typed asReact.ReactNodeand follows WordPress documentation standards.
363-365: Well-designed container structure for floating actions.The new highlight container structure properly separates content from actions bar and supports the floating actions functionality while maintaining clean DOM organization.
Also applies to: 380-380, 392-392, 400-400, 406-406
752-783: Solid dynamic positioning implementation.The
adjustActionsBarPositionfunction properly handles responsive positioning with appropriate bounds checking and uses standard layout completion patterns.
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts
Show resolved
Hide resolved
…ress/Internal dependencies"
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx (2)
147-199: Remove unnecessary Fragment wrapper.The Fragment around the ternary operator is redundant since it only contains one child element.
Apply this diff to remove the unnecessary Fragment:
- { isInboundLink && ( - <> - { selectedText ? ( + { isInboundLink && selectedText ? ( <> <Button variant="primary" onClick={ () => onUpdateLink( activeLink, restoreOriginal ) } isBusy={ isAccepting } disabled={ isAccepting } icon={ isAccepting ? null : check } >{ isAccepting ? __( 'Updating…', 'wp-parsely' ) : __( 'Update Link', 'wp-parsely' ) }</Button> { activeLink.smartLink?.is_link_replacement && ( <CheckboxControl __nextHasNoMarginBottom label={ __( 'Restore original link?', 'wp-parsely' ) } checked={ restoreOriginal } onChange={ ( value ) => { setRestoreOriginal( value ); } } /> ) } <VerticalDivider size={ 48 } color="#1e1e1e" /> <Button variant="tertiary" onClick={ onRestoreOriginal } icon={ undo } > { __( 'Clear changes', 'wp-parsely' ) } </Button> - ) : ( + </> + ) } + { isInboundLink && ! selectedText && ( <> <Button variant={ isRemoving ? 'primary' : 'tertiary' } icon={ isRemoving ? null : close } onClick={ () => onRemove( activeLink, restoreOriginal ) } isBusy={ isRemoving } disabled={ isRemoving } isDestructive >{ isRemoving ? __( 'Removing…', 'wp-parsely' ) : __( 'Remove Link', 'wp-parsely' ) }</Button> { activeLink.smartLink?.is_link_replacement && ( <CheckboxControl __nextHasNoMarginBottom label={ __( 'Restore original link?', 'wp-parsely' ) } checked={ restoreOriginal } onChange={ ( value ) => { setRestoreOriginal( value ); } } /> ) } - ) } - </> - ) } + </> + ) }🧰 Tools
🪛 Biome (1.9.4)
[error] 147-199: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment(lint/complexity/noUselessFragments)
133-133: Consider using CSS variables for colors.The hardcoded color values could be moved to CSS variables for better maintainability and theming support.
Example approach:
-<VerticalDivider size={ 48 } color="#1e1e1e" /> +<VerticalDivider size={ 48 } color="var(--wp-parsely-text-primary)" />Also applies to: 167-167
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/content-helper/common/components/loading/component.tsx(1 hunks)src/content-helper/common/icons/error-icon.tsx(1 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/components/link-options-panel.tsx(2 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx(1 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-footer.tsx(1 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-header.tsx(2 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-iframe.tsx(9 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/components/text-selection-tooltip.tsx(6 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-draggable.ts(1 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-resize.ts(1 hunks)
✅ Files skipped from review due to trivial changes (4)
- src/content-helper/common/components/loading/component.tsx
- src/content-helper/common/icons/error-icon.tsx
- src/content-helper/dashboard-page/pages/traffic-boost/preview/components/link-options-panel.tsx
- src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-header.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
- src/content-helper/dashboard-page/pages/traffic-boost/preview/components/text-selection-tooltip.tsx
- src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-footer.tsx
- src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-resize.ts
- src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-iframe.tsx
- src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-draggable.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{js,ts,tsx,jsx}`: "Perform a detailed review of the provided code with following key aspects in mind: - Review the code to ensure it is well-structured and adheres to best ...
**/*.{js,ts,tsx,jsx}: "Perform a detailed review of the provided code with following key aspects in mind:
- Review the code to ensure it is well-structured and adheres to best practices.
- Verify compliance with WordPress coding standards.
- Ensure the code is well-documented.
- Check for security vulnerabilities and confirm the code is secure.
- Optimize the code for performance, removing any unnecessary elements.
- Validate JSDoc comments for accuracy, currency, and adherence to WordPress coding standards.
- Ensure each line comment concludes with a period.
- Confirm every JSDoc comment includes a @SInCE tag indicating the next version of the plugin to include the code.
- Guarantee compatibility with the latest version of WordPress, avoiding deprecated functions or features."
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx
🧬 Code Graph Analysis (1)
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx (5)
src/content-helper/dashboard-page/pages/traffic-boost/provider.ts (1)
TrafficBoostLink(40-45)src/content-helper/dashboard-page/pages/traffic-boost/preview/preview.tsx (1)
TextSelection(28-31)src/content-helper/dashboard-page/pages/traffic-boost/store.ts (3)
isGenerating(818-820)isAccepting(809-811)isRemoving(812-814)src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-draggable.ts (3)
OnDragProps(17-21)DRAG_MARGIN_PX(6-6)useDraggable(29-150)src/content-helper/common/components/vertical-divider/component.tsx (1)
VerticalDivider(28-34)
🪛 Biome (1.9.4)
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx
[error] 147-199: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment
(lint/complexity/noUselessFragments)
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: E2E against WordPress latest
- GitHub Check: build
- GitHub Check: build
🔇 Additional comments (3)
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx (3)
1-18: LGTM! Imports follow WordPress coding standards.The imports are well-organized and follow WordPress conventions properly.
19-33: LGTM! Interface follows WordPress JSDoc standards.The interface is well-documented with proper @SInCE versioning and clear prop definitions.
43-101: LGTM! Component logic is well-implemented.The dragging logic correctly implements boundary constraints and follows React best practices with proper hook usage.
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx
Outdated
Show resolved
Hide resolved
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-draggable.ts
Outdated
Show resolved
Hide resolved
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-draggable.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx (1)
152-204: Remove unnecessary Fragment wrapper.The outer Fragment is redundant since it's the only child of the conditional expression.
Apply this diff to remove the unnecessary Fragment:
{ isInboundLink && ( - <> { selectedText ? ( <> <Button variant="primary" onClick={ () => onUpdateLink( activeLink, restoreOriginal ) } isBusy={ isAccepting } disabled={ isAccepting } icon={ isAccepting ? null : check } >{ isAccepting ? __( 'Updating…', 'wp-parsely' ) : __( 'Update Link', 'wp-parsely' ) }</Button> { activeLink.smartLink?.is_link_replacement && ( <CheckboxControl __nextHasNoMarginBottom label={ __( 'Restore original link?', 'wp-parsely' ) } checked={ restoreOriginal } onChange={ ( value ) => { setRestoreOriginal( value ); } } /> ) } <VerticalDivider size={ 48 } color="#1e1e1e" /> <Button variant="tertiary" onClick={ onRestoreOriginal } icon={ undo } > { __( 'Clear changes', 'wp-parsely' ) } </Button> </> ) : ( <> <Button variant={ isRemoving ? 'primary' : 'tertiary' } icon={ isRemoving ? null : close } onClick={ () => onRemove( activeLink, restoreOriginal ) } isBusy={ isRemoving } disabled={ isRemoving } isDestructive >{ isRemoving ? __( 'Removing…', 'wp-parsely' ) : __( 'Remove Link', 'wp-parsely' ) }</Button> { activeLink.smartLink?.is_link_replacement && ( <CheckboxControl __nextHasNoMarginBottom label={ __( 'Restore original link?', 'wp-parsely' ) } checked={ restoreOriginal } onChange={ ( value ) => { setRestoreOriginal( value ); } } /> ) } </> ) } - </> ) }🧰 Tools
🪛 Biome (1.9.4)
[error] 152-204: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment(lint/complexity/noUselessFragments)
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
build/content-helper/dashboard-page.asset.phpis excluded by!build/**build/content-helper/dashboard-page.jsis excluded by!build/**
📒 Files selected for processing (5)
src/UI/class-dashboard-page.php(1 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx(1 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-iframe.tsx(8 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-draggable.ts(1 hunks)src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts(13 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/UI/class-dashboard-page.php
- src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-draggable.ts
- src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-iframe.tsx
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{js,ts,tsx,jsx}`: "Perform a detailed review of the provided code with following key aspects in mind: - Review the code to ensure it is well-structured and adheres to best ...
**/*.{js,ts,tsx,jsx}: "Perform a detailed review of the provided code with following key aspects in mind:
- Review the code to ensure it is well-structured and adheres to best practices.
- Verify compliance with WordPress coding standards.
- Ensure the code is well-documented.
- Check for security vulnerabilities and confirm the code is secure.
- Optimize the code for performance, removing any unnecessary elements.
- Validate JSDoc comments for accuracy, currency, and adherence to WordPress coding standards.
- Ensure each line comment concludes with a period.
- Confirm every JSDoc comment includes a @SInCE tag indicating the next version of the plugin to include the code.
- Guarantee compatibility with the latest version of WordPress, avoiding deprecated functions or features."
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.tssrc/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx
🧬 Code Graph Analysis (2)
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts (2)
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-wordpress-component-styles.ts (1)
useWordpressComponentStyles(13-37)src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-draggable.ts (1)
DRAG_MARGIN_PX(6-6)
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx (5)
src/content-helper/dashboard-page/pages/traffic-boost/provider.ts (1)
TrafficBoostLink(40-45)src/content-helper/dashboard-page/pages/traffic-boost/preview/preview.tsx (1)
TextSelection(28-31)src/content-helper/dashboard-page/pages/traffic-boost/store.ts (3)
isGenerating(818-820)isAccepting(809-811)isRemoving(812-814)src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-draggable.ts (3)
OnDragProps(17-21)DRAG_MARGIN_PX(6-6)useDraggable(29-153)src/content-helper/common/components/vertical-divider/component.tsx (1)
VerticalDivider(28-34)
🪛 Biome (1.9.4)
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx
[error] 152-204: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment
(lint/complexity/noUselessFragments)
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: build
- GitHub Check: E2E against WordPress latest
- GitHub Check: build
🔇 Additional comments (6)
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx (1)
1-210: Excellent component implementation!The PreviewActions component is well-structured with proper WordPress coding standards compliance:
- Clean separation of concerns with clear prop interfaces
- Proper JSDoc documentation with @SInCE tags
- Appropriate use of WordPress data selectors and components
- Good accessibility support (drag handle has proper ARIA attributes)
- Logical conditional rendering based on link types and selection state
- Proper integration with the useDraggable hook for positioning constraints
The drag functionality and button states are handled correctly, providing a smooth user experience.
🧰 Tools
🪛 Biome (1.9.4)
[error] 152-204: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment(lint/complexity/noUselessFragments)
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-iframe-highlight.ts (5)
18-24: Well-designed global state management.The global window interface declaration for tracking the React root is a clean solution for managing the single floating actions bar instance within the iframe context. This approach properly encapsulates the implementation detail while enabling necessary cleanup.
78-241: Comprehensive CSS styling for floating actions bar.The CSS styles cover all necessary scenarios:
- Proper positioning with responsive alignment classes
- Clean visual design with appropriate spacing and borders
- Drag handle styling with proper cursor states
- Button layout and sizing
- Responsive behavior with left/right alignment options
The styles integrate well with WordPress component styles and provide a polished user interface.
353-412: Excellent React root management implementation.The React rendering logic properly handles:
- Cleanup of existing actions before creating new ones
- Proper unmounting of React roots to prevent memory leaks
- Clean DOM structure with highlight containers
- Integration of the actions bar into the highlight flow
The implementation follows React best practices for portal-like rendering within iframes.
751-782: Smart responsive positioning logic.The
adjustActionsBarPositionmethod provides intelligent positioning:
- Removes existing alignment classes before recalculating
- Uses proper timing with setTimeout to allow layout completion
- Applies margin-aware boundary checking with
DRAG_MARGIN_PX- Handles both left and right overflow scenarios
This ensures the actions bar remains visible and usable across different viewport sizes.
1-792: Outstanding integration of React components with iframe highlighting.The enhanced
useIframeHighlighthook successfully integrates a React-based actions bar into the iframe highlighting system while maintaining:
- Clean separation of concerns
- Proper memory management with React root cleanup
- Responsive positioning logic
- Enhanced DOM structure for better containment
- Improved error handling and logging
The implementation demonstrates excellent technical execution and follows WordPress coding standards throughout.
src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-actions.tsx
Show resolved
Hide resolved
|
@acicovic Thank you for your comments and commits to fix things up. This should be ready for another review, thank you! |
src/content-helper/dashboard-page/pages/traffic-boost/preview/hooks/use-draggable.ts
Outdated
Show resolved
Hide resolved
acicovic
left a comment
There was a problem hiding this comment.
This is good to go! Thank you for your work on this, as well as for providing such an excellent, thorough and clear PR description.
…actions Add floating Traffic Boost actions bar" (d635a4a)
Description
This PR moves Traffic Boost actions from the page footer into a floating action bar:
Motivation and context
The previous location of the actions toolbar required moving between the post context to the bottom of the Traffic Boost page to interact with suggestions and links. The floating action bar layout allows actions to be completed in the place they were initiated for a faster experience.
How has this been tested?
This has been extensively tested manually. There are a few key problem areas during development that are worth additional focus in testing:
Reselecting suggested text, like shown below:
Screen.Recording.2025-06-06.at.12.20.06.PM.mov
The action bar markup is now embedded within the highlight mark and positioned absolutely above the suggestion. This caused some issues with our highlighting logic, which could stumble on the embedded
<div>s or see newlines where HTML was embedded. This lead to a number of scenarios where reselecting text containing the initial suggestion (partially or completely) caused a failure to highlight. Please try modifying suggestion text to include none, some of, or all of the original text in testing as shown above.Ensure that the bar stays within the bounds of post content during dragging, and that dragging feels natural and fluid:
bar-move-to-bounds.mov
This is a less common scenario, but we want to ensure that the floating action bar stays usable if the window is resized:
iframe-resize.mov
Ensure regular operations on the bar (accept, reject actions) and inbound links (remove action) function as before.
Technical notes
Component mounting
The actions component
<PreviewActions>is created in the context of the outer document, and passed intouseIframeHighlight()and mounted here. This was modeled after the existing "Use as Link Text" popover shown when text is selected.The combination of creating a component in the window's document and mounting it within the iframe allows communication between actions taken within the iframe in the outer page. This is similar to built-in React functionality like createPortal(), but I chose to use the same technique as the popover during development.
Actions bar markup as a child of highlight span
The actions bar is positioned absolutely above the current highlight, and structured this way:
This caused some issues that I didn't notice until late into development on this feature. Namely, the inserted HTML can cause newlines to appear in the
textContentof the highlight that weren't previously there when the highlight was only a single<span>, and the document selection sometimes including more than 1 combined range. This mainly affected:<TextSelectionTooltip>'shandleSelection(), which includes a check for when multiple ranges are present. This logic mainly kicks in when a user selects text that includes an existing suggestion. This also fixes an existing bug that could allow a user to select over multiple paragraphs and still improperly recieve a prompt to "Use as Link Text" when the placement was invalid.<TextSelectionTooltip>'sonSelect()callback, which also has additional steps to handle multiple ranges and strip out HTML when the selected text includes an existing suggestion.removeAndClean()used in the highlighting process was also modified to handle the parent container node that is added in highlight markup.See the "Reselecting suggested text" test suggestion above for ways to test this is working.
In retrospect, this particular issue would be a good reason to implement the actions bar without absolutely positioning above the highlight text, and instead inserting it into a non-content area of the iframe HTML. However to reimplement this bar that way, we'd need to modify offset calculations, add more event listeners and logic to keep it aligned, and potentially have other positioning issues. These workarounds were a trade-off to make positioning logic easier, but there were a lot of highlight-related problems that came out of this design.
Actions bar realignment
There are two main areas we actively change action bar alignment to fit the page:
<PreviewActions>'sonDrag()handler. This function receives a delta of movement when a user is dragging (e.g.x = -5, y = +2) and returns the resulting correct delta when taking into account the iframe's bounds. The logic in here keeps the actions bar withinDRAG_MARGIN_PX(5px) of the outer wall of the iframe.EDIT: This code was modified in eaee1f8 to fix a bug that caused the bar to drag weirdly in Safari. Instead of using the reported
movementX/movementYwe get from the mouse event, we instead store the initial coordinates and keep a running tally of the delta. It's a pretty minor change, and it fixes the Safari issue.When the page is resized after render, this
resizehook calls intoadjustActionsBarPosition(). The logic here works like this:First, remove the
align-leftandalign-rightCSS classes if they exist. This will place the suggestion bar centered above the suggestion:If the size of the toolbar (plus margin) is found to overflow on the right side of the page, add the
align-rightclass. This will move the actions bar so that the trailing edge aligns with the suggestion and keep the bar on the page:If the overflows on the left, add the
align-leftclass. This will move the actions bar so that the leading edge aligns with the suggestion and keep the bar on the page:Summary by CodeRabbit
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores