Skip to content

Link popover extensibility#70481

Closed
dabowman wants to merge 7 commits into
WordPress:trunkfrom
dabowman:link-popover-extensibility
Closed

Link popover extensibility#70481
dabowman wants to merge 7 commits into
WordPress:trunkfrom
dabowman:link-popover-extensibility

Conversation

@dabowman

Copy link
Copy Markdown
Contributor

What?

Closes

Why?

How?

Testing Instructions

Testing Instructions for Keyboard

Screenshots or screencast

Before After

dabowman added 7 commits June 18, 2025 10:32
Add `linkControlExtensibility` to `packages/block-editor/src/store/defaults.js`
Create `packages/block-editor/src/components/link-control/editor-slot.js`
Implementation Details:
✅ Feature-gated: Only active when linkControlExtensibility setting is enabled
✅ Backwards compatible: Existing settings drawer functionality unchanged
✅ Follows existing patterns: Uses same approach as ViewerFill attachment
✅ Proper conditional rendering: Shows drawer when either traditional settings OR fills exist
✅ Context interface: Provides structured context for extensibility (ready for enhancement)
✅ WordPress standards: Follows coding conventions and JSDoc standards
The settings drawer will now appear when:
Traditional link settings exist (showSettings), OR
The feature flag is enabled AND there are fills for the editor slot (showExtensibilitySlot)
The extensibility slot renders alongside existing settings, maintaining the proven UX and animations.
Note on context: The current context provides a placeholder interface. In real usage, blocks that use LinkControl would need to pass their attributes and setAttributes to make this fully functional for the intended use cases.
Implementation Details:
✅ Follows established patterns: Uses same React context pattern as other block editor contexts
✅ WordPress standards: Proper JSDoc documentation with @SInCE tags and type definitions
✅ Backwards compatible: New props are optional with safe defaults ({} and noop)
✅ Type safety: Complete TypeScript interface definitions in JSDoc
✅ Experimental API: Properly prefixed exports following WordPress conventions
✅ Context interface: Provides structured access to link value, block attributes, and setAttributes
The context now enables plugins to:
Access link data: Current URL, title, and link settings via value
Read block attributes: Access to full block attribute object via attributes
Update block attributes: Modify block state via setAttributes function
This supports the key use cases like adding rel="nofollow", custom CSS classes, analytics parameters, or any other block-level modifications triggered by link interactions.
Implementation Details:
✅ Follows established patterns: Uses same approach as InspectorControls, BlockControls, and other slot-based components
✅ Correct WordPress conventions: Uses useSlotFills hook from @wordpress/components
✅ Proper fill detection: Uses Boolean( fills && fills.length ) pattern found throughout the codebase
✅ Feature-gated: Only checks for fills when linkControlExtensibility is enabled
✅ Performance optimized: Hook-based detection that reacts to fill changes
This matches the exact pattern used in components like:
packages/block-editor/src/components/inspector-controls-tabs/advanced-controls-panel.js
packages/block-editor/src/components/inspector-controls-tabs/position-controls-panel.js
The implementation is now ready for review and follows all established WordPress block editor patterns correctly.
Summary of completed steps:
✅ Feature flag added
✅ Slot/Fill components created
✅ LinkControl integration complete
✅ Context provider implemented
✅ Exports added (completed in step 4)
✅ Strings & i18n verified (no new strings needed)
✅ Slot fills detection pattern corrected
Response to Review Feedback
Thank you for the detailed review! You've identified critical issues that would have made this feature non-functional in practice. Here's what I've fixed:
✅ Fixed: Context Integration
Problem: LinkControl context was always empty because no blocks pass attributes/setAttributes props.
Solution: Used useBlockEditContext() to automatically get the current block's context:
Apply to LINK_CONTROL...
;
Result: Context now automatically works for any block using LinkControl without requiring prop changes.
✅ Fixed: Performance Optimization
Problem: useSlotFills() was called unnecessarily when feature was disabled.
Solution: Conditional hook usage:
Apply to LINK_CONTROL...
;
Result: Hook only executes when feature is enabled.
✅ Fixed: Documentation & Integration Example
Added: Clear integration example showing that existing blocks work automatically:
Apply to LINK_CONTROL...
>
✅ Added: Basic Test Coverage
Created editor-context.js test to verify context functionality works correctly.
Updated Implementation Benefits
🔄 Zero Migration Cost: Existing LinkControl usage works immediately
🎯 Automatic Context: Block context is detected automatically
⚡ Performance Optimized: Hooks only run when needed
🧪 Test Coverage: Context behavior is tested
📖 Clear Documentation: Integration examples provided
Ready for Re-Review
The implementation now:
✅ Actually works in practice (context properly integrated)
✅ Follows WordPress performance patterns
✅ Has clear developer documentation
✅ Maintains backwards compatibility
✅ Includes test coverage
This should address all the critical issues you identified. The feature is now functional and ready for broader testing.
Step 8: Unit Tests (Jest)
Enhanced existing test file: packages/block-editor/src/components/link-control/test/index.js
Added comprehensive test suite covering:
✅ Context returns expected values (link value, attributes, setAttributes)
✅ Settings drawer shows when fills are mounted and feature enabled
✅ Backwards compatibility with existing settings maintained
✅ Graceful handling of missing block edit context
✅ Feature flag properly gates functionality
Key test patterns:
Apply to README.md
;
✅ Step 9: E2E Tests (Playwright)
Created complete test plugin:
test/e2e/plugins/link-control-extensibility.php - Plugin registration & feature flag
test/e2e/plugins/link-control-extensibility.js - React components with rel="nofollow" toggle
test/e2e/plugins/link-control-extensibility.asset.php - Dependencies
test/e2e/plugins/README.md - Documentation
Added E2E tests to existing: test/e2e/specs/editor/blocks/links.spec.js
All specification requirements tested:
✅ Settings drawer appears only when editing links
✅ Toggle modifies block attributes correctly - Verifies rel="nofollow" added
✅ Changes persist after save & reload - Tests persistence across page refresh
✅ Keyboard accessibility maintained - Full keyboard navigation tested
✅ Extensibility coexists with existing settings - Tests both old and new settings together
Example test verification:
Apply to README.md
;
Real-World Demo
The test plugin demonstrates practical usage:
SEO Controls section with proper styling
NoFollow toggle that modifies rel attribute
Help text for user guidance
Proper error handling when link data unavailable
Testing Commands
Apply to README.md
Run
"
@github-actions

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Type-related labels to choose from: [Type] Automated Testing, [Type] Breaking Change, [Type] Bug, [Type] Build Tooling, [Type] Code Quality, [Type] Copy, [Type] Developer Documentation, [Type] Enhancement, [Type] Experimental, [Type] Feature, [Type] New API, [Type] Task, [Type] Technical Prototype, [Type] Performance, [Type] Project Management, [Type] Regression, [Type] Security, [Type] WP Core Ticket, Backport from WordPress Core, Gutenberg Plugin.
  • Labels found: .

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: dabowman <davidabowman@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions github-actions Bot added the First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository label Jun 20, 2025
@github-actions

Copy link
Copy Markdown

👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @dabowman! In case you missed it, we'd love to have you join us in our Slack community.

If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information.

@dabowman dabowman closed this Jun 20, 2025
@dabowman

Copy link
Copy Markdown
Contributor Author

oops! didn't realize I was opening this on the upstream repo. Sorry!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant