Skip to content

Conversation

@sapayth
Copy link
Member

@sapayth sapayth commented Oct 8, 2025

fixes #162

User Story
As a site admin, I want to add a Sidebar block to my documentation pages so that I can display selected docs, sections, and docs with customizable order and layout, making navigation easier for users.

Description
Introduce a "Sidebar" Gutenberg block in weDocs. The block should allow selecting ocsd, including/excluding categories, defining order, and customizing layout.

Developers can follow the default Gutenberg block handbook for implementation standards and coding best practices.

Summary by CodeRabbit

  • New Features
    • Introduced a configurable Sidebar block for displaying docs sections and articles with nesting, sorting, and live preview.
    • Added a DocsGrid block with layout options, pagination, and rich styling controls.
  • Style
    • New RTL-friendly styles for DocsGrid and frontend UI.
    • Enhanced print styles for clearer, consistent output.
    • Updated search block stylesheet formatting without visual changes.
  • Chores
    • Updated build dependencies and scripts, including WordPress scripts.
    • Refreshed asset manifests and versions for improved compatibility and caching.

@coderabbitai
Copy link

coderabbitai bot commented Oct 8, 2025

Walkthrough

Adds a new Sidebar Gutenberg block (editor, view script, PHP render, styles) and introduces a DocsGrid block build output. Updates build assets (dependencies and versions), adds comprehensive CSS (LTR/RTL, print, frontend), introduces shared editor controls, registers data store, and updates tooling/config (webpack, scripts), and plugin registration.

Changes

Cohort / File(s) Summary
DocsGrid block (build outputs)
assets/build/blocks/DocsGrid/index.js, assets/build/blocks/DocsGrid/style-index.css, assets/build/blocks/DocsGrid/style-index-rtl.css
New DocsGrid block build artifacts: registration JS and styles (LTR/RTL).
Sidebar block (build)
assets/build/blocks/Sidebar/block.json, assets/build/blocks/Sidebar/index.js, assets/build/blocks/Sidebar/index.asset.php, assets/build/blocks/Sidebar/render.php
New Sidebar block: manifest, registration, asset deps, and PHP renderer.
Sidebar block (source)
src/blocks/Sidebar/block.json, src/blocks/Sidebar/index.js, src/blocks/Sidebar/edit.js, src/blocks/Sidebar/save.js, src/blocks/Sidebar/render.php, src/blocks/Sidebar/style.css, src/blocks/Sidebar/view.js, src/blocks/Sidebar/components/*, src/blocks/Sidebar/components/index.js
Full source for Sidebar block: edit/save, renderer, styles, view script, and UI components (SectionItem, ArticleItem, CountBadge, SidebarContainer).
Shared editor controls
src/components/Blocks/AlignmentControls.js, .../BackgroundImageControls.js, .../BorderAndShadowControls.js, .../ColorsControls.js, .../DimensionsControls.js, .../DisplayControls.js, .../TypographyControls.js
New reusable React controls for alignment, background image, border/shadow, colors, dimensions, display, and typography.
Data store
assets/build/store.js, assets/build/store.asset.php
Adds/registers docs data store with actions/selectors/resolvers; bumps store asset version.
Frontend and print styles/scripts
assets/build/frontend.css, assets/build/frontend-rtl.css, assets/build/frontend.js, assets/build/frontend.asset.php, assets/build/print.css, assets/build/print-rtl.css, assets/build/print.js, assets/build/print.asset.php, assets/build/style-block.css, assets/build/style-block-rtl.css
Adds/updates CSS/JS for frontend, RTL, and print; version bumps and webpack bootstrap helpers; expanded search styles.
Block assets metadata
assets/build/block.asset.php, assets/build/index.asset.php
Dependency updates (add react-jsx-runtime, wp-data) and version bumps for block/index assets.
Plugin wiring
wedocs.php, src/blocks/index.js
Registers the new Sidebar block and includes its renderer; imports Sidebar into blocks index.
Build config and tooling
webpack.config.js, package.json
Switches to calling defaultConfig.entry(); bumps @wordpress/scripts to ^30.25.0.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • Add docs grid #203 — Touches the DocsGrid block implementation and assets, overlapping with the newly added DocsGrid build outputs here.

Suggested labels

Needs Review

Poem

In burrows of code I hop with glee,
New Sidebar sprouts beside the docs tree.
Grids bloom in rows, RTL in tow,
Styles like clover softly glow.
With stores and scripts, I twitch my ear—
Commit by commit, the path is clear. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning The pull request does not address the linked issue #162, which requires bumping the async dependency to version 3.2.4; no changes to async or related lockfiles are present. Include updates to bump async from 2.6.3 to 3.2.4 in package.json and lockfiles, and ensure any breaking changes from v3.x are accounted for and tested.
Out of Scope Changes Check ⚠️ Warning The pull request introduces extensive block implementations, styling, and data stores unrelated to the async dependency bump in the linked issue, indicating numerous out-of-scope changes beyond the objective of updating the async package. Limit changes to updating the async dependency and remove or separate feature work into dedicated pull requests for the Sidebar block and related components.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly indicates that the primary change is the addition of a Sidebar Gutenberg block, matching the main purpose of the pull request.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 29

🧹 Nitpick comments (26)
src/blocks/Sidebar/components/CountBadge.js (1)

14-16: Consider handling negative count values.

While checking for count === 0 is appropriate, consider also handling negative values (e.g., count <= 0) to guard against unexpected data.

Apply this diff:

-    if (count === 0) {
+    if (count <= 0) {
         return null;
     }
src/components/Blocks/AlignmentControls.js (1)

205-215: Consider using undefined instead of null for consistency.

The Reset All button sets alignment values to null, whereas ColorsControls.js (line 338-341) uses undefined for the same purpose. For consistency across control components, consider using undefined as it's the conventional way to indicate "no value set" for optional attributes.

Apply this diff for consistency:

   onClick={() => {
     setAttributes({
       alignmentControls: {
         ...alignmentControls,
         [device]: {
           ...currentAlignment,
-          textAlign: null,
-          alignItems: null,
-          justifyContent: null,
-          direction: null,
+          textAlign: undefined,
+          alignItems: undefined,
+          justifyContent: undefined,
+          direction: undefined,
         },
       },
     });
   }}
src/components/Blocks/DimensionsControls.js (1)

239-256: Consider using undefined instead of null for consistency.

The Reset All button uses null to clear dimension values, while ColorsControls.js uses undefined. For consistency across control components, consider using undefined.

src/components/Blocks/DisplayControls.js (2)

50-57: Add defensive check for displayControls.

The function assumes attributes.displayControls exists and is an object. If it's undefined or null, this will throw an error.

Apply this diff to add a safe default:

 	const toggleDeviceVisibility = (deviceKey) => {
 		setAttributes({
 			displayControls: {
-				...attributes.displayControls,
+				...(attributes.displayControls || {}),
 				[deviceKey]: !attributes.displayControls[deviceKey],
 			},
 		});
 	};

60-61: Add defensive check for device key access.

Line 61 accesses attributes.displayControls[key] without checking if displayControls exists.

Apply this diff:

 	const renderDeviceCard = ({ key, icon, label }) => {
-		const isHidden = attributes.displayControls[key];
+		const isHidden = attributes.displayControls?.[key] || false;
src/components/Blocks/BackgroundImageControls.js (1)

33-60: Consider extracting focal point configuration.

The logic for setting focal points based on size is somewhat complex and could benefit from extraction into a configuration object for better maintainability.

Consider refactoring like this:

const FOCAL_POINT_PRESETS = {
	cover: { focalPoint: null, repeat: null },
	contain: { focalPoint: { x: 0.5, y: 0.5 }, repeat: false },
	tile: { focalPoint: { x: 0.5, y: 0 }, repeat: true }
};

const handleBackgroundImageSizeChange = (value) => {
	const preset = FOCAL_POINT_PRESETS[value] || {};
	
	setAttributes({
		backgroundImageControls: {
			...backgroundImageControls,
			[device]: {
				...currentBackgroundImage,
				bgSize: value,
				bgFocalPoint: preset.focalPoint,
				bgRepeat: preset.repeat,
			},
		},
	});
};
src/components/Blocks/TypographyControls.js (2)

34-37: Add defensive checks for font families structure.

The code assumes fontFamilies[0] exists and has theme and custom properties. This could fail if the structure is different.

Apply this diff:

 	// Combine both theme and custom fonts
-	const themeFonts = fontFamilies[0]?.theme || [];
-	const customFonts = fontFamilies[0]?.custom || [];
+	const themeFonts = fontFamilies?.[0]?.theme || [];
+	const customFonts = fontFamilies?.[0]?.custom || [];
 	const validFontFamilies = [...themeFonts, ...customFonts];

77-77: Remove or clarify empty onChange handler.

The disabled SelectControl has an empty onChange={() => {}} handler. Since the control is disabled, this handler will never be called. Consider removing it or adding a comment explaining why it's present.

 						value={'default'}
-						onChange={() => {}}
 						disabled
src/blocks/Sidebar/index.js (1)

7-17: Consider adding block icon for better UX.

The block registration doesn't include an icon, which means it will use a default placeholder icon in the block inserter. Consider adding an icon to improve the user experience.

Example:

+import { folder } from '@wordpress/icons';
+
 registerBlockType(metadata.name, {
 	/**
 	 * @see ./edit.js
 	 */
 	edit: Edit,
+	icon: folder,
 
 	/**
 	 * @see ./save.js
 	 */
 	save: Save,
 });
src/blocks/Sidebar/view.js (3)

10-44: Refactor to use class toggles instead of inline styles.

The current implementation directly manipulates style.display which prevents CSS transitions and makes styling harder to maintain. Consider toggling a CSS class instead.

                 if (isExpanded) {
                     // Collapse
-                    children.style.display = 'none';
+                    children.classList.add('is-collapsed');
                     this.setAttribute('aria-expanded', 'false');
                     if (toggleButton) {
                         // Change to down arrow
-                        toggleButton.innerHTML = `
-                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="width: 16px; height: 16px;">
-                                <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
-                            </svg>
-                        `;
+                        toggleButton.classList.add('is-collapsed');
                     }
                 } else {
                     // Expand
-                    children.style.display = 'block';
+                    children.classList.remove('is-collapsed');
                     this.setAttribute('aria-expanded', 'true');
                     if (toggleButton) {
                         // Change to up arrow
-                        toggleButton.innerHTML = `
-                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="width: 16px; height: 16px;">
-                                <path stroke-linecap="round" stroke-linejoin="round" d="m4.5 15.75 7.5-7.5 7.5 7.5" />
-                            </svg>
-                        `;
+                        toggleButton.classList.remove('is-collapsed');
                     }
                 }

Then add CSS:

.wedocs-section-children.is-collapsed {
    display: none;
}

.wedocs-expand-toggle.is-collapsed svg:first-child {
    display: none;
}

.wedocs-expand-toggle:not(.is-collapsed) svg:last-child {
    display: none;
}

56-116: Consider event delegation for better performance.

The current implementation attaches individual event listeners to every section, title, and article link. For large documentation trees, this could create hundreds of listeners. Event delegation would be more efficient.

-    // Handle hover effects for sections
-    const sections = document.querySelectorAll('.wedocs-section');
-    
-    sections.forEach(section => {
-        section.addEventListener('mouseenter', function() {
-            const hoverBg = getComputedStyle(this).getPropertyValue('--section-bg-hover');
-            if (hoverBg && hoverBg.trim() !== '') {
-                this.style.backgroundColor = hoverBg;
-            }
-        });
-        
-        section.addEventListener('mouseleave', function() {
-            const normalBg = getComputedStyle(this).getPropertyValue('--section-bg');
-            this.style.backgroundColor = normalBg || '';
-        });
-    });
+    // Handle hover effects using event delegation
+    document.addEventListener('mouseenter', function(e) {
+        const section = e.target.closest('.wedocs-section');
+        if (section) {
+            const hoverBg = getComputedStyle(section).getPropertyValue('--section-bg-hover');
+            if (hoverBg && hoverBg.trim() !== '') {
+                section.style.backgroundColor = hoverBg;
+            }
+        }
+        
+        const articleLink = e.target.closest('.wedocs-article a');
+        if (articleLink) {
+            const article = articleLink.closest('.wedocs-article');
+            const hoverColor = getComputedStyle(article).getPropertyValue('--doc-list-text-color-hover');
+            if (hoverColor) {
+                articleLink.style.color = hoverColor;
+            }
+        }
+    }, true);
+    
+    document.addEventListener('mouseleave', function(e) {
+        const section = e.target.closest('.wedocs-section');
+        if (section) {
+            const normalBg = getComputedStyle(section).getPropertyValue('--section-bg');
+            section.style.backgroundColor = normalBg || '';
+        }
+        
+        const articleLink = e.target.closest('.wedocs-article a');
+        if (articleLink) {
+            const article = articleLink.closest('.wedocs-article');
+            const textColor = getComputedStyle(article).getPropertyValue('--doc-list-text-color');
+            if (textColor) {
+                articleLink.style.color = textColor;
+            }
+        }
+    }, true);

48-53: Extract toggle logic to avoid indirect click triggering.

Calling this.click() in the keyboard handler is indirect and can cause issues if the click handler changes. Extract the toggle logic into a function.

+    function toggleSection(header) {
+        const section = header.closest('.wedocs-section');
+        const children = section.querySelector('.wedocs-section-children');
+        const toggleButton = header.querySelector('.wedocs-expand-toggle');
+        const isExpanded = header.getAttribute('aria-expanded') === 'true';
+        
+        if (!children) return;
+        
+        if (isExpanded) {
+            children.classList.add('is-collapsed');
+            header.setAttribute('aria-expanded', 'false');
+            if (toggleButton) {
+                toggleButton.classList.add('is-collapsed');
+            }
+        } else {
+            children.classList.remove('is-collapsed');
+            header.setAttribute('aria-expanded', 'true');
+            if (toggleButton) {
+                toggleButton.classList.remove('is-collapsed');
+            }
+        }
+    }
+    
     sectionHeaders.forEach(header => {
         header.addEventListener('click', function(e) {
             e.preventDefault();
-            
-            const section = this.closest('.wedocs-section');
-            const children = section.querySelector('.wedocs-section-children');
-            // ... rest of toggle logic
+            toggleSection(this);
         });
         
         header.addEventListener('keydown', function(e) {
             if (e.key === 'Enter' || e.key === ' ') {
                 e.preventDefault();
-                this.click();
+                toggleSection(this);
             }
         });
     });
assets/build/blocks/DocsGrid/style-index.css (1)

13-46: Reduce duplication in pagination styles and relocate RTL-specific rule.

  • .wedocs-docs-pagination is defined twice; consider consolidating the shared rules and scoping differences (buttons vs .page-numbers) to avoid drift.
  • The [dir=rtl] arrow rule in the LTR stylesheet is redundant given the separate RTL file; keep RTL-only rules in the RTL stylesheet for clarity.

Also applies to: 217-299, 213-215

src/components/Blocks/BorderAndShadowControls.js (1)

70-81: Unify i18n text domain with the plugin.

Use wedocs as the text domain for consistent translation loading.

Apply this diff (repeat for all labels):

- label={__('Border', 'block-responsive')}
+ label={__('Border', 'wedocs')}
- name: __('Theme', 'block-responsive'),
+ name: __('Theme', 'wedocs'),
- label={__('Border Radius', 'block-responsive')}
+ label={__('Border Radius', 'wedocs')}
- <Text>{__('Drop Shadow', 'block-responsive')}</Text>
+ <Text>{__('Drop Shadow', 'wedocs')}</Text>
- label={__('Outset', 'block-responsive')}
+ label={__('Outset', 'wedocs')}
- label={__('Inset', 'block-responsive')}
+ label={__('Inset', 'wedocs')}
- label={__('X Position', 'block-responsive')}
+ label={__('X Position', 'wedocs')}
- label={__('Y Position', 'block-responsive')}
+ label={__('Y Position', 'wedocs')}
- label={__('Blur', 'block-responsive')}
+ label={__('Blur', 'wedocs')}
- label={__('Spread', 'block-responsive')}
+ label={__('Spread', 'wedocs')}
- text={__('Reset All', 'block-responsive')}
+ text={__('Reset All', 'wedocs')}

Also applies to: 95-99, 131-135, 159-166, 177-181, 185-191, 193-201, 203-209, 219-219

src/blocks/Sidebar/components/ArticleItem.js (1)

10-24: Reduce duplication; prefer CSS hovers over JS events

  • decodeHtmlEntities and getColorValue duplicate SectionItem.js helpers; extract to a small shared util.
  • Replace inline onMouseEnter/onMouseLeave color changes with CSS :hover using CSS variables for consistency.

Also applies to: 36-45, 58-66

src/blocks/Sidebar/edit.js (1)

121-124: Prefer importing apiFetch over using wp.apiFetch

Importing ensures bundling and typings: import apiFetch from '@wordpress/api-fetch' then use apiFetch({ path }).

src/blocks/Sidebar/components/SectionItem.js (1)

1-4: Remove unused import

CountBadge is imported but not used.

-import CountBadge from './CountBadge';
assets/build/blocks/Sidebar/render.php (1)

19-29: Remove or use unused variables

$section_title_tag, $article_title_tag, $count_badge_styles, $doc_list_styles, and $content/$parent are unused. Clean up or wire them into output (see parity comment).

src/blocks/Sidebar/render.php (5)

324-324: Remove unused $count_badge_styles param (and argument) or implement badge rendering

Parameter is unused; keep code lean or render the badge.

Apply:

-    function wedocs_render_section_with_articles( $section, $articles_by_section, $enable_nested_articles, $section_title_tag, $article_title_tag, $section_styles, $title_styles, $doc_list_styles, $tree_styles, $count_badge_styles, $level = 0 ) {
+    function wedocs_render_section_with_articles( $section, $articles_by_section, $enable_nested_articles, $section_title_tag, $article_title_tag, $section_styles, $title_styles, $doc_list_styles, $tree_styles, $level = 0 ) {

And adjust call:

-            $children .= wedocs_render_section_with_articles(
-                $section, $articles_by_section, $enable_nested_articles, $section_title_tag, $article_title_tag,
-                $section_styles, $title_styles, $doc_list_styles, $tree_styles, $count_badge_styles
-            );
+            $children .= wedocs_render_section_with_articles(
+                $section, $articles_by_section, $enable_nested_articles, $section_title_tag, $article_title_tag,
+                $section_styles, $title_styles, $doc_list_styles, $tree_styles
+            );

Also applies to: 204-207


340-413: Localize ARIA labels for accessibility

Hardcoded English strings for aria-labels should be translated.

Example:

-            ) . '; background: none; border: none; cursor: pointer; padding: 2px; border-radius: 2px; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px;" aria-expanded="true" aria-label="Toggle ' . esc_attr(
-                                 $section->post_title
-                             ) . ' section">
+            ) . '; background: none; border: none; cursor: pointer; padding: 2px; border-radius: 2px; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px;" aria-expanded="true" aria-label="' . esc_attr( sprintf( __( 'Toggle %s section', 'wedocs' ), $section->post_title ) ) . '">

Apply similar change where aria-label is set on headers/buttons.

Also applies to: 474-493, 575-590


142-153: Normalize boolean enableNestedArticles from attributes

The empty-string coerce is brittle; normalize robustly.

Consider:

-    if ($enable_nested_articles === '') {
-        $enable_nested_articles = true;
-    }
+    $enable_nested_articles = filter_var( $enable_nested_articles, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
+    if ( null === $enable_nested_articles ) {
+        $enable_nested_articles = true;
+    }

294-319: Sorting: normalize $order input and use spaceship operator

Guard against 'ASC' casing and improve readability.

Example:

-    function wedocs_sort_docs( $docs, $orderby, $order ) {
+    function wedocs_sort_docs( $docs, $orderby, $order ) {
+        $order = strtolower( (string) $order ) === 'desc' ? 'desc' : 'asc';
         if ( empty( $docs ) ) {
             return $docs;
         }
         usort(
             $docs, function( $a, $b ) use ( $orderby, $order ) {
             switch ( $orderby ) {
                 case 'name':
-                    $result = strcmp( $a->post_title, $b->post_title );
+                    $result = strcmp( $a->post_title, $b->post_title );
                     break;
                 case 'slug':
-                    $result = strcmp( $a->post_name, $b->post_name );
+                    $result = strcmp( $a->post_name, $b->post_name );
                     break;
                 case 'id':
-                    $result = $a->ID - $b->ID;
+                    $result = $a->ID <=> $b->ID;
                     break;
                 default:
-                    $result = $a->menu_order - $b->menu_order;
+                    $result = $a->menu_order <=> $b->menu_order;
             }
 
-            return $order === 'desc' ? - $result : $result;
+            return $order === 'desc' ? -$result : $result;
         }
         );
 
         return $docs;
     }

570-589: Avoid emoji as icon; prefer SVG for consistency and a11y

The 📄 emoji may render inconsistently. Consider an inline SVG like other icons.

assets/build/blocks/Sidebar/index.js (3)

1207-1223: Ignore lints on bundled artifacts; errors are from webpack runtime

Biome flags (use-before-declare, redeclare) are in webpack bootstrap code. Exclude built assets (assets/build/) from linting and code review. Source changes should be made under src/.


670-672: Import and declare dependency for apiFetch in source

Using wp.apiFetch assumes the global is enqueued. Prefer importing from @wordpress/api-fetch in src and adding it to the block’s asset dependencies to avoid runtime undefined globals.


158-174: Remove dead code (CountBadge) or wire it up

CountBadge is built and exported but not used anywhere. Either render it (e.g., for children counts) or drop it to reduce bundle size.

Also applies to: 206-207, 510-514

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0434ddd and daa0cdf.

⛔ Files ignored due to path filters (14)
  • assets/build/block.js.map is excluded by !**/*.map
  • assets/build/blocks/DocsGrid/index.js.map is excluded by !**/*.map
  • assets/build/blocks/DocsGrid/style-index.css.map is excluded by !**/*.map
  • assets/build/blocks/Sidebar/index.js.map is excluded by !**/*.map
  • assets/build/blocks/Sidebar/style-index.css.map is excluded by !**/*.map
  • assets/build/frontend.css.map is excluded by !**/*.map
  • assets/build/frontend.js.map is excluded by !**/*.map
  • assets/build/index.css.map is excluded by !**/*.map
  • assets/build/index.js.map is excluded by !**/*.map
  • assets/build/print.css.map is excluded by !**/*.map
  • assets/build/print.js.map is excluded by !**/*.map
  • assets/build/store.js.map is excluded by !**/*.map
  • assets/build/style-block.css.map is excluded by !**/*.map
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (45)
  • assets/build/block.asset.php (1 hunks)
  • assets/build/blocks/DocsGrid/index.asset.php (1 hunks)
  • assets/build/blocks/DocsGrid/index.js (1 hunks)
  • assets/build/blocks/DocsGrid/style-index-rtl.css (1 hunks)
  • assets/build/blocks/DocsGrid/style-index.css (1 hunks)
  • assets/build/blocks/Sidebar/block.json (1 hunks)
  • assets/build/blocks/Sidebar/index.asset.php (1 hunks)
  • assets/build/blocks/Sidebar/index.js (1 hunks)
  • assets/build/blocks/Sidebar/render.php (1 hunks)
  • assets/build/frontend-rtl.css (1 hunks)
  • assets/build/frontend.asset.php (1 hunks)
  • assets/build/frontend.css (2 hunks)
  • assets/build/frontend.js (1 hunks)
  • assets/build/index.asset.php (1 hunks)
  • assets/build/print-rtl.css (1 hunks)
  • assets/build/print.asset.php (1 hunks)
  • assets/build/print.css (2 hunks)
  • assets/build/print.js (1 hunks)
  • assets/build/store.asset.php (1 hunks)
  • assets/build/store.js (1 hunks)
  • assets/build/style-block-rtl.css (1 hunks)
  • assets/build/style-block.css (1 hunks)
  • package.json (1 hunks)
  • src/blocks/Sidebar/block.json (1 hunks)
  • src/blocks/Sidebar/components/ArticleItem.js (1 hunks)
  • src/blocks/Sidebar/components/CountBadge.js (1 hunks)
  • src/blocks/Sidebar/components/SectionItem.js (1 hunks)
  • src/blocks/Sidebar/components/SidebarContainer.js (1 hunks)
  • src/blocks/Sidebar/components/index.js (1 hunks)
  • src/blocks/Sidebar/edit.js (1 hunks)
  • src/blocks/Sidebar/index.js (1 hunks)
  • src/blocks/Sidebar/render.php (1 hunks)
  • src/blocks/Sidebar/save.js (1 hunks)
  • src/blocks/Sidebar/style.css (1 hunks)
  • src/blocks/Sidebar/view.js (1 hunks)
  • src/blocks/index.js (1 hunks)
  • src/components/Blocks/AlignmentControls.js (1 hunks)
  • src/components/Blocks/BackgroundImageControls.js (1 hunks)
  • src/components/Blocks/BorderAndShadowControls.js (1 hunks)
  • src/components/Blocks/ColorsControls.js (1 hunks)
  • src/components/Blocks/DimensionsControls.js (1 hunks)
  • src/components/Blocks/DisplayControls.js (1 hunks)
  • src/components/Blocks/TypographyControls.js (1 hunks)
  • webpack.config.js (1 hunks)
  • wedocs.php (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (17)
src/blocks/Sidebar/components/CountBadge.js (3)
src/blocks/Sidebar/edit.js (1)
  • attributes (9-23)
src/blocks/Sidebar/components/ArticleItem.js (2)
  • attributes (3-8)
  • getColorValue (22-24)
src/blocks/Sidebar/components/SectionItem.js (2)
  • attributes (8-13)
  • getColorValue (24-26)
src/blocks/Sidebar/components/ArticleItem.js (4)
src/blocks/Sidebar/edit.js (1)
  • attributes (9-23)
src/blocks/Sidebar/components/SectionItem.js (7)
  • attributes (8-13)
  • decodeHtmlEntities (16-21)
  • indentation (29-29)
  • getColorValue (24-26)
  • iconStyle (59-63)
  • TitleTag (69-69)
  • children (70-70)
src/blocks/Sidebar/components/CountBadge.js (2)
  • attributes (2-2)
  • getColorValue (5-7)
src/blocks/Sidebar/view.js (1)
  • hoverColor (104-104)
src/blocks/Sidebar/components/SidebarContainer.js (3)
src/blocks/Sidebar/edit.js (2)
  • sections (82-82)
  • attributes (9-23)
src/blocks/Sidebar/components/SectionItem.js (2)
  • SectionItem (5-236)
  • attributes (8-13)
src/blocks/Sidebar/components/ArticleItem.js (1)
  • attributes (3-8)
src/blocks/Sidebar/components/SectionItem.js (2)
src/blocks/Sidebar/edit.js (1)
  • attributes (9-23)
src/blocks/Sidebar/components/ArticleItem.js (8)
  • attributes (3-8)
  • decodeHtmlEntities (11-16)
  • getColorValue (22-24)
  • indentation (19-19)
  • iconStyle (36-40)
  • TitleTag (47-47)
  • children (48-48)
  • ArticleItem (1-144)
src/components/Blocks/DimensionsControls.js (5)
src/components/Blocks/AlignmentControls.js (1)
  • attributes (27-27)
src/components/Blocks/BackgroundImageControls.js (1)
  • attributes (15-15)
src/components/Blocks/BorderAndShadowControls.js (1)
  • attributes (22-22)
src/components/Blocks/ColorsControls.js (1)
  • attributes (18-18)
src/components/Blocks/TypographyControls.js (1)
  • attributes (29-29)
src/blocks/Sidebar/edit.js (3)
src/blocks/Sidebar/components/ArticleItem.js (1)
  • attributes (3-8)
src/blocks/Sidebar/components/SectionItem.js (1)
  • attributes (8-13)
src/blocks/Sidebar/components/SidebarContainer.js (1)
  • SidebarContainer (4-26)
src/blocks/Sidebar/index.js (2)
src/blocks/Sidebar/edit.js (1)
  • Edit (8-467)
src/blocks/Sidebar/save.js (1)
  • Save (1-5)
src/components/Blocks/BorderAndShadowControls.js (5)
src/components/Blocks/AlignmentControls.js (1)
  • attributes (27-27)
src/components/Blocks/BackgroundImageControls.js (1)
  • attributes (15-15)
src/components/Blocks/ColorsControls.js (1)
  • attributes (18-18)
src/components/Blocks/DimensionsControls.js (1)
  • attributes (12-12)
src/components/Blocks/TypographyControls.js (1)
  • attributes (29-29)
assets/build/store.js (10)
src/components/Documentations/index.js (3)
  • docs (19-22)
  • loading (29-32)
  • parentDocs (24-27)
src/components/DocListing/index.js (3)
  • docs (27-29)
  • loading (37-40)
  • sections (103-103)
src/components/SelectBox.js (1)
  • pages (16-16)
src/blocks/DocsGrid/edit.js (2)
  • loading (18-18)
  • wp (16-16)
src/components/DocListing/ListingHeader.js (1)
  • loading (13-16)
src/blocks/Sidebar/edit.js (1)
  • sections (82-82)
src/components/Documentations/ParentDocs.js (2)
  • sections (36-40)
  • articles (42-46)
src/components/AddArticleModal.js (1)
  • articles (35-39)
src/components/DocListing/QuickEditModal.js (1)
  • articles (34-38)
src/components/DocListing/DocSections.js (2)
  • articles (70-70)
  • settings (86-89)
src/components/Blocks/AlignmentControls.js (5)
src/components/Blocks/BackgroundImageControls.js (1)
  • attributes (15-15)
src/components/Blocks/BorderAndShadowControls.js (1)
  • attributes (22-22)
src/components/Blocks/ColorsControls.js (1)
  • attributes (18-18)
src/components/Blocks/DimensionsControls.js (1)
  • attributes (12-12)
src/components/Blocks/TypographyControls.js (1)
  • attributes (29-29)
assets/build/blocks/DocsGrid/index.js (1)
src/blocks/Sidebar/edit.js (3)
  • attributes (9-23)
  • processDocsData (142-238)
  • sections (82-82)
src/components/Blocks/BackgroundImageControls.js (1)
src/blocks/CustomControls/UnitControl.js (1)
  • UnitControl (4-27)
src/components/Blocks/TypographyControls.js (9)
src/blocks/Sidebar/edit.js (1)
  • attributes (9-23)
src/blocks/Sidebar/components/ArticleItem.js (1)
  • attributes (3-8)
src/blocks/Sidebar/components/SectionItem.js (1)
  • attributes (8-13)
src/blocks/Sidebar/components/CountBadge.js (1)
  • attributes (2-2)
src/components/Blocks/AlignmentControls.js (1)
  • attributes (27-27)
src/components/Blocks/BackgroundImageControls.js (1)
  • attributes (15-15)
src/components/Blocks/BorderAndShadowControls.js (1)
  • attributes (22-22)
src/components/Blocks/ColorsControls.js (1)
  • attributes (18-18)
src/components/Blocks/DimensionsControls.js (1)
  • attributes (12-12)
src/components/Blocks/ColorsControls.js (1)
src/blocks/Sidebar/edit.js (1)
  • useSelect (30-36)
src/blocks/Sidebar/render.php (1)
assets/build/blocks/Sidebar/render.php (3)
  • render_wedocs_sidebar (11-153)
  • wedocs_sort_docs (158-192)
  • wedocs_render_section_with_articles (197-226)
assets/build/blocks/Sidebar/render.php (2)
src/blocks/Sidebar/render.php (3)
  • render_wedocs_sidebar (142-289)
  • wedocs_sort_docs (294-319)
  • wedocs_render_section_with_articles (324-521)
includes/Walker.php (2)
  • Walker (10-22)
  • start_el (15-21)
src/components/Blocks/DisplayControls.js (6)
src/components/Blocks/AlignmentControls.js (1)
  • attributes (27-27)
src/components/Blocks/BackgroundImageControls.js (1)
  • attributes (15-15)
src/components/Blocks/BorderAndShadowControls.js (1)
  • attributes (22-22)
src/components/Blocks/ColorsControls.js (1)
  • attributes (18-18)
src/components/Blocks/DimensionsControls.js (1)
  • attributes (12-12)
src/components/Blocks/TypographyControls.js (1)
  • attributes (29-29)
🪛 Biome (2.1.2)
src/blocks/Sidebar/style.css

[error] 74-74: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

padding is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

assets/build/print-rtl.css

[error] 40-40: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

white-space is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 65-65: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

font-size is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

assets/build/store.js

[error] 321-324: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 325-325: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 375-375: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)


[error] 376-376: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)

assets/build/blocks/DocsGrid/index.js

[error] 1040-1040: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1047-1047: Shouldn't redeclare 'i'. Consider to delete it or rename it.

'i' is defined here:

(lint/suspicious/noRedeclare)


[error] 1048-1048: Shouldn't redeclare 'chunkIds'. Consider to delete it or rename it.

'chunkIds' is defined here:

(lint/suspicious/noRedeclare)


[error] 1048-1048: Shouldn't redeclare 'fn'. Consider to delete it or rename it.

'fn' is defined here:

(lint/suspicious/noRedeclare)


[error] 1048-1048: Shouldn't redeclare 'priority'. Consider to delete it or rename it.

'priority' is defined here:

(lint/suspicious/noRedeclare)

assets/build/style-block.css

[error] 54-54: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

width is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

assets/build/frontend-rtl.css

[error] 326-326: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

display is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 493-493: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

white-space is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 518-518: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

font-size is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

assets/build/style-block-rtl.css

[error] 54-54: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

width is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

assets/build/blocks/Sidebar/index.js

[error] 1210-1210: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1217-1217: Shouldn't redeclare 'i'. Consider to delete it or rename it.

'i' is defined here:

(lint/suspicious/noRedeclare)


[error] 1218-1218: Shouldn't redeclare 'chunkIds'. Consider to delete it or rename it.

'chunkIds' is defined here:

(lint/suspicious/noRedeclare)


[error] 1218-1218: Shouldn't redeclare 'fn'. Consider to delete it or rename it.

'fn' is defined here:

(lint/suspicious/noRedeclare)


[error] 1218-1218: Shouldn't redeclare 'priority'. Consider to delete it or rename it.

'priority' is defined here:

(lint/suspicious/noRedeclare)

🪛 PHPMD (2.15.0)
src/blocks/Sidebar/render.php

142-142: Avoid unused parameters such as '$content'. (undefined)

(UnusedFormalParameter)


157-157: Avoid unused local variables such as '$container_styles'. (undefined)

(UnusedLocalVariable)


324-324: Avoid unused parameters such as '$count_badge_styles'. (undefined)

(UnusedFormalParameter)

assets/build/blocks/Sidebar/render.php

11-11: Avoid unused parameters such as '$content'. (undefined)

(UnusedFormalParameter)


19-19: Avoid unused local variables such as '$section_title_tag'. (undefined)

(UnusedLocalVariable)


20-20: Avoid unused local variables such as '$article_title_tag'. (undefined)

(UnusedLocalVariable)


26-26: Avoid unused local variables such as '$count_badge_styles'. (undefined)

(UnusedLocalVariable)


27-27: Avoid unused local variables such as '$doc_list_styles'. (undefined)

(UnusedLocalVariable)


32-32: Avoid unused local variables such as '$parent'. (undefined)

(UnusedLocalVariable)

🔇 Additional comments (29)
assets/build/print.css (1)

1-186: LGTM!

Build artifact with updated pipeline metadata and source map reference. No functional CSS changes detected.

assets/build/print.asset.php (1)

1-1: LGTM!

Standard asset manifest version bump for cache invalidation.

assets/build/frontend.js (1)

1-28: LGTM!

Standard webpack bootstrap runtime for ES module interop. No concerns.

assets/build/print.js (1)

1-28: LGTM!

Standard webpack bootstrap runtime, consistent with other build outputs.

src/blocks/Sidebar/components/CountBadge.js (1)

18-26: LGTM!

The badge rendering logic is clean with proper accessibility support via aria-label.

assets/build/style-block-rtl.css (2)

53-54: Vendor prefix pattern is intentional.

The duplicate width properties flagged by static analysis are intentional vendor prefixing. The -moz-fit-content prefix ensures compatibility with older Firefox versions, while fit-content provides the standard fallback. This is a common progressive enhancement pattern in CSS.


1-137: LGTM!

RTL styling for the Wedocs search block is comprehensive and properly structured. The CSS variables, layout rules, and accessibility considerations are well-implemented.

webpack.config.js (1)

9-9: Verify @wordpress/scripts defaultConfig.entry API. Unable to locate the upstream webpack config locally; please confirm that in @wordpress/scripts v^30.25.0+, defaultConfig.entry is indeed a function and that using ...defaultConfig.entry() aligns with the official API.

package.json (1)

33-33: Select format for breaking changes overview. Would you prefer a short summary of the breaking changes across @wordpress/scripts v25→30 or a detailed changelog with links for each version?

assets/build/block.asset.php (1)

1-1: LGTM!

The dependency update from react to react-jsx-runtime aligns with the modern JSX transform introduced in React 17+. The addition of wp-data suggests proper integration with WordPress data stores.

src/components/Blocks/ColorsControls.js (1)

17-351: LGTM!

The color controls component follows WordPress block editor patterns correctly:

  • Proper use of useSelect to fetch theme colors and gradients
  • Consistent per-device attribute management with proper spread operators
  • Appropriate use of experimental components with ESLint disable comment
  • Reset functionality correctly clears values while preserving other device settings
src/components/Blocks/AlignmentControls.js (1)

26-222: LGTM!

The alignment controls component follows the established patterns:

  • Consistent per-device attribute management
  • Proper use of WordPress icon components
  • Clear separation of concerns with individual handlers
src/blocks/Sidebar/block.json (1)

1-118: LGTM!

The block manifest is well-structured:

  • Uses latest schema and API version 3
  • Comprehensive attribute definitions with appropriate types and defaults
  • Proper asset file references for editor and frontend
  • Support configuration appropriately enables spacing and background customization
src/components/Blocks/DimensionsControls.js (1)

11-261: LGTM!

The dimension controls component is well-implemented:

  • Proper use of WordPress experimental components
  • Consistent per-device attribute management
  • Comprehensive coverage of dimension properties (padding, margin, width, height)
  • Clear UI organization with appropriate labels
assets/build/store.asset.php (1)

1-1: LGTM!

The asset version bump aligns with the build changes introduced in this PR.

src/blocks/index.js (1)

3-3: LGTM!

The Sidebar block import follows the same pattern as the existing blocks and properly integrates into the block registration system.

assets/build/frontend.asset.php (1)

1-1: LGTM!

The asset version bump reflects the build changes in this PR.

assets/build/frontend.css (1)

1-3: LGTM!

The addition of build metadata comments and sourcemap reference is standard for build artifacts. No functional changes to CSS.

Also applies to: 1223-1224

src/blocks/Sidebar/index.js (1)

5-5: Retain style import. This import is required for the bundler to generate the style-index.css file declared in block.json.

assets/build/blocks/Sidebar/index.asset.php (1)

1-1: LGTM! Standard WordPress block asset manifest.

The dependencies and version hash are correctly formatted for a server-rendered Gutenberg block.

src/blocks/Sidebar/save.js (1)

1-7: LGTM! Correct pattern for server-rendered blocks.

Returning null from the save function is the standard approach for dynamic blocks that render server-side via PHP. The comment clearly documents this behavior.

wedocs.php (2)

50-50: LGTM! Sidebar render file inclusion.

The require_once statement properly includes the Sidebar block's render callback, following the same pattern as the DocsGrid block.


187-193: LGTM! Sidebar block registration.

The block registration follows WordPress best practices and maintains consistency with the existing DocsGrid block registration pattern. The render callback is properly configured.

assets/build/index.asset.php (1)

1-1: LGTM! Updated for modern JSX transform.

The addition of react-jsx-runtime aligns with the new JSX transform introduced in React 17+, which is now the standard for WordPress block development.

src/blocks/Sidebar/components/index.js (1)

1-4: LGTM! Clean barrel export pattern.

The barrel export provides a clean public API for the Sidebar components, allowing consumers to import from a single entry point.

src/blocks/Sidebar/components/SidebarContainer.js (1)

20-20: Tailwind CSS is configured
Confirmed tailwind.config.js, tailwindcss dependency, and wide use of utility classes—no changes needed.

assets/build/store.js (1)

1-20: No async dependency detected
package.json and lockfiles contain no async entries. Confirm whether [email protected] is required or if issue #162 can be closed.

assets/build/blocks/DocsGrid/index.js (1)

1036-1055: Ignore lints on webpack runtime in built artifacts

Biome warnings about redeclarations/use-before-declaration are from webpack runtime scaffolding. Safe to ignore in built files; don’t patch compiled output.

Also applies to: 1047-1048

assets/build/blocks/Sidebar/index.js (1)

11-11: Block attribute parity: ensure server supports all editor options

The editor exposes “Count” ordering (block.json). Confirm render.php supports it (currently missing before fix) and that style attributes (e.g., container background) match frontend output.

@@ -0,0 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'c2ad1e7060a95f9ac780');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Inconsistent with AI-generated summary.

The AI summary states that wp-data is included in the dependencies array, but the actual code does not include it. The Sidebar block includes wp-data but DocsGrid does not, while DocsGrid includes wp-primitives that Sidebar lacks.

Verify whether the DocsGrid block requires wp-data for its functionality. If the block uses WordPress data stores or selectors, the dependency should be included.


🏁 Script executed:

#!/bin/bash
# Description: Check if DocsGrid source files use wp-data APIs

# Search for wp-data usage in DocsGrid source files
rg -n --type=js -C3 -g '!**/build/**' -g '**/DocsGrid/**' '@wordpress/data|useSelect|useDispatch|select|dispatch'

Length of output: 81305


Include wp-data in DocsGrid block dependencies
DocsGrid edit.js invokes wp.data.useSelect → enqueue 'wp-data'.

In assets/build/blocks/DocsGrid/index.asset.php, add 'wp-data' to the dependencies array:

 <?php return array(
-   'dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives'),
+   'dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-data'),
    'version'   => 'c2ad1e7060a95f9ac780'
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'c2ad1e7060a95f9ac780');
<?php return array(
'dependencies' => array(
'react-jsx-runtime',
'wp-block-editor',
'wp-blocks',
'wp-components',
'wp-element',
'wp-i18n',
'wp-primitives',
'wp-data',
),
'version' => 'c2ad1e7060a95f9ac780',
);
🤖 Prompt for AI Agents
In assets/build/blocks/DocsGrid/index.asset.php around line 1, the block
dependencies array is missing 'wp-data' even though DocsGrid edit.js calls
wp.data.useSelect; update the dependencies array to include 'wp-data' (add
'wp-data' as an element in the returned 'dependencies' array) so the built block
enqueues the data module at runtime.

Comment on lines +884 to +886
className: `wedocs-docs-grid ${getGridClass()}`,
children: loading ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(Spinner, {}) : displayDocs.map(doc => renderGridItem(doc, applyStyles()))
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Spinner is undefined in bundle — import and reference it from components

The compiled bundle renders but there’s no import or qualified reference. This will throw at runtime.

Fix in source (src/blocks/DocsGrid/edit.js):

- import { __ } from '@wordpress/i18n';
+ import { __ } from '@wordpress/i18n';
+ import { Spinner } from '@wordpress/components';

And ensure usage is <Spinner /> (named import) so the bundle emits _wordpress_components__.Spinner.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
className: `wedocs-docs-grid ${getGridClass()}`,
children: loading ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(Spinner, {}) : displayDocs.map(doc => renderGridItem(doc, applyStyles()))
})
import { __ } from '@wordpress/i18n';
import { Spinner } from '@wordpress/components';
🤖 Prompt for AI Agents
In assets/build/blocks/DocsGrid/index.js around lines 884-886 the compiled
bundle renders <Spinner /> but Spinner is not imported, causing a runtime error;
update the source file src/blocks/DocsGrid/edit.js to add a named import for
Spinner from @wordpress/components (e.g. import { Spinner } from
'@wordpress/components') and ensure the component usage is the named <Spinner />
so the bundle emits the correct _wordpress_components_.Spinner reference.

Comment on lines +182 to +186
.wedocs-docs-grid__articles li ::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-left: 0.5rem;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix incorrect ::marker selector spacing (won’t apply).

Use li::marker (no space). The current li ::marker will not style list markers in RTL either.

Apply this diff:

-.wedocs-docs-grid__articles li ::marker {
+.wedocs-docs-grid__articles li::marker {
   content: "•";
   color: var(--wedocs-doc-children-active-color, #0073aa);
-  margin-left: 0.5rem;
+  margin-left: 0.5rem;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.wedocs-docs-grid__articles li ::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-left: 0.5rem;
}
.wedocs-docs-grid__articles li::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-left: 0.5rem;
}
🤖 Prompt for AI Agents
In assets/build/blocks/DocsGrid/style-index-rtl.css around lines 182–186 the
selector "li ::marker" is incorrect (the space prevents the ::marker
pseudo-element from applying); change it to "li::marker" (no space) and keep the
same declarations (content, color, margin-left) so list markers are properly
styled in RTL.

Comment on lines +182 to +186
.wedocs-docs-grid__articles li ::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-right: 0.5rem;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix incorrect ::marker selector spacing (won’t apply).

Use li::marker (no space). The current li ::marker targets a descendant’s marker and won’t affect the list item bullet.

Apply this diff:

-.wedocs-docs-grid__articles li ::marker {
+.wedocs-docs-grid__articles li::marker {
   content: "•";
   color: var(--wedocs-doc-children-active-color, #0073aa);
   margin-right: 0.5rem;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.wedocs-docs-grid__articles li ::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-right: 0.5rem;
}
.wedocs-docs-grid__articles li::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-right: 0.5rem;
}
🤖 Prompt for AI Agents
In assets/build/blocks/DocsGrid/style-index.css around lines 182 to 186, the
selector uses "li ::marker" (a space) which targets a descendant's marker and
won't style the list item's bullet; change it to "li::marker" (no space) so the
rule applies to the list item marker, keeping the same declarations (content,
color, margin-right).

Comment on lines +10 to +19
"supports": {
"html": true,
"spacing": {
"padding": true
},
"color": {
"background": true,
"text": false
}
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Disable HTML editing for this dynamic block; add textdomain.

  • For server-rendered blocks, set "html": false to prevent editing raw HTML that won’t persist through render.
  • Consider adding "textdomain": "wedocs" for consistent translations.

Apply this diff:

   "supports": {
-    "html": true,
+    "html": false,
     "spacing": {
       "padding": true
     },
     "color": {
       "background": true,
       "text": false
     }
   },
+  "textdomain": "wedocs",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"supports": {
"html": true,
"spacing": {
"padding": true
},
"color": {
"background": true,
"text": false
}
},
"supports": {
"html": false,
"spacing": {
"padding": true
},
"color": {
"background": true,
"text": false
}
},
"textdomain": "wedocs",
🤖 Prompt for AI Agents
In assets/build/blocks/Sidebar/block.json around lines 10 to 19, the block
currently allows raw HTML editing and lacks a textdomain; update the "supports"
object to set "html" to false and add "textdomain": "wedocs" at the same level
(ensuring valid JSON structure and commas), so server-rendered content can't be
edited as raw HTML and translations use the wedocs textdomain.

Comment on lines +71 to +75
padding: 8px 12px;
background-color: var(--tree-header-bg, transparent);
color: var(--tree-header-text, inherit);
padding: var(--tree-header-padding, 8px 12px);
border-radius: var(--tree-header-border-radius, 0);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove duplicate padding declaration.

The padding property is declared twice (lines 71 and 74). The second declaration with a CSS variable overrides the first fixed value.

Apply this diff to remove the duplicate:

   align-items: center;
   justify-content: space-between;
   cursor: pointer;
-  padding: 8px 12px;
   background-color: var(--tree-header-bg, transparent);
   color: var(--tree-header-text, inherit);
   padding: var(--tree-header-padding, 8px 12px);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
padding: 8px 12px;
background-color: var(--tree-header-bg, transparent);
color: var(--tree-header-text, inherit);
padding: var(--tree-header-padding, 8px 12px);
border-radius: var(--tree-header-border-radius, 0);
align-items: center;
justify-content: space-between;
cursor: pointer;
background-color: var(--tree-header-bg, transparent);
color: var(--tree-header-text, inherit);
padding: var(--tree-header-padding, 8px 12px);
border-radius: var(--tree-header-border-radius, 0);
🧰 Tools
🪛 Biome (2.1.2)

[error] 74-74: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

padding is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🤖 Prompt for AI Agents
In src/blocks/Sidebar/style.css around lines 71 to 75, remove the duplicate
padding declaration so only the CSS variable-based padding remains (delete the
fixed `padding: 8px 12px;` line); ensure the remaining `padding:
var(--tree-header-padding, 8px 12px);` provides the default value and no other
padding declarations in this block conflict.

Comment on lines +1 to +244
import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
import {
Button,
FocalPointPicker,
ToggleControl,
__experimentalUnitControl as UnitControl,
Flex,
FlexItem,
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';

const BackgroundImageControls = ({ attributes, setAttributes, device }) => {
const { backgroundImageControls } = attributes;
const currentBackgroundImage = backgroundImageControls[device] || {};

const ALLOWED_MEDIA_TYPES = ['image'];

// Handle focal point change
const handleFocalPointChange = (newFocalPoint) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgFocalPoint: newFocalPoint,
},
},
});
};

const handleBackgroundImageSizeChange = (value) => {
let newFocalPoint = currentBackgroundImage.bgFocalPoint || {};
let newBgRepeat = currentBackgroundImage.bgRepeat || false;

// Set focal point and repeat based on size
if (value === 'cover') {
newFocalPoint = null;
newBgRepeat = null;
} else if (value === 'contain') {
newFocalPoint = { x: 0.5, y: 0.5 }; // 50% 50%
newBgRepeat = false;
} else if (value === 'tile') {
newFocalPoint = { x: 0.5, y: 0 }; // 50% 0px
newBgRepeat = true;
}

setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgSize: value,
bgFocalPoint: newFocalPoint,
bgRepeat: newBgRepeat,
},
},
});
};

return (
<div
className="block-responsive-background-image-controls"
style={{
display: 'flex',
flexDirection: 'column',
gap: '16px',
}}
>
<MediaUploadCheck>
<MediaUpload
onSelect={(media) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgUrl: media.url,
bgId: media.id,
},
},
});
}}
allowedTypes={ALLOWED_MEDIA_TYPES}
value={currentBackgroundImage.bgId}
render={({ open }) => (
<Button
__next40pxDefaultSize
onClick={open}
style={{
width: '100%',
justifyContent: 'center',
border: '1px solid #ddd',
}}
>
{currentBackgroundImage.bgUrl
? __(
'Change Background Image',
'block-responsive'
)
: __(
'Add Background Image',
'block-responsive'
)}
</Button>
)}
/>
</MediaUploadCheck>
{currentBackgroundImage.bgUrl && (
<>
<FocalPointPicker
__nextHasNoMarginBottom
url={currentBackgroundImage.bgUrl || ''}
value={currentBackgroundImage.bgFocalPoint || {}}
onDragStart={handleFocalPointChange}
onDrag={handleFocalPointChange}
onChange={handleFocalPointChange}
/>
<ToggleControl
__nextHasNoMarginBottom
label={__('Fixed background', 'block-responsive')}
checked={currentBackgroundImage.bgFixed || false}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgFixed: value,
},
},
});
}}
/>
<ToggleGroupControl
label={__('Size', 'block-responsive')}
value={currentBackgroundImage.bgSize || 'cover'}
onChange={handleBackgroundImageSizeChange}
isBlock
__nextHasNoMarginBottom
__next40pxDefaultSize
>
<ToggleGroupControlOption
value="cover"
label={__('Cover', 'block-responsive')}
/>
<ToggleGroupControlOption
value="contain"
label={__('Contain', 'block-responsive')}
/>
<ToggleGroupControlOption
value="tile"
label={__('Tile', 'block-responsive')}
/>
</ToggleGroupControl>
<Flex
style={{
gap: '8px',
justifyContent: 'flex-start',
}}
>
<FlexItem style={{ maxWidth: '100px' }}>
<UnitControl
__next40pxDefaultSize
value={currentBackgroundImage.bgWidth || 'auto'}
disabled={
currentBackgroundImage.bgSize !== 'tile'
}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgWidth: value,
},
},
});
}}
placeholder={__('Auto', 'block-responsive')}
/>
</FlexItem>
<FlexItem>
<ToggleControl
__nextHasNoMarginBottom
label={__('Repeat', 'block-responsive')}
disabled={
!(
currentBackgroundImage.bgSize ===
'contain' ||
currentBackgroundImage.bgSize === 'tile'
)
}
checked={
currentBackgroundImage.bgRepeat || false
}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgRepeat: value,
},
},
});
}}
/>
</FlexItem>
</Flex>

<Button
__next40pxDefaultSize
variant="secondary"
isDestructive
text={__('Reset All', 'block-responsive')}
style={{
width: '100%',
justifyContent: 'center',
}}
onClick={() => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgUrl: null,
bgId: null,
bgFocalPoint: null,
bgFixed: null,
bgSize: null,
bgWidth: null,
bgRepeat: null,
},
},
});
}}
/>
</>
)}
</div>
);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent text domain throughout the file.

The component uses 'block-responsive' as the text domain across all localized strings (lines 100, 104, 122, 137, 146, 150, 154, 181, 187, 217), but should use 'wedocs' to match the plugin's text domain.

Example fix for line 100:

-										'Change Background Image',
-										'block-responsive'
+										'Change Background Image',
+										'wedocs'

Apply similar changes to all other __() calls in this file.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
import {
Button,
FocalPointPicker,
ToggleControl,
__experimentalUnitControl as UnitControl,
Flex,
FlexItem,
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
const BackgroundImageControls = ({ attributes, setAttributes, device }) => {
const { backgroundImageControls } = attributes;
const currentBackgroundImage = backgroundImageControls[device] || {};
const ALLOWED_MEDIA_TYPES = ['image'];
// Handle focal point change
const handleFocalPointChange = (newFocalPoint) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgFocalPoint: newFocalPoint,
},
},
});
};
const handleBackgroundImageSizeChange = (value) => {
let newFocalPoint = currentBackgroundImage.bgFocalPoint || {};
let newBgRepeat = currentBackgroundImage.bgRepeat || false;
// Set focal point and repeat based on size
if (value === 'cover') {
newFocalPoint = null;
newBgRepeat = null;
} else if (value === 'contain') {
newFocalPoint = { x: 0.5, y: 0.5 }; // 50% 50%
newBgRepeat = false;
} else if (value === 'tile') {
newFocalPoint = { x: 0.5, y: 0 }; // 50% 0px
newBgRepeat = true;
}
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgSize: value,
bgFocalPoint: newFocalPoint,
bgRepeat: newBgRepeat,
},
},
});
};
return (
<div
className="block-responsive-background-image-controls"
style={{
display: 'flex',
flexDirection: 'column',
gap: '16px',
}}
>
<MediaUploadCheck>
<MediaUpload
onSelect={(media) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgUrl: media.url,
bgId: media.id,
},
},
});
}}
allowedTypes={ALLOWED_MEDIA_TYPES}
value={currentBackgroundImage.bgId}
render={({ open }) => (
<Button
__next40pxDefaultSize
onClick={open}
style={{
width: '100%',
justifyContent: 'center',
border: '1px solid #ddd',
}}
>
{currentBackgroundImage.bgUrl
? __(
'Change Background Image',
'block-responsive'
)
: __(
'Add Background Image',
'block-responsive'
)}
</Button>
)}
/>
</MediaUploadCheck>
{currentBackgroundImage.bgUrl && (
<>
<FocalPointPicker
__nextHasNoMarginBottom
url={currentBackgroundImage.bgUrl || ''}
value={currentBackgroundImage.bgFocalPoint || {}}
onDragStart={handleFocalPointChange}
onDrag={handleFocalPointChange}
onChange={handleFocalPointChange}
/>
<ToggleControl
__nextHasNoMarginBottom
label={__('Fixed background', 'block-responsive')}
checked={currentBackgroundImage.bgFixed || false}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgFixed: value,
},
},
});
}}
/>
<ToggleGroupControl
label={__('Size', 'block-responsive')}
value={currentBackgroundImage.bgSize || 'cover'}
onChange={handleBackgroundImageSizeChange}
isBlock
__nextHasNoMarginBottom
__next40pxDefaultSize
>
<ToggleGroupControlOption
value="cover"
label={__('Cover', 'block-responsive')}
/>
<ToggleGroupControlOption
value="contain"
label={__('Contain', 'block-responsive')}
/>
<ToggleGroupControlOption
value="tile"
label={__('Tile', 'block-responsive')}
/>
</ToggleGroupControl>
<Flex
style={{
gap: '8px',
justifyContent: 'flex-start',
}}
>
<FlexItem style={{ maxWidth: '100px' }}>
<UnitControl
__next40pxDefaultSize
value={currentBackgroundImage.bgWidth || 'auto'}
disabled={
currentBackgroundImage.bgSize !== 'tile'
}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgWidth: value,
},
},
});
}}
placeholder={__('Auto', 'block-responsive')}
/>
</FlexItem>
<FlexItem>
<ToggleControl
__nextHasNoMarginBottom
label={__('Repeat', 'block-responsive')}
disabled={
!(
currentBackgroundImage.bgSize ===
'contain' ||
currentBackgroundImage.bgSize === 'tile'
)
}
checked={
currentBackgroundImage.bgRepeat || false
}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgRepeat: value,
},
},
});
}}
/>
</FlexItem>
</Flex>
<Button
__next40pxDefaultSize
variant="secondary"
isDestructive
text={__('Reset All', 'block-responsive')}
style={{
width: '100%',
justifyContent: 'center',
}}
onClick={() => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgUrl: null,
bgId: null,
bgFocalPoint: null,
bgFixed: null,
bgSize: null,
bgWidth: null,
bgRepeat: null,
},
},
});
}}
/>
</>
)}
</div>
);
};
<MediaUpload
onSelect={(media) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgUrl: media.url,
bgId: media.id,
},
},
});
}}
allowedTypes={ALLOWED_MEDIA_TYPES}
value={currentBackgroundImage.bgId}
render={({ open }) => (
<Button
__next40pxDefaultSize
onClick={open}
style={{
width: '100%',
justifyContent: 'center',
border: '1px solid #ddd',
}}
>
{currentBackgroundImage.bgUrl
? __(
'Change Background Image',
'wedocs'
)
: __(
'Add Background Image',
'wedocs'
)}
</Button>
)}
/>
🤖 Prompt for AI Agents
In src/components/Blocks/BackgroundImageControls.js lines ~100–217, all
localization calls use the wrong text domain 'block-responsive'; replace every
instance of __('...','block-responsive') with __('...','wedocs') (i.e., update
all __() calls in the file to use 'wedocs' as the second argument) and run a
quick grep to ensure no remaining occurrences of 'block-responsive' in this
file.

Comment on lines +21 to +25
const BorderAndShadowControls = ({ attributes, setAttributes, device }) => {
const { borderAndShadowControls } = attributes;
const currentBorderAndShadow = borderAndShadowControls[device] || {};
const themeColors = useSetting('color.palette');

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard against undefined attributes to prevent runtime crash.

borderAndShadowControls[device] will throw if borderAndShadowControls is undefined. Default it safely.

Apply this diff:

-const { borderAndShadowControls } = attributes;
-const currentBorderAndShadow = borderAndShadowControls[device] || {};
+const { borderAndShadowControls = {} } = attributes;
+const currentBorderAndShadow = borderAndShadowControls?.[device] || {};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const BorderAndShadowControls = ({ attributes, setAttributes, device }) => {
const { borderAndShadowControls } = attributes;
const currentBorderAndShadow = borderAndShadowControls[device] || {};
const themeColors = useSetting('color.palette');
const BorderAndShadowControls = ({ attributes, setAttributes, device }) => {
const { borderAndShadowControls = {} } = attributes;
const currentBorderAndShadow = borderAndShadowControls?.[device] || {};
const themeColors = useSetting('color.palette');
// …
🤖 Prompt for AI Agents
In src/components/Blocks/BorderAndShadowControls.js around lines 21 to 25, guard
against attributes or attributes.borderAndShadowControls being undefined before
indexing by device; replace the direct access with a safe default (for example
destructure from attributes || {}, and compute currentBorderAndShadow as
(borderAndShadowControls && borderAndShadowControls[device]) || {} or use
optional chaining with a fallback) so the code never attempts to read properties
of undefined.

{
key: 'mobile',
icon: mobile,
label: __('Hide on mobile', 'block-responsive'),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent text domain.

The component uses 'block-responsive' as the text domain, but based on the PR context (weDocs plugin) and other files in the codebase, it should use 'wedocs' for consistency.

Apply this diff to fix the text domain:

-			label: __('Hide on mobile', 'block-responsive'),
+			label: __('Hide on mobile', 'wedocs'),
-			label: __('Hide on tablet', 'block-responsive'),
+			label: __('Hide on tablet', 'wedocs'),
-			label: __('Hide on desktop', 'block-responsive'),
+			label: __('Hide on desktop', 'wedocs'),
-				{__('Display Options', 'block-responsive')}
+				{__('Display Options', 'wedocs')}

Also applies to: 16-16, 21-21, 90-90

🤖 Prompt for AI Agents
In src/components/Blocks/DisplayControls.js around lines 11, 16, 21 and 90, the
i18n text domain is incorrectly set to 'block-responsive'; update each
__('...','block-responsive') and _x(...,'block-responsive') occurrences on those
lines to use the correct text domain 'wedocs' so all translation calls match the
project convention.

Comment on lines +1 to +274
import { __ } from '@wordpress/i18n';
import {
__experimentalFontFamilyControl as FontFamilyControl,
LineHeightControl,
useSetting,
useSettings,
FontSizePicker,
__experimentalFontAppearanceControl as FontAppearanceControl,
} from '@wordpress/block-editor';
import {
Flex,
FlexItem,
Button,
__experimentalUnitControl as UnitControl,
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon,
SelectControl,
} from '@wordpress/components';
import {
lineSolid,
formatUnderline,
formatStrikethrough,
formatUppercase,
formatLowercase,
formatCapitalize,
} from '@wordpress/icons';

const TypographyControls = ({ attributes, setAttributes, device }) => {
const { typographyControls } = attributes;
const currentTypography = typographyControls[device] || {};
const fontSizes = useSetting('typography.fontSizes');
const fontFamilies = useSettings('typography.fontFamilies');

// Combine both theme and custom fonts
const themeFonts = fontFamilies[0]?.theme || [];
const customFonts = fontFamilies[0]?.custom || [];
const validFontFamilies = [...themeFonts, ...customFonts];

return (
<>
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '16px',
}}
>
{validFontFamilies.length > 0 ? (
<FontFamilyControl
__next40pxDefaultSize
__nextHasNoMarginBottom
fontFamilies={validFontFamilies}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontFamily: value,
},
},
});
}}
value={currentTypography.fontFamily || ''}
/>
) : (
<div className="block-responsive-font-control-disabled">
<SelectControl
__next40pxDefaultSize
__nextHasNoMarginBottom
label={__('Font', 'block-responsive')}
help={__(
'Not supported in classic themes.',
'block-responsive'
)}
value={'default'}
onChange={() => {}}
disabled
options={[
{
disabled: true,
label: __('Default', 'block-responsive'),
value: 'default',
},
]}
/>
</div>
)}

<FontSizePicker
__next40pxDefaultSize
fontSizes={fontSizes}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontSize: value,
},
},
});
}}
value={currentTypography.fontSize || ''}
withSlider
withReset={false}
/>

<Flex style={{ gap: '16px' }}>
<FlexItem isBlock>
<FontAppearanceControl
__next40pxDefaultSize
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontAppearance: value,
},
},
});
}}
value={currentTypography.fontAppearance || ''}
/>
</FlexItem>
<FlexItem isBlock>
<LineHeightControl
__next40pxDefaultSize
__unstableInputWidth="auto"
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
lineHeight: value,
},
},
});
}}
value={currentTypography.lineHeight || ''}
/>
</FlexItem>
</Flex>

<Flex style={{ gap: '16px' }}>
<FlexItem isBlock>
<UnitControl
label={__('Letter spacing', 'block-responsive')}
__next40pxDefaultSize
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
letterSpacing: value,
},
},
});
}}
value={currentTypography.letterSpacing || ''}
/>
</FlexItem>
<FlexItem isBlock>
<ToggleGroupControl
isDeselectable
label={__('Decoration', 'block-responsive')}
value={currentTypography.textDecoration || ''}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
textDecoration: value,
},
},
});
}}
__next40pxDefaultSize
__nextHasNoMarginBottom
>
<ToggleGroupControlOptionIcon
value="none"
label={__('None', 'block-responsive')}
icon={lineSolid}
/>
<ToggleGroupControlOptionIcon
value="underline"
label={__('Underline', 'block-responsive')}
icon={formatUnderline}
/>
<ToggleGroupControlOptionIcon
value="line-through"
label={__('Strikethrough', 'block-responsive')}
icon={formatStrikethrough}
/>
</ToggleGroupControl>
</FlexItem>
</Flex>

<ToggleGroupControl
isDeselectable
label={__('Letter case', 'block-responsive')}
value={currentTypography.textTransform || ''}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
textTransform: value,
},
},
});
}}
__next40pxDefaultSize
__nextHasNoMarginBottom
>
<ToggleGroupControlOptionIcon
value="none"
label={__('None', 'block-responsive')}
icon={lineSolid}
/>
<ToggleGroupControlOptionIcon
value="uppercase"
label={__('Uppercase', 'block-responsive')}
icon={formatUppercase}
/>
<ToggleGroupControlOptionIcon
value="lowercase"
label={__('Lowercase', 'block-responsive')}
icon={formatLowercase}
/>
<ToggleGroupControlOptionIcon
value="capitalize"
label={__('Capitalize', 'block-responsive')}
icon={formatCapitalize}
/>
</ToggleGroupControl>
</div>
<Button
__next40pxDefaultSize
variant="secondary"
isDestructive
text={__('Reset All', 'block-responsive')}
style={{
width: '100%',
justifyContent: 'center',
marginTop: '16px',
}}
onClick={() => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...currentTypography,
fontFamily: null,
fontSize: null,
fontAppearance: null,
lineHeight: null,
letterSpacing: null,
textDecoration: null,
textTransform: null,
},
},
});
}}
/>
</>
);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent text domain throughout the file.

The component uses 'block-responsive' as the text domain across all localized strings, but should use 'wedocs' to match the plugin's text domain.

Lines affected: 71, 73, 82, 150, 169, 187-188, 192-193, 197-198, 206, 224-225, 229-230, 234-235, 239-240, 248.

Apply this pattern to all __() calls:

-					label={__('Font', 'block-responsive')}
+					label={__('Font', 'wedocs')}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { __ } from '@wordpress/i18n';
import {
__experimentalFontFamilyControl as FontFamilyControl,
LineHeightControl,
useSetting,
useSettings,
FontSizePicker,
__experimentalFontAppearanceControl as FontAppearanceControl,
} from '@wordpress/block-editor';
import {
Flex,
FlexItem,
Button,
__experimentalUnitControl as UnitControl,
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon,
SelectControl,
} from '@wordpress/components';
import {
lineSolid,
formatUnderline,
formatStrikethrough,
formatUppercase,
formatLowercase,
formatCapitalize,
} from '@wordpress/icons';
const TypographyControls = ({ attributes, setAttributes, device }) => {
const { typographyControls } = attributes;
const currentTypography = typographyControls[device] || {};
const fontSizes = useSetting('typography.fontSizes');
const fontFamilies = useSettings('typography.fontFamilies');
// Combine both theme and custom fonts
const themeFonts = fontFamilies[0]?.theme || [];
const customFonts = fontFamilies[0]?.custom || [];
const validFontFamilies = [...themeFonts, ...customFonts];
return (
<>
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '16px',
}}
>
{validFontFamilies.length > 0 ? (
<FontFamilyControl
__next40pxDefaultSize
__nextHasNoMarginBottom
fontFamilies={validFontFamilies}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontFamily: value,
},
},
});
}}
value={currentTypography.fontFamily || ''}
/>
) : (
<div className="block-responsive-font-control-disabled">
<SelectControl
__next40pxDefaultSize
__nextHasNoMarginBottom
label={__('Font', 'block-responsive')}
help={__(
'Not supported in classic themes.',
'block-responsive'
)}
value={'default'}
onChange={() => {}}
disabled
options={[
{
disabled: true,
label: __('Default', 'block-responsive'),
value: 'default',
},
]}
/>
</div>
)}
<FontSizePicker
__next40pxDefaultSize
fontSizes={fontSizes}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontSize: value,
},
},
});
}}
value={currentTypography.fontSize || ''}
withSlider
withReset={false}
/>
<Flex style={{ gap: '16px' }}>
<FlexItem isBlock>
<FontAppearanceControl
__next40pxDefaultSize
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontAppearance: value,
},
},
});
}}
value={currentTypography.fontAppearance || ''}
/>
</FlexItem>
<FlexItem isBlock>
<LineHeightControl
__next40pxDefaultSize
__unstableInputWidth="auto"
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
lineHeight: value,
},
},
});
}}
value={currentTypography.lineHeight || ''}
/>
</FlexItem>
</Flex>
<Flex style={{ gap: '16px' }}>
<FlexItem isBlock>
<UnitControl
label={__('Letter spacing', 'block-responsive')}
__next40pxDefaultSize
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
letterSpacing: value,
},
},
});
}}
value={currentTypography.letterSpacing || ''}
/>
</FlexItem>
<FlexItem isBlock>
<ToggleGroupControl
isDeselectable
label={__('Decoration', 'block-responsive')}
value={currentTypography.textDecoration || ''}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
textDecoration: value,
},
},
});
}}
__next40pxDefaultSize
__nextHasNoMarginBottom
>
<ToggleGroupControlOptionIcon
value="none"
label={__('None', 'block-responsive')}
icon={lineSolid}
/>
<ToggleGroupControlOptionIcon
value="underline"
label={__('Underline', 'block-responsive')}
icon={formatUnderline}
/>
<ToggleGroupControlOptionIcon
value="line-through"
label={__('Strikethrough', 'block-responsive')}
icon={formatStrikethrough}
/>
</ToggleGroupControl>
</FlexItem>
</Flex>
<ToggleGroupControl
isDeselectable
label={__('Letter case', 'block-responsive')}
value={currentTypography.textTransform || ''}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
textTransform: value,
},
},
});
}}
__next40pxDefaultSize
__nextHasNoMarginBottom
>
<ToggleGroupControlOptionIcon
value="none"
label={__('None', 'block-responsive')}
icon={lineSolid}
/>
<ToggleGroupControlOptionIcon
value="uppercase"
label={__('Uppercase', 'block-responsive')}
icon={formatUppercase}
/>
<ToggleGroupControlOptionIcon
value="lowercase"
label={__('Lowercase', 'block-responsive')}
icon={formatLowercase}
/>
<ToggleGroupControlOptionIcon
value="capitalize"
label={__('Capitalize', 'block-responsive')}
icon={formatCapitalize}
/>
</ToggleGroupControl>
</div>
<Button
__next40pxDefaultSize
variant="secondary"
isDestructive
text={__('Reset All', 'block-responsive')}
style={{
width: '100%',
justifyContent: 'center',
marginTop: '16px',
}}
onClick={() => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...currentTypography,
fontFamily: null,
fontSize: null,
fontAppearance: null,
lineHeight: null,
letterSpacing: null,
textDecoration: null,
textTransform: null,
},
},
});
}}
/>
</>
);
};
<div className="block-responsive-font-control-disabled">
<SelectControl
__next40pxDefaultSize
__nextHasNoMarginBottom
label={__( 'Font', 'wedocs' )}
help={__(
'Not supported in classic themes.',
'block-responsive'
)}
value={'default'}
onChange={() => {}}
disabled
options={[
{
disabled: true,
label={__( 'Default', 'wedocs' )}
value: 'default',
},
]}
/>
</div>

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants