From 8833f35c0cceec3c6abb4dce21f06c6e008243ec Mon Sep 17 00:00:00 2001
From: Iftakharul Islam Ifat
<88052038+iftakharul-islam@users.noreply.github.com>
Date: Wed, 18 Feb 2026 11:17:14 +0600
Subject: [PATCH 1/4] Add Elementor widgets and AJAX handlers
Register and include several new Elementor widgets and add AJAX endpoints/handlers.
- Added new Elementor widgets: DocsSidebar, NeedHelp, SearchModal, TableOfContents, WasThisHelpful (full widget implementations added under includes/Elementor/Widgets).
- Updated includes/Elementor.php to require and register the new widgets with Elementor.
- Extended includes/Ajax.php to register AJAX actions and implemented handlers for:
- wedocs_helpful_vote: records yes/no votes using post meta (_wedocs_helpful_yes/_wedocs_helpful_no) with nonce verification.
- wedocs_helpful_feedback: saves textual negative feedback into post meta (_wedocs_helpful_feedback) with nonce verification.
- wedocs_need_help_submit: processes the "Need More Help" contact form (nonce check per widget), sends email to recipient (falls back to admin email), and optionally saves submission to Elementor Pro submissions if available.
- Added private helper save_to_elementor_submissions() to persist form entries to Elementor Pro Submissions DB (checks for Elementor Pro class first).
Security: nonces and input sanitization are applied; email/recipient fallbacks handled. Widgets include styles, scripts and content templates for Elementor editor preview.
---
includes/Ajax.php | 184 ++++
includes/Elementor.php | 10 +
includes/Elementor/Widgets/DocsSidebar.php | 789 ++++++++++++++
includes/Elementor/Widgets/NeedHelp.php | 890 ++++++++++++++++
includes/Elementor/Widgets/SearchModal.php | 972 ++++++++++++++++++
.../Elementor/Widgets/TableOfContents.php | 745 ++++++++++++++
includes/Elementor/Widgets/WasThisHelpful.php | 636 ++++++++++++
7 files changed, 4226 insertions(+)
create mode 100644 includes/Elementor/Widgets/DocsSidebar.php
create mode 100644 includes/Elementor/Widgets/NeedHelp.php
create mode 100644 includes/Elementor/Widgets/SearchModal.php
create mode 100644 includes/Elementor/Widgets/TableOfContents.php
create mode 100644 includes/Elementor/Widgets/WasThisHelpful.php
diff --git a/includes/Ajax.php b/includes/Ajax.php
index 81700b0e..6ad3270c 100644
--- a/includes/Ajax.php
+++ b/includes/Ajax.php
@@ -53,6 +53,18 @@ public function __construct() {
// Handle load more for DocsGrid widget
add_action('wp_ajax_wedocs_load_more_docs', [$this, 'load_more_docs']);
add_action('wp_ajax_nopriv_wedocs_load_more_docs', [$this, 'load_more_docs']);
+
+ // Handle "Was This Helpful" votes
+ add_action('wp_ajax_wedocs_helpful_vote', [$this, 'handle_helpful_vote']);
+ add_action('wp_ajax_nopriv_wedocs_helpful_vote', [$this, 'handle_helpful_vote']);
+
+ // Handle "Was This Helpful" feedback
+ add_action('wp_ajax_wedocs_helpful_feedback', [$this, 'handle_helpful_feedback']);
+ add_action('wp_ajax_nopriv_wedocs_helpful_feedback', [$this, 'handle_helpful_feedback']);
+
+ // Handle "Need More Help" form submission
+ add_action('wp_ajax_wedocs_need_help_submit', [$this, 'handle_need_help_submit']);
+ add_action('wp_ajax_nopriv_wedocs_need_help_submit', [$this, 'handle_need_help_submit']);
}
/**
@@ -574,4 +586,176 @@ public function quick_search() {
wp_send_json_success( $results );
}
}
+
+ /**
+ * Handle "Was This Helpful" vote.
+ */
+ public function handle_helpful_vote() {
+ check_ajax_referer('wedocs_helpful_vote', 'nonce');
+
+ $post_id = intval($_POST['post_id'] ?? 0);
+ $vote = sanitize_text_field($_POST['vote'] ?? '');
+
+ if (!$post_id || !in_array($vote, ['yes', 'no'], true)) {
+ wp_send_json_error(['message' => __('Invalid vote.', 'wedocs')]);
+ }
+
+ $meta_key = $vote === 'yes' ? '_wedocs_helpful_yes' : '_wedocs_helpful_no';
+ $current = (int) get_post_meta($post_id, $meta_key, true);
+ update_post_meta($post_id, $meta_key, $current + 1);
+
+ wp_send_json_success([
+ 'yes' => (int) get_post_meta($post_id, '_wedocs_helpful_yes', true),
+ 'no' => (int) get_post_meta($post_id, '_wedocs_helpful_no', true),
+ ]);
+ }
+
+ /**
+ * Handle "Was This Helpful" negative feedback text.
+ */
+ public function handle_helpful_feedback() {
+ check_ajax_referer('wedocs_helpful_vote', 'nonce');
+
+ $post_id = intval($_POST['post_id'] ?? 0);
+ $feedback = sanitize_textarea_field($_POST['feedback'] ?? '');
+
+ if (!$post_id || empty($feedback)) {
+ wp_send_json_error(['message' => __('Invalid feedback.', 'wedocs')]);
+ }
+
+ $existing = get_post_meta($post_id, '_wedocs_helpful_feedback', true);
+ if (!is_array($existing)) {
+ $existing = [];
+ }
+
+ $existing[] = [
+ 'feedback' => $feedback,
+ 'date' => current_time('mysql'),
+ 'ip' => sanitize_text_field($_SERVER['REMOTE_ADDR'] ?? ''),
+ ];
+
+ update_post_meta($post_id, '_wedocs_helpful_feedback', $existing);
+ wp_send_json_success();
+ }
+
+ /**
+ * Handle "Need More Help" contact form submission.
+ */
+ public function handle_need_help_submit() {
+ $widget_id = sanitize_text_field($_POST['widget_id'] ?? '');
+
+ if (!wp_verify_nonce($_POST['nonce'] ?? '', 'wedocs_need_help_' . $widget_id)) {
+ wp_send_json_error(['message' => __('Security check failed.', 'wedocs')]);
+ }
+
+ $name = sanitize_text_field($_POST['name'] ?? '');
+ $email = sanitize_email($_POST['email'] ?? '');
+ $subject = sanitize_text_field($_POST['subject'] ?? '');
+ $message = sanitize_textarea_field($_POST['message'] ?? '');
+ $page_url = esc_url_raw($_POST['page_url'] ?? '');
+ $page_title = sanitize_text_field($_POST['page_title'] ?? '');
+ $recipient = sanitize_email($_POST['recipient'] ?? get_option('admin_email'));
+ $save_to_elementor = sanitize_text_field($_POST['save_to_elementor'] ?? '');
+ $post_id = intval($_POST['post_id'] ?? 0);
+
+ if (empty($message)) {
+ wp_send_json_error(['message' => __('Message is required.', 'wedocs')]);
+ }
+
+ if (empty($recipient) || !is_email($recipient)) {
+ $recipient = get_option('admin_email');
+ }
+
+ // Send email
+ $email_subject = !empty($subject) ? $subject : sprintf(__('[weDocs] Support request from %s', 'wedocs'), $page_title);
+
+ $body = sprintf(__("Name: %s\n", 'wedocs'), $name ?: __('Not provided', 'wedocs'));
+ $body .= sprintf(__("Email: %s\n", 'wedocs'), $email ?: __('Not provided', 'wedocs'));
+ $body .= sprintf(__("Page: %s (%s)\n\n", 'wedocs'), $page_title, $page_url);
+ $body .= sprintf(__("Message:\n%s", 'wedocs'), $message);
+
+ $headers = ['Content-Type: text/plain; charset=UTF-8'];
+ if (!empty($email) && is_email($email)) {
+ $headers[] = 'Reply-To: ' . ($name ? "$name <$email>" : $email);
+ }
+
+ $sent = wp_mail($recipient, $email_subject, $body, $headers);
+
+ // Save to Elementor Pro submissions if enabled
+ if ($save_to_elementor === 'yes') {
+ $this->save_to_elementor_submissions($widget_id, $post_id, $page_url, $page_title, [
+ 'name' => $name,
+ 'email' => $email,
+ 'subject' => $subject,
+ 'message' => $message,
+ ]);
+ }
+
+ if ($sent) {
+ wp_send_json_success();
+ } else {
+ wp_send_json_error(['message' => __('Failed to send email. Please try again.', 'wedocs')]);
+ }
+ }
+
+ /**
+ * Save form data to Elementor Pro submissions table.
+ *
+ * @param string $widget_id The Elementor widget ID.
+ * @param int $post_id The post/page ID where the form was submitted.
+ * @param string $page_url The page URL (referer).
+ * @param string $page_title The page title.
+ * @param array $fields Associative array of field id => value.
+ */
+ private function save_to_elementor_submissions($widget_id, $post_id, $page_url, $page_title, $fields) {
+ // Check if Elementor Pro submissions are available
+ if (!class_exists('\ElementorPro\Modules\Forms\Submissions\Database\Query')) {
+ return;
+ }
+
+ $query = \ElementorPro\Modules\Forms\Submissions\Database\Query::get_instance();
+
+ $fields_data = [];
+ foreach ($fields as $id => $value) {
+ if (empty($value)) {
+ continue;
+ }
+
+ $type = 'text';
+ if ($id === 'email') {
+ $type = 'email';
+ } elseif ($id === 'message') {
+ $type = 'textarea';
+ }
+
+ $fields_data[] = [
+ 'id' => $id,
+ 'value' => $value,
+ 'type' => $type,
+ ];
+ }
+
+ if (empty($fields_data)) {
+ return;
+ }
+
+ $submission_data = [
+ 'post_id' => $post_id ?: 0,
+ 'referer' => $page_url,
+ 'referer_title' => $page_title,
+ 'element_id' => $widget_id,
+ 'form_name' => __('weDocs - Need More Help', 'wedocs'),
+ 'campaign_id' => 0,
+ 'user_id' => get_current_user_id() ?: null,
+ 'user_ip' => sanitize_text_field($_SERVER['REMOTE_ADDR'] ?? ''),
+ 'user_agent' => sanitize_text_field($_SERVER['HTTP_USER_AGENT'] ?? ''),
+ 'actions_count' => 1,
+ 'actions_succeeded_count' => 1,
+ 'meta' => wp_json_encode([
+ 'edit_post_id' => $post_id ?: 0,
+ ]),
+ ];
+
+ $query->add_submission($submission_data, $fields_data);
+ }
}
diff --git a/includes/Elementor.php b/includes/Elementor.php
index 9f433630..a62fae37 100644
--- a/includes/Elementor.php
+++ b/includes/Elementor.php
@@ -44,10 +44,20 @@ public function register_widgets() {
// Include widget files
// require_once WEDOCS_PATH . '/includes/Elementor/Widgets/Search.php';
require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocsGrid.php';
+ require_once WEDOCS_PATH . '/includes/Elementor/Widgets/TableOfContents.php';
+ require_once WEDOCS_PATH . '/includes/Elementor/Widgets/NeedHelp.php';
+ require_once WEDOCS_PATH . '/includes/Elementor/Widgets/WasThisHelpful.php';
+ require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocsSidebar.php';
+ require_once WEDOCS_PATH . '/includes/Elementor/Widgets/SearchModal.php';
// Register widgets
// \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\Search() );
\Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsGrid() );
+ \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\TableOfContents() );
+ \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\NeedHelp() );
+ \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\WasThisHelpful() );
+ \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsSidebar() );
+ \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\SearchModal() );
}
/**
diff --git a/includes/Elementor/Widgets/DocsSidebar.php b/includes/Elementor/Widgets/DocsSidebar.php
new file mode 100644
index 00000000..fa429f8d
--- /dev/null
+++ b/includes/Elementor/Widgets/DocsSidebar.php
@@ -0,0 +1,789 @@
+start_controls_section(
+ 'content_section',
+ [
+ 'label' => __('Content', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_CONTENT,
+ ]
+ );
+
+ $this->add_control(
+ 'show_search',
+ [
+ 'label' => __('Show Quick Search', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'search_placeholder',
+ [
+ 'label' => __('Search Placeholder', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Quick search...', 'wedocs'),
+ 'condition' => ['show_search' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'show_shortcut',
+ [
+ 'label' => __('Show Keyboard Shortcut', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ 'description' => __('Show the ⌘K shortcut hint', 'wedocs'),
+ 'condition' => ['show_search' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'show_title',
+ [
+ 'label' => __('Show Doc Title', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'collapse_behavior',
+ [
+ 'label' => __('Default Collapse', 'wedocs'),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'expand_active',
+ 'options' => [
+ 'expand_active' => __('Expand Active Only', 'wedocs'),
+ 'expand_all' => __('Expand All', 'wedocs'),
+ 'collapse_all' => __('Collapse All', 'wedocs'),
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Container
+ $this->start_controls_section(
+ 'style_container',
+ [
+ 'label' => __('Container', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'bg_color',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'container_padding',
+ [
+ 'label' => __('Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%', 'em'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'container_border',
+ 'selector' => '{{WRAPPER}} .wedocs-el-sidebar',
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'container_border_radius',
+ [
+ 'label' => __('Border Radius', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Box_Shadow::get_type(),
+ [
+ 'name' => 'container_shadow',
+ 'selector' => '{{WRAPPER}} .wedocs-el-sidebar',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Title
+ $this->start_controls_section(
+ 'style_title',
+ [
+ 'label' => __('Doc Title', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ 'condition' => ['show_title' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'title_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#1e293b',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar__title' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'title_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-el-sidebar__title',
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'title_margin',
+ [
+ 'label' => __('Margin', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', 'em'],
+ 'default' => ['top' => 0, 'right' => 0, 'bottom' => 15, 'left' => 0, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar__title' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Search
+ $this->start_controls_section(
+ 'style_search',
+ [
+ 'label' => __('Quick Search', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ 'condition' => ['show_search' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'search_bg',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#f8fafc',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar__search' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'search_text_color',
+ [
+ 'label' => __('Text Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#64748b',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar__search input' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'search_placeholder_color',
+ [
+ 'label' => __('Placeholder Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#94a3b8',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar__search input::placeholder' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'search_icon_color',
+ [
+ 'label' => __('Icon Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#95a4b9',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar__search svg' => 'fill: {{VALUE}};',
+ '{{WRAPPER}} .wedocs-el-sidebar__search svg path' => 'fill: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'search_border',
+ 'selector' => '{{WRAPPER}} .wedocs-el-sidebar__search',
+ 'fields_options' => [
+ 'border' => ['default' => 'solid'],
+ 'width' => ['default' => ['top' => 1, 'right' => 1, 'bottom' => 1, 'left' => 1]],
+ 'color' => ['default' => '#e2e8f0'],
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'search_border_radius',
+ [
+ 'label' => __('Border Radius', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%'],
+ 'default' => ['top' => 6, 'right' => 6, 'bottom' => 6, 'left' => 6, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar__search' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'search_padding',
+ [
+ 'label' => __('Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', 'em'],
+ 'default' => ['top' => 10, 'right' => 14, 'bottom' => 10, 'left' => 14, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar__search' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'shortcut_bg',
+ [
+ 'label' => __('Shortcut Badge Background', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#e2e8f0',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar__search .short-key' => 'background-color: {{VALUE}};',
+ ],
+ 'condition' => ['show_shortcut' => 'yes'],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Navigation Items
+ $this->start_controls_section(
+ 'style_nav',
+ [
+ 'label' => __('Navigation Items', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'link_color',
+ [
+ 'label' => __('Link Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#475569',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list a' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'link_hover_color',
+ [
+ 'label' => __('Hover Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list a:hover' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'active_color',
+ [
+ 'label' => __('Active Item Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list .current_page_item > a' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'active_bg_color',
+ [
+ 'label' => __('Active Item Background', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list .current_page_item > a' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'active_border_color',
+ [
+ 'label' => __('Active Border Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list .current_page_item > a' => 'border-left-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'link_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list a',
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'item_padding',
+ [
+ 'label' => __('Item Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', 'em'],
+ 'default' => ['top' => 8, 'right' => 12, 'bottom' => 8, 'left' => 12, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list a' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'child_indent',
+ [
+ 'label' => __('Sub-item Indent', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 0, 'max' => 40]],
+ 'default' => ['size' => 16],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list .children' => 'padding-left: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'caret_color',
+ [
+ 'label' => __('Caret/Arrow Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#94a3b8',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar .wedocs-caret' => 'border-top-color: {{VALUE}};',
+ '{{WRAPPER}} .wedocs-el-sidebar .wd-state-closed > a .wedocs-caret' => 'border-left-color: {{VALUE}}; border-top-color: transparent;',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'divider_color',
+ [
+ 'label' => __('Divider Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#f1f5f9',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list > li' => 'border-bottom-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'show_dividers',
+ [
+ 'label' => __('Show Dividers', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => '',
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ protected function render() {
+ $settings = $this->get_settings_for_display();
+
+ $show_search = ($settings['show_search'] ?? 'yes') === 'yes';
+ $show_shortcut = ($settings['show_shortcut'] ?? 'yes') === 'yes';
+ $show_title = ($settings['show_title'] ?? 'yes') === 'yes';
+ $search_placeholder = $settings['search_placeholder'] ?? __('Quick search...', 'wedocs');
+ $collapse_behavior = $settings['collapse_behavior'] ?? 'expand_active';
+ $show_dividers = ($settings['show_dividers'] ?? '') === 'yes';
+
+ global $post;
+
+ // Determine the parent doc
+ $ancestors = [];
+ $parent = false;
+
+ if (!empty($post->post_parent)) {
+ $ancestors = get_post_ancestors($post->ID);
+ $root = count($ancestors) - 1;
+ $parent = $ancestors[$root];
+ } else {
+ $parent = !empty($post->ID) ? $post->ID : '';
+ }
+
+ if (!$parent) {
+ if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
+ echo '
' . __('Docs Sidebar: This widget displays the documentation navigation. Preview it on a single doc page.', 'wedocs') . '
';
+ }
+ return;
+ }
+
+ $walker = new \WeDevs\WeDocs\Walker();
+ $children = wp_list_pages([
+ 'title_li' => '',
+ 'order' => 'menu_order',
+ 'child_of' => $parent,
+ 'echo' => false,
+ 'post_type' => 'docs',
+ 'walker' => $walker,
+ ]);
+
+ $sidebar_class = 'wedocs-el-sidebar';
+ if ($collapse_behavior === 'expand_all') {
+ $sidebar_class .= ' wedocs-el-sidebar--expand-all';
+ } elseif ($collapse_behavior === 'collapse_all') {
+ $sidebar_class .= ' wedocs-el-sidebar--collapse-all';
+ }
+ ?>
+
+
+
+
+
+
+
+ <#
+ var showSearch = settings.show_search === 'yes';
+ var showShortcut = settings.show_shortcut === 'yes';
+ var showTitle = settings.show_title === 'yes';
+ var showDividers = settings.show_dividers === 'yes';
+ #>
+
+
+ start_controls_section(
+ 'trigger_section',
+ [
+ 'label' => __('Trigger', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_CONTENT,
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_heading',
+ [
+ 'label' => __('Heading', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Need More Help?', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_description',
+ [
+ 'label' => __('Description', 'wedocs'),
+ 'type' => Controls_Manager::TEXTAREA,
+ 'default' => __("Can't find what you're looking for? Reach out to our support team.", 'wedocs'),
+ 'rows' => 3,
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_icon',
+ [
+ 'label' => __('Icon', 'wedocs'),
+ 'type' => Controls_Manager::ICONS,
+ 'default' => [
+ 'value' => 'fas fa-headset',
+ 'library' => 'fa-solid',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'button_text',
+ [
+ 'label' => __('Button Text', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Contact Support', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'layout',
+ [
+ 'label' => __('Layout', 'wedocs'),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'card',
+ 'options' => [
+ 'card' => __('Card', 'wedocs'),
+ 'inline' => __('Inline', 'wedocs'),
+ 'minimal' => __('Minimal (Button Only)', 'wedocs'),
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Content Section - Modal
+ $this->start_controls_section(
+ 'modal_section',
+ [
+ 'label' => __('Modal Content', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_CONTENT,
+ ]
+ );
+
+ $this->add_control(
+ 'modal_title',
+ [
+ 'label' => __('Modal Title', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Contact Support', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'modal_description',
+ [
+ 'label' => __('Modal Description', 'wedocs'),
+ 'type' => Controls_Manager::TEXTAREA,
+ 'default' => __('Fill out the form below and our team will get back to you as soon as possible.', 'wedocs'),
+ 'rows' => 2,
+ ]
+ );
+
+ $this->add_control(
+ 'show_name_field',
+ [
+ 'label' => __('Show Name Field', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'show_email_field',
+ [
+ 'label' => __('Show Email Field', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'show_subject_field',
+ [
+ 'label' => __('Show Subject Field', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'submit_text',
+ [
+ 'label' => __('Submit Button Text', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Send Message', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'success_message',
+ [
+ 'label' => __('Success Message', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Thank you! Your message has been sent successfully.', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'recipient_email',
+ [
+ 'label' => __('Recipient Email', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => get_option('admin_email'),
+ 'description' => __('Email address where form submissions will be sent', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'save_to_elementor',
+ [
+ 'label' => __('Save to Elementor Submissions', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => '',
+ 'description' => __('Save form data to Elementor Pro submissions (requires Elementor Pro)', 'wedocs'),
+ 'separator' => 'before',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Card
+ $this->start_controls_section(
+ 'style_card',
+ [
+ 'label' => __('Card / Trigger', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'card_bg_color',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#f0f7ff',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__card' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'card_padding',
+ [
+ 'label' => __('Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%', 'em'],
+ 'default' => [
+ 'top' => 25,
+ 'right' => 25,
+ 'bottom' => 25,
+ 'left' => 25,
+ 'unit' => 'px',
+ ],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__card' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'card_border',
+ 'selector' => '{{WRAPPER}} .wedocs-need-help__card',
+ 'fields_options' => [
+ 'border' => ['default' => 'solid'],
+ 'width' => ['default' => ['top' => 1, 'right' => 1, 'bottom' => 1, 'left' => 1]],
+ 'color' => ['default' => '#d0e3f7'],
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'card_border_radius',
+ [
+ 'label' => __('Border Radius', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%'],
+ 'default' => ['top' => 8, 'right' => 8, 'bottom' => 8, 'left' => 8, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__card' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'heading_color',
+ [
+ 'label' => __('Heading Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#1a202c',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__heading' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'heading_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-need-help__heading',
+ ]
+ );
+
+ $this->add_control(
+ 'desc_color',
+ [
+ 'label' => __('Description Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#4a5568',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__desc' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'icon_color',
+ [
+ 'label' => __('Icon Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__icon' => 'color: {{VALUE}};',
+ '{{WRAPPER}} .wedocs-need-help__icon svg' => 'fill: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'icon_size',
+ [
+ 'label' => __('Icon Size', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 16, 'max' => 80]],
+ 'default' => ['size' => 40],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__icon i' => 'font-size: {{SIZE}}px;',
+ '{{WRAPPER}} .wedocs-need-help__icon svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Button
+ $this->start_controls_section(
+ 'style_button',
+ [
+ 'label' => __('Button', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'btn_bg_color',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__btn' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'btn_text_color',
+ [
+ 'label' => __('Text Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#ffffff',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__btn' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'btn_hover_bg_color',
+ [
+ 'label' => __('Hover Background', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#005177',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__btn:hover' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'btn_padding',
+ [
+ 'label' => __('Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', 'em'],
+ 'default' => ['top' => 12, 'right' => 24, 'bottom' => 12, 'left' => 24, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__btn' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'btn_border_radius',
+ [
+ 'label' => __('Border Radius', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%'],
+ 'default' => ['top' => 6, 'right' => 6, 'bottom' => 6, 'left' => 6, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__btn' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'btn_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-need-help__btn',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Modal
+ $this->start_controls_section(
+ 'style_modal',
+ [
+ 'label' => __('Modal', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'modal_bg_color',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#ffffff',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__modal-content' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'modal_overlay_color',
+ [
+ 'label' => __('Overlay Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => 'rgba(0,0,0,0.5)',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__modal' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'modal_width',
+ [
+ 'label' => __('Modal Width', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'size_units' => ['px', '%'],
+ 'range' => [
+ 'px' => ['min' => 300, 'max' => 800],
+ '%' => ['min' => 30, 'max' => 90],
+ ],
+ 'default' => ['size' => 500, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__modal-content' => 'max-width: {{SIZE}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'modal_border_radius',
+ [
+ 'label' => __('Border Radius', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%'],
+ 'default' => ['top' => 12, 'right' => 12, 'bottom' => 12, 'left' => 12, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-need-help__modal-content' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Box_Shadow::get_type(),
+ [
+ 'name' => 'modal_shadow',
+ 'selector' => '{{WRAPPER}} .wedocs-need-help__modal-content',
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ protected function render() {
+ $settings = $this->get_settings_for_display();
+
+ $layout = $settings['layout'] ?? 'card';
+ $show_name = ($settings['show_name_field'] ?? 'yes') === 'yes';
+ $show_email = ($settings['show_email_field'] ?? 'yes') === 'yes';
+ $show_subject = ($settings['show_subject_field'] ?? 'yes') === 'yes';
+ $widget_id = $this->get_id();
+ ?>
+
+
+
+
+
+ 'true']); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true']); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <#
+ var layout = settings.layout || 'card';
+ #>
+
+ <# if (layout !== 'minimal') { #>
+
+ <# if (settings.trigger_icon && settings.trigger_icon.value) { #>
+
+ <# var iconHTML = elementor.helpers.renderIcon(view, settings.trigger_icon, { 'aria-hidden': true }, 'i', 'object');
+ if (iconHTML && iconHTML.rendered) { #>
+ {{{ iconHTML.value }}}
+ <# } else { #>
+
+ <# } #>
+
+ <# } #>
+
+
+
{{ settings.trigger_heading }}
+ <# if (settings.trigger_description) { #>
+
{{ settings.trigger_description }}
+ <# } #>
+
+
+
+ {{ settings.button_text }}
+
+
+ <# } else { #>
+
+ <# if (settings.trigger_icon && settings.trigger_icon.value) {
+ var iconHTML = elementor.helpers.renderIcon(view, settings.trigger_icon, { 'aria-hidden': true }, 'i', 'object');
+ if (iconHTML && iconHTML.rendered) { #>
+ {{{ iconHTML.value }}}
+ <# } else { #>
+
+ <# }
+ } #>
+ {{ settings.button_text }}
+
+ <# } #>
+ start_controls_section(
+ 'trigger_section',
+ [
+ 'label' => __('Trigger', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_CONTENT,
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_type',
+ [
+ 'label' => __('Trigger Type', 'wedocs'),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'input',
+ 'options' => [
+ 'input' => __('Search Input (like sidebar)', 'wedocs'),
+ 'button' => __('Button', 'wedocs'),
+ 'icon' => __('Icon Only', 'wedocs'),
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'placeholder',
+ [
+ 'label' => __('Placeholder Text', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Search documentation...', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'button_text',
+ [
+ 'label' => __('Button Text', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Search Docs', 'wedocs'),
+ 'condition' => ['trigger_type' => 'button'],
+ ]
+ );
+
+ $this->add_control(
+ 'show_shortcut',
+ [
+ 'label' => __('Show ⌘K Shortcut', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_icon',
+ [
+ 'label' => __('Search Icon', 'wedocs'),
+ 'type' => Controls_Manager::ICONS,
+ 'default' => [
+ 'value' => 'fas fa-search',
+ 'library' => 'fa-solid',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'alignment',
+ [
+ 'label' => __('Alignment', 'wedocs'),
+ 'type' => Controls_Manager::CHOOSE,
+ 'options' => [
+ 'left' => ['title' => __('Left', 'wedocs'), 'icon' => 'eicon-text-align-left'],
+ 'center' => ['title' => __('Center', 'wedocs'), 'icon' => 'eicon-text-align-center'],
+ 'right' => ['title' => __('Right', 'wedocs'), 'icon' => 'eicon-text-align-right'],
+ ],
+ 'default' => 'left',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-search-modal-trigger-wrap' => 'text-align: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Content Section - Modal
+ $this->start_controls_section(
+ 'modal_section',
+ [
+ 'label' => __('Modal', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_CONTENT,
+ ]
+ );
+
+ $this->add_control(
+ 'modal_placeholder',
+ [
+ 'label' => __('Modal Search Placeholder', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Search documentation', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'empty_message',
+ [
+ 'label' => __('No Results Message', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __("Your search didn't match any documents", 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'blank_message',
+ [
+ 'label' => __('Blank Search Message', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Search field cannot be blank', 'wedocs'),
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Trigger
+ $this->start_controls_section(
+ 'style_trigger',
+ [
+ 'label' => __('Trigger', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_bg',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#f8fafc',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-search-modal-trigger' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_text_color',
+ [
+ 'label' => __('Text Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#94a3b8',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-search-modal-trigger' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_icon_color',
+ [
+ 'label' => __('Icon Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#95a4b9',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-search-modal-trigger__icon' => 'color: {{VALUE}};',
+ '{{WRAPPER}} .wedocs-search-modal-trigger__icon svg' => 'fill: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_hover_bg',
+ [
+ 'label' => __('Hover Background', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#f1f5f9',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-search-modal-trigger:hover' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_hover_border_color',
+ [
+ 'label' => __('Hover Border Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#cbd5e1',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-search-modal-trigger:hover' => 'border-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'trigger_border',
+ 'selector' => '{{WRAPPER}} .wedocs-search-modal-trigger',
+ 'fields_options' => [
+ 'border' => ['default' => 'solid'],
+ 'width' => ['default' => ['top' => 1, 'right' => 1, 'bottom' => 1, 'left' => 1]],
+ 'color' => ['default' => '#e2e8f0'],
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'trigger_border_radius',
+ [
+ 'label' => __('Border Radius', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%'],
+ 'default' => ['top' => 8, 'right' => 8, 'bottom' => 8, 'left' => 8, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-search-modal-trigger' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'trigger_padding',
+ [
+ 'label' => __('Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', 'em'],
+ 'default' => ['top' => 12, 'right' => 16, 'bottom' => 12, 'left' => 16, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-search-modal-trigger' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Box_Shadow::get_type(),
+ [
+ 'name' => 'trigger_shadow',
+ 'selector' => '{{WRAPPER}} .wedocs-search-modal-trigger',
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'trigger_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-search-modal-trigger',
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'trigger_width',
+ [
+ 'label' => __('Width', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'size_units' => ['px', '%'],
+ 'range' => [
+ 'px' => ['min' => 100, 'max' => 800],
+ '%' => ['min' => 10, 'max' => 100],
+ ],
+ 'default' => ['size' => 100, 'unit' => '%'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-search-modal-trigger' => 'width: {{SIZE}}{{UNIT}};',
+ ],
+ 'condition' => ['trigger_type' => 'input'],
+ ]
+ );
+
+ $this->add_control(
+ 'shortcut_bg',
+ [
+ 'label' => __('Shortcut Badge Background', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#e2e8f0',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-search-modal-trigger__shortcut' => 'background-color: {{VALUE}};',
+ ],
+ 'condition' => ['show_shortcut' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'shortcut_text_color',
+ [
+ 'label' => __('Shortcut Badge Text', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#64748b',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-search-modal-trigger__shortcut' => 'color: {{VALUE}};',
+ ],
+ 'condition' => ['show_shortcut' => 'yes'],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Modal
+ $this->start_controls_section(
+ 'style_modal',
+ [
+ 'label' => __('Modal', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'modal_overlay_color',
+ [
+ 'label' => __('Overlay Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => 'rgba(15, 23, 42, 0.6)',
+ ]
+ );
+
+ $this->add_control(
+ 'modal_bg',
+ [
+ 'label' => __('Modal Background', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#ffffff',
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'modal_width',
+ [
+ 'label' => __('Modal Width', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'size_units' => ['px', '%'],
+ 'range' => [
+ 'px' => ['min' => 400, 'max' => 900],
+ '%' => ['min' => 30, 'max' => 90],
+ ],
+ 'default' => ['size' => 620, 'unit' => 'px'],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'modal_border_radius',
+ [
+ 'label' => __('Modal Border Radius', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px'],
+ 'default' => ['top' => 12, 'right' => 12, 'bottom' => 12, 'left' => 12, 'unit' => 'px'],
+ ]
+ );
+
+ $this->add_control(
+ 'result_hover_color',
+ [
+ 'label' => __('Result Hover Background', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#3B82F6',
+ ]
+ );
+
+ $this->add_control(
+ 'result_icon_bg',
+ [
+ 'label' => __('Result Icon Background', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#D9EBFF',
+ ]
+ );
+
+ $this->add_control(
+ 'result_icon_color',
+ [
+ 'label' => __('Result Icon Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#3B82F6',
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ protected function render() {
+ $settings = $this->get_settings_for_display();
+
+ $trigger_type = $settings['trigger_type'] ?? 'input';
+ $show_shortcut = ($settings['show_shortcut'] ?? 'yes') === 'yes';
+ $widget_id = $this->get_id();
+
+ $modal_overlay = $settings['modal_overlay_color'] ?? 'rgba(15, 23, 42, 0.6)';
+ $modal_bg = $settings['modal_bg'] ?? '#ffffff';
+ $modal_width = ($settings['modal_width']['size'] ?? 620) . ($settings['modal_width']['unit'] ?? 'px');
+ $modal_radius_top = $settings['modal_border_radius']['top'] ?? 12;
+ $modal_radius_right = $settings['modal_border_radius']['right'] ?? 12;
+ $modal_radius_bottom = $settings['modal_border_radius']['bottom'] ?? 12;
+ $modal_radius_left = $settings['modal_border_radius']['left'] ?? 12;
+ $modal_radius_unit = $settings['modal_border_radius']['unit'] ?? 'px';
+ $modal_radius = "{$modal_radius_top}{$modal_radius_unit} {$modal_radius_right}{$modal_radius_unit} {$modal_radius_bottom}{$modal_radius_unit} {$modal_radius_left}{$modal_radius_unit}";
+
+ $result_hover = $settings['result_hover_color'] ?? '#3B82F6';
+ $result_icon_bg = $settings['result_icon_bg'] ?? '#D9EBFF';
+ $result_icon_color = $settings['result_icon_color'] ?? '#3B82F6';
+ ?>
+
+
+
+
+
+
+
+
+
+ 'true']); ?>
+
+
+
+
+
+
+ ⌘K
+
+
+
+
+
+
+
+ 'true']); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <#
+ var triggerType = settings.trigger_type || 'input';
+ var showShortcut = settings.show_shortcut === 'yes';
+ #>
+
+
+ <# if (triggerType === 'input') { #>
+
+
+ <# } else if (triggerType === 'button') { #>
+
+
+ <# if (settings.trigger_icon && settings.trigger_icon.value) {
+ var iconHTML = elementor.helpers.renderIcon(view, settings.trigger_icon, { 'aria-hidden': true }, 'i', 'object');
+ if (iconHTML && iconHTML.rendered) { #>
+ {{{ iconHTML.value }}}
+ <# } else { #>
+
+ <# }
+ } else { #>
+
+ <# } #>
+
+ {{ settings.button_text || 'Search Docs' }}
+ <# if (showShortcut) { #>
+ ⌘K
+ <# } #>
+
+
+ <# } else { #>
+
+ <# if (settings.trigger_icon && settings.trigger_icon.value) {
+ var iconHTML = elementor.helpers.renderIcon(view, settings.trigger_icon, { 'aria-hidden': true }, 'i', 'object');
+ if (iconHTML && iconHTML.rendered) { #>
+ {{{ iconHTML.value }}}
+ <# } else { #>
+
+ <# }
+ } else { #>
+
+ <# } #>
+
+ <# } #>
+
+ start_controls_section(
+ 'content_section',
+ [
+ 'label' => __('Content', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_CONTENT,
+ ]
+ );
+
+ $this->add_control(
+ 'title',
+ [
+ 'label' => __('Title', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('On This Page', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'title_tag',
+ [
+ 'label' => __('Title HTML Tag', 'wedocs'),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'h3',
+ 'options' => [
+ 'h2' => 'H2',
+ 'h3' => 'H3',
+ 'h4' => 'H4',
+ 'h5' => 'H5',
+ 'div' => 'DIV',
+ 'span' => 'SPAN',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'heading_levels',
+ [
+ 'label' => __('Heading Levels', 'wedocs'),
+ 'type' => Controls_Manager::SELECT2,
+ 'multiple' => true,
+ 'default' => ['2', '3'],
+ 'options' => [
+ '2' => 'H2',
+ '3' => 'H3',
+ '4' => 'H4',
+ '5' => 'H5',
+ '6' => 'H6',
+ ],
+ 'description' => __('Select which heading levels to include', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'collapsible',
+ [
+ 'label' => __('Collapsible', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => '',
+ ]
+ );
+
+ $this->add_control(
+ 'collapsed_default',
+ [
+ 'label' => __('Collapsed by Default', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => '',
+ 'condition' => [
+ 'collapsible' => 'yes',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'sticky',
+ [
+ 'label' => __('Sticky Position', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => '',
+ 'description' => __('Make TOC sticky when scrolling', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'sticky_offset',
+ [
+ 'label' => __('Sticky Offset (px)', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => [
+ 'px' => [
+ 'min' => 0,
+ 'max' => 200,
+ ],
+ ],
+ 'default' => [
+ 'size' => 20,
+ ],
+ 'condition' => [
+ 'sticky' => 'yes',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'show_numbers',
+ [
+ 'label' => __('Show Numbers', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => '',
+ ]
+ );
+
+ $this->add_control(
+ 'smooth_scroll',
+ [
+ 'label' => __('Smooth Scroll', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'highlight_active',
+ [
+ 'label' => __('Highlight Active Section', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Container
+ $this->start_controls_section(
+ 'style_container',
+ [
+ 'label' => __('Container', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'bg_color',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#f8f9fa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-toc' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'padding',
+ [
+ 'label' => __('Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%', 'em'],
+ 'default' => [
+ 'top' => 20,
+ 'right' => 20,
+ 'bottom' => 20,
+ 'left' => 20,
+ 'unit' => 'px',
+ ],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-toc' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'container_border',
+ 'label' => __('Border', 'wedocs'),
+ 'selector' => '{{WRAPPER}} .wedocs-toc',
+ 'fields_options' => [
+ 'border' => ['default' => 'solid'],
+ 'width' => ['default' => ['top' => 1, 'right' => 1, 'bottom' => 1, 'left' => 1]],
+ 'color' => ['default' => '#e2e8f0'],
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'border_radius',
+ [
+ 'label' => __('Border Radius', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%'],
+ 'default' => [
+ 'top' => 8,
+ 'right' => 8,
+ 'bottom' => 8,
+ 'left' => 8,
+ 'unit' => 'px',
+ ],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-toc' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Box_Shadow::get_type(),
+ [
+ 'name' => 'container_shadow',
+ 'selector' => '{{WRAPPER}} .wedocs-toc',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Title
+ $this->start_controls_section(
+ 'style_title',
+ [
+ 'label' => __('Title', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'title_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#1a202c',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-toc__title' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'title_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-toc__title',
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'title_margin',
+ [
+ 'label' => __('Margin Bottom', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => [
+ 'px' => ['min' => 0, 'max' => 50],
+ ],
+ 'default' => ['size' => 15],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-toc__title' => 'margin-bottom: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - List Items
+ $this->start_controls_section(
+ 'style_items',
+ [
+ 'label' => __('List Items', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'link_color',
+ [
+ 'label' => __('Link Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#4a5568',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-toc__link' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'link_hover_color',
+ [
+ 'label' => __('Link Hover Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-toc__link:hover' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'active_color',
+ [
+ 'label' => __('Active Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-toc__link.active' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'active_border_color',
+ [
+ 'label' => __('Active Border Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-toc__link.active' => 'border-left-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'link_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-toc__link',
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'item_spacing',
+ [
+ 'label' => __('Item Spacing', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => [
+ 'px' => ['min' => 0, 'max' => 30],
+ ],
+ 'default' => ['size' => 8],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-toc__item' => 'margin-bottom: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'indent',
+ [
+ 'label' => __('Sub-item Indent', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => [
+ 'px' => ['min' => 0, 'max' => 50],
+ ],
+ 'default' => ['size' => 16],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-toc__list .wedocs-toc__list' => 'padding-left: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ protected function render() {
+ $settings = $this->get_settings_for_display();
+
+ $title = $settings['title'] ?? __('On This Page', 'wedocs');
+ $title_tag = $settings['title_tag'] ?? 'h3';
+ $heading_levels = $settings['heading_levels'] ?? ['2', '3'];
+ $collapsible = ($settings['collapsible'] ?? '') === 'yes';
+ $collapsed_default = ($settings['collapsed_default'] ?? '') === 'yes';
+ $sticky = ($settings['sticky'] ?? '') === 'yes';
+ $sticky_offset = $settings['sticky_offset']['size'] ?? 20;
+ $show_numbers = ($settings['show_numbers'] ?? '') === 'yes';
+ $smooth_scroll = ($settings['smooth_scroll'] ?? 'yes') === 'yes';
+ $highlight_active = ($settings['highlight_active'] ?? 'yes') === 'yes';
+
+ $selector = implode(',', array_map(function ($level) {
+ return 'h' . intval($level);
+ }, $heading_levels));
+
+ // Build heading regex pattern from selected levels
+ $level_pattern = implode('|', array_map('intval', $heading_levels));
+
+ // Extract headings from the current post content (server-side)
+ $headings = [];
+ global $post;
+ if (!empty($post->post_content)) {
+ $content = apply_filters('the_content', $post->post_content);
+ if (preg_match_all('/]*(?:\s+id=["\']([^"\']*)["\'])?[^>]*>(.*?)<\/h\1>/si', $content, $matches, PREG_SET_ORDER)) {
+ $counter = 0;
+ foreach ($matches as $match) {
+ $counter++;
+ $level = intval($match[1]);
+ $id = !empty($match[2]) ? $match[2] : 'wedocs-heading-' . $counter;
+ $text = wp_strip_all_tags($match[3]);
+ if (!empty(trim($text))) {
+ $headings[] = [
+ 'level' => $level,
+ 'id' => $id,
+ 'text' => $text,
+ 'index' => $counter,
+ ];
+ }
+ }
+ }
+ }
+
+ $wrapper_class = 'wedocs-toc';
+ if ($sticky) {
+ $wrapper_class .= ' wedocs-toc--sticky';
+ }
+ if ($collapsible) {
+ $wrapper_class .= ' wedocs-toc--collapsible';
+ }
+ if ($collapsed_default) {
+ $wrapper_class .= ' wedocs-toc--collapsed';
+ }
+
+ // Determine minimum heading level for indentation
+ $min_level = !empty($headings) ? min(array_column($headings, 'level')) : 2;
+ ?>
+
+ style="position: sticky; top: px;">
+
+
+
+
style="display: none;">
+
+
+
+
+
+
+
+
+ <#
+ var titleTag = settings.title_tag || 'h3';
+ var collapsible = settings.collapsible === 'yes';
+ var collapsed = settings.collapsed_default === 'yes';
+ var sticky = settings.sticky === 'yes';
+ var stickyOffset = settings.sticky_offset?.size || 20;
+ var showNumbers = settings.show_numbers === 'yes';
+
+ var wrapperClass = 'wedocs-toc';
+ if (sticky) wrapperClass += ' wedocs-toc--sticky';
+ if (collapsible) wrapperClass += ' wedocs-toc--collapsible';
+ #>
+
+ style="position: sticky; top: {{ stickyOffset }}px;"<# } #>>
+
+
+
+
+ <# var sampleItems = ['Getting Started', 'Installation', 'Configuration', 'Basic Usage', 'Advanced Features', 'API Reference'];
+ for (var i = 0; i < sampleItems.length; i++) {
+ var depth = (i === 2 || i === 3) ? 1 : 0;
+ var numberHtml = showNumbers ? '' + (i+1) + '. ' : '';
+ #>
+
+ {{{ numberHtml }}}{{ sampleItems[i] }}
+
+ <# } #>
+
+
+
+ start_controls_section(
+ 'content_section',
+ [
+ 'label' => __('Content', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_CONTENT,
+ ]
+ );
+
+ $this->add_control(
+ 'question_text',
+ [
+ 'label' => __('Question Text', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Was this article helpful?', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'style',
+ [
+ 'label' => __('Style', 'wedocs'),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'thumbs',
+ 'options' => [
+ 'thumbs' => __('Thumbs Up/Down', 'wedocs'),
+ 'emoji' => __('Emoji Reactions', 'wedocs'),
+ 'yes_no' => __('Yes/No Buttons', 'wedocs'),
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'yes_text',
+ [
+ 'label' => __('Positive Text', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Yes', 'wedocs'),
+ 'condition' => ['style' => 'yes_no'],
+ ]
+ );
+
+ $this->add_control(
+ 'no_text',
+ [
+ 'label' => __('Negative Text', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('No', 'wedocs'),
+ 'condition' => ['style' => 'yes_no'],
+ ]
+ );
+
+ $this->add_control(
+ 'show_count',
+ [
+ 'label' => __('Show Vote Count', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'return_value' => 'yes',
+ 'default' => '',
+ ]
+ );
+
+ $this->add_control(
+ 'thank_you_message',
+ [
+ 'label' => __('Thank You Message', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Thank you for your feedback!', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'negative_follow_up',
+ [
+ 'label' => __('Negative Feedback Follow-up', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'return_value' => 'yes',
+ 'default' => '',
+ 'description' => __('Show a text field when negative feedback is given', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'follow_up_placeholder',
+ [
+ 'label' => __('Follow-up Placeholder', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('How can we improve this article?', 'wedocs'),
+ 'condition' => ['negative_follow_up' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'alignment',
+ [
+ 'label' => __('Alignment', 'wedocs'),
+ 'type' => Controls_Manager::CHOOSE,
+ 'options' => [
+ 'left' => ['title' => __('Left', 'wedocs'), 'icon' => 'eicon-text-align-left'],
+ 'center' => ['title' => __('Center', 'wedocs'), 'icon' => 'eicon-text-align-center'],
+ 'right' => ['title' => __('Right', 'wedocs'), 'icon' => 'eicon-text-align-right'],
+ ],
+ 'default' => 'center',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful' => 'text-align: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Container
+ $this->start_controls_section(
+ 'style_container',
+ [
+ 'label' => __('Container', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'bg_color',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#f8f9fa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'padding',
+ [
+ 'label' => __('Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%', 'em'],
+ 'default' => ['top' => 20, 'right' => 25, 'bottom' => 20, 'left' => 25, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'container_border',
+ 'selector' => '{{WRAPPER}} .wedocs-helpful',
+ 'fields_options' => [
+ 'border' => ['default' => 'solid'],
+ 'width' => ['default' => ['top' => 1, 'right' => 1, 'bottom' => 1, 'left' => 1]],
+ 'color' => ['default' => '#e2e8f0'],
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'border_radius',
+ [
+ 'label' => __('Border Radius', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%'],
+ 'default' => ['top' => 8, 'right' => 8, 'bottom' => 8, 'left' => 8, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Question
+ $this->start_controls_section(
+ 'style_question',
+ [
+ 'label' => __('Question Text', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'question_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#1a202c',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful__question' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'question_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-helpful__question',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Buttons
+ $this->start_controls_section(
+ 'style_buttons',
+ [
+ 'label' => __('Vote Buttons', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'btn_color',
+ [
+ 'label' => __('Button Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#718096',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful__btn' => 'color: {{VALUE}}; border-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'btn_hover_color',
+ [
+ 'label' => __('Hover Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful__btn:hover' => 'color: {{VALUE}}; border-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'btn_positive_active',
+ [
+ 'label' => __('Positive Active Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#10b981',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful__btn--positive.active' => 'color: {{VALUE}}; border-color: {{VALUE}}; background-color: color-mix(in srgb, {{VALUE}} 10%, transparent);',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'btn_negative_active',
+ [
+ 'label' => __('Negative Active Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#ef4444',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful__btn--negative.active' => 'color: {{VALUE}}; border-color: {{VALUE}}; background-color: color-mix(in srgb, {{VALUE}} 10%, transparent);',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'btn_size',
+ [
+ 'label' => __('Button Size', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 24, 'max' => 80]],
+ 'default' => ['size' => 44],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful__btn' => 'width: {{SIZE}}px; height: {{SIZE}}px;',
+ '{{WRAPPER}} .wedocs-helpful__btn--text' => 'width: auto; height: auto;',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'btn_icon_size',
+ [
+ 'label' => __('Icon Size', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 14, 'max' => 48]],
+ 'default' => ['size' => 22],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful__btn svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;',
+ '{{WRAPPER}} .wedocs-helpful__btn .wedocs-helpful__emoji' => 'font-size: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'btn_gap',
+ [
+ 'label' => __('Button Spacing', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 4, 'max' => 30]],
+ 'default' => ['size' => 10],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-helpful__actions' => 'gap: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ protected function render() {
+ $settings = $this->get_settings_for_display();
+
+ $style = $settings['style'] ?? 'thumbs';
+ $show_count = ($settings['show_count'] ?? '') === 'yes';
+ $negative_follow_up = ($settings['negative_follow_up'] ?? '') === 'yes';
+ $widget_id = $this->get_id();
+ $post_id = get_the_ID();
+
+ // Get existing vote counts
+ $positive_count = (int) get_post_meta($post_id, '_wedocs_helpful_yes', true);
+ $negative_count = (int) get_post_meta($post_id, '_wedocs_helpful_no', true);
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 👍
+
+
+
+ 👎
+
+
+
+
+
+
+ ()
+
+
+
+ ()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <#
+ var style = settings.style || 'thumbs';
+ var showCount = settings.show_count === 'yes';
+ #>
+
+
+
{{ settings.question_text }}
+
+
+ <# if (style === 'thumbs') { #>
+
+
+ <# if (showCount) { #>12 <# } #>
+
+
+
+ <# if (showCount) { #>3 <# } #>
+
+ <# } else if (style === 'emoji') { #>
+
+ 👍
+ <# if (showCount) { #>12 <# } #>
+
+
+ 👎
+ <# if (showCount) { #>3 <# } #>
+
+ <# } else if (style === 'yes_no') { #>
+
+ {{ settings.yes_text || 'Yes' }}
+ <# if (showCount) { #>(12) <# } #>
+
+
+ {{ settings.no_text || 'No' }}
+ <# if (showCount) { #>(3) <# } #>
+
+ <# } #>
+
+
+
Date: Wed, 18 Feb 2026 12:04:54 +0600
Subject: [PATCH 2/4] Add Elementor widgets: nav, breadcrumb, menu
Register and include three new Elementor widgets (DocNavigation, DocsBreadcrumb, DocsHamburgerMenu) by updating includes/Elementor.php. Add full widget implementations for next/previous doc navigation, docs breadcrumb, and an off-canvas/hamburger docs menu including controls, rendering, editor preview templates and inline styles. Also adjust responsive styles in src/assets/less/responsive.less to support the new widgets.
---
includes/Elementor.php | 6 +
includes/Elementor/Widgets/DocNavigation.php | 577 ++++++++++++++
includes/Elementor/Widgets/DocsBreadcrumb.php | 508 ++++++++++++
.../Elementor/Widgets/DocsHamburgerMenu.php | 749 ++++++++++++++++++
src/assets/less/responsive.less | 73 ++
5 files changed, 1913 insertions(+)
create mode 100644 includes/Elementor/Widgets/DocNavigation.php
create mode 100644 includes/Elementor/Widgets/DocsBreadcrumb.php
create mode 100644 includes/Elementor/Widgets/DocsHamburgerMenu.php
diff --git a/includes/Elementor.php b/includes/Elementor.php
index a62fae37..d34b9c40 100644
--- a/includes/Elementor.php
+++ b/includes/Elementor.php
@@ -49,6 +49,9 @@ public function register_widgets() {
require_once WEDOCS_PATH . '/includes/Elementor/Widgets/WasThisHelpful.php';
require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocsSidebar.php';
require_once WEDOCS_PATH . '/includes/Elementor/Widgets/SearchModal.php';
+ require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocNavigation.php';
+ require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocsHamburgerMenu.php';
+ require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocsBreadcrumb.php';
// Register widgets
// \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\Search() );
@@ -58,6 +61,9 @@ public function register_widgets() {
\Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\WasThisHelpful() );
\Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsSidebar() );
\Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\SearchModal() );
+ \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocNavigation() );
+ \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsHamburgerMenu() );
+ \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsBreadcrumb() );
}
/**
diff --git a/includes/Elementor/Widgets/DocNavigation.php b/includes/Elementor/Widgets/DocNavigation.php
new file mode 100644
index 00000000..7c4577a7
--- /dev/null
+++ b/includes/Elementor/Widgets/DocNavigation.php
@@ -0,0 +1,577 @@
+start_controls_section(
+ 'content_section',
+ [
+ 'label' => __('Content', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_CONTENT,
+ ]
+ );
+
+ $this->add_control(
+ 'show_prev',
+ [
+ 'label' => __('Show Previous', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'show_next',
+ [
+ 'label' => __('Show Next', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'prev_label',
+ [
+ 'label' => __('Previous Label', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Previous', 'wedocs'),
+ 'condition' => ['show_prev' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'next_label',
+ [
+ 'label' => __('Next Label', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Next', 'wedocs'),
+ 'condition' => ['show_next' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'show_arrows',
+ [
+ 'label' => __('Show Arrows', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'layout',
+ [
+ 'label' => __('Layout', 'wedocs'),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'side-by-side',
+ 'options' => [
+ 'side-by-side' => __('Side by Side', 'wedocs'),
+ 'stacked' => __('Stacked', 'wedocs'),
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Container
+ $this->start_controls_section(
+ 'style_container',
+ [
+ 'label' => __('Container', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'bg_color',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-nav' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'container_padding',
+ [
+ 'label' => __('Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%', 'em'],
+ 'default' => ['top' => 20, 'right' => 0, 'bottom' => 20, 'left' => 0, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-nav' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'container_border',
+ 'selector' => '{{WRAPPER}} .wedocs-el-nav',
+ 'fields_options' => [
+ 'border' => ['default' => 'solid'],
+ 'width' => ['default' => ['top' => 1, 'right' => 0, 'bottom' => 1, 'left' => 0]],
+ 'color' => ['default' => '#e2e8f0'],
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'container_border_radius',
+ [
+ 'label' => __('Border Radius', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-nav' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Box_Shadow::get_type(),
+ [
+ 'name' => 'container_shadow',
+ 'selector' => '{{WRAPPER}} .wedocs-el-nav',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Label
+ $this->start_controls_section(
+ 'style_label',
+ [
+ 'label' => __('Label', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'label_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#94a3b8',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-nav__label' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'label_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-el-nav__label',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Title
+ $this->start_controls_section(
+ 'style_title',
+ [
+ 'label' => __('Doc Title', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'title_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#1e293b',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-nav__title a' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'title_hover_color',
+ [
+ 'label' => __('Hover Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-nav__title a:hover' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'title_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-el-nav__title',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Arrow
+ $this->start_controls_section(
+ 'style_arrow',
+ [
+ 'label' => __('Arrow', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ 'condition' => ['show_arrows' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'arrow_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#94a3b8',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-nav__arrow' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'arrow_size',
+ [
+ 'label' => __('Size', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 12, 'max' => 40]],
+ 'default' => ['size' => 20],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-nav__arrow svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Separator
+ $this->start_controls_section(
+ 'style_separator',
+ [
+ 'label' => __('Separator', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'separator_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#e2e8f0',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-nav--side-by-side .wedocs-el-nav__separator' => 'background-color: {{VALUE}};',
+ '{{WRAPPER}} .wedocs-el-nav--stacked .wedocs-el-nav__item + .wedocs-el-nav__item' => 'border-top-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'separator_width',
+ [
+ 'label' => __('Width', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 0, 'max' => 5]],
+ 'default' => ['size' => 1],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-nav--side-by-side .wedocs-el-nav__separator' => 'width: {{SIZE}}px;',
+ '{{WRAPPER}} .wedocs-el-nav--stacked .wedocs-el-nav__item + .wedocs-el-nav__item' => 'border-top-width: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ protected function render() {
+ $settings = $this->get_settings_for_display();
+
+ $show_prev = ($settings['show_prev'] ?? 'yes') === 'yes';
+ $show_next = ($settings['show_next'] ?? 'yes') === 'yes';
+ $prev_label = $settings['prev_label'] ?? __('Previous', 'wedocs');
+ $next_label = $settings['next_label'] ?? __('Next', 'wedocs');
+ $show_arrows = ($settings['show_arrows'] ?? 'yes') === 'yes';
+ $layout = $settings['layout'] ?? 'side-by-side';
+
+ global $post, $wpdb;
+
+ if (empty($post) || $post->post_type !== 'docs') {
+ if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
+ echo '' . __('Doc Navigation: Preview it on a single doc page.', 'wedocs') . '
';
+ }
+ return;
+ }
+
+ $next_post_id = 0;
+ $prev_post_id = 0;
+
+ if ($show_next) {
+ $next_query = "SELECT ID FROM {$wpdb->posts}
+ WHERE post_parent = {$post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order > {$post->menu_order}
+ ORDER BY menu_order ASC
+ LIMIT 0, 1";
+ $next_post_id = (int) $wpdb->get_var($next_query);
+ }
+
+ if ($show_prev) {
+ $prev_query = "SELECT ID FROM {$wpdb->posts}
+ WHERE post_parent = {$post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order < {$post->menu_order}
+ ORDER BY menu_order DESC
+ LIMIT 0, 1";
+ $prev_post_id = (int) $wpdb->get_var($prev_query);
+ }
+
+ if (!$next_post_id && !$prev_post_id) {
+ if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
+ echo '' . __('Doc Navigation: No adjacent docs found.', 'wedocs') . '
';
+ }
+ return;
+ }
+
+ $nav_class = 'wedocs-el-nav wedocs-el-nav--' . $layout;
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <#
+ var showPrev = settings.show_prev === 'yes';
+ var showNext = settings.show_next === 'yes';
+ var showArrows = settings.show_arrows === 'yes';
+ var layout = settings.layout || 'side-by-side';
+ var prevLabel = settings.prev_label || 'Previous';
+ var nextLabel = settings.next_label || 'Next';
+ var arrowColor = settings.arrow_color || '#94a3b8';
+ var labelColor = settings.label_color || '#94a3b8';
+ var titleColor = settings.title_color || '#1e293b';
+ var arrowSize = settings.arrow_size?.size || 20;
+ #>
+
+
+ <# if (showPrev) { #>
+
+ <# } #>
+
+ <# if (showPrev && showNext && layout === 'side-by-side') { #>
+
+ <# } #>
+
+ <# if (showPrev && showNext && layout === 'stacked') { #>
+
+ <# } #>
+
+ <# if (showNext) { #>
+
+ <# } #>
+
+ start_controls_section(
+ 'content_section',
+ [
+ 'label' => __('Content', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_CONTENT,
+ ]
+ );
+
+ $this->add_control(
+ 'home_text',
+ [
+ 'label' => __('Home Text', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Home', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'show_home_icon',
+ [
+ 'label' => __('Show Home Icon', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'separator',
+ [
+ 'label' => __('Separator', 'wedocs'),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'angle',
+ 'options' => [
+ 'angle' => '›',
+ 'slash' => '/',
+ 'arrow' => '→',
+ 'dot' => '·',
+ 'dash' => '—',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'truncate_length',
+ [
+ 'label' => __('Max Characters per Item', 'wedocs'),
+ 'type' => Controls_Manager::NUMBER,
+ 'default' => 0,
+ 'min' => 0,
+ 'max' => 100,
+ 'description' => __('0 = no truncation', 'wedocs'),
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Container
+ $this->start_controls_section(
+ 'style_container',
+ [
+ 'label' => __('Container', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'bg_color',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-breadcrumb' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'container_padding',
+ [
+ 'label' => __('Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', 'em'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-breadcrumb' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'item_gap',
+ [
+ 'label' => __('Item Spacing', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 2, 'max' => 20]],
+ 'default' => ['size' => 8],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-breadcrumb__list' => 'gap: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Links
+ $this->start_controls_section(
+ 'style_links',
+ [
+ 'label' => __('Links', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'link_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#64748b',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-breadcrumb__link' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'link_hover_color',
+ [
+ 'label' => __('Hover Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-breadcrumb__link:hover' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'link_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-el-breadcrumb__link, {{WRAPPER}} .wedocs-el-breadcrumb__current',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Current Item
+ $this->start_controls_section(
+ 'style_current',
+ [
+ 'label' => __('Current Item', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'current_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#1e293b',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-breadcrumb__current' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'current_font_weight',
+ [
+ 'label' => __('Font Weight', 'wedocs'),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => '600',
+ 'options' => [
+ '400' => __('Normal', 'wedocs'),
+ '500' => __('Medium', 'wedocs'),
+ '600' => __('Semi Bold', 'wedocs'),
+ '700' => __('Bold', 'wedocs'),
+ ],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-breadcrumb__current' => 'font-weight: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Separator
+ $this->start_controls_section(
+ 'style_separator',
+ [
+ 'label' => __('Separator', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'separator_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#cbd5e1',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-breadcrumb__sep' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'separator_size',
+ [
+ 'label' => __('Size', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 10, 'max' => 24]],
+ 'default' => ['size' => 14],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-breadcrumb__sep' => 'font-size: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Home Icon
+ $this->start_controls_section(
+ 'style_home_icon',
+ [
+ 'label' => __('Home Icon', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ 'condition' => ['show_home_icon' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'home_icon_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#94a3b8',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-breadcrumb__home-icon svg' => 'fill: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'home_icon_size',
+ [
+ 'label' => __('Size', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 12, 'max' => 24]],
+ 'default' => ['size' => 16],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-breadcrumb__home-icon svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ protected function render() {
+ $settings = $this->get_settings_for_display();
+
+ $home_text = $settings['home_text'] ?? __('Home', 'wedocs');
+ $show_home_icon = ($settings['show_home_icon'] ?? 'yes') === 'yes';
+ $separator = $settings['separator'] ?? 'angle';
+ $truncate = absint($settings['truncate_length'] ?? 0);
+
+ $separators = [
+ 'angle' => '›',
+ 'slash' => '/',
+ 'arrow' => '→',
+ 'dot' => '·',
+ 'dash' => '—',
+ ];
+ $sep_char = $separators[$separator] ?? '›';
+
+ global $post;
+
+ if (empty($post) || $post->post_type !== 'docs') {
+ if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
+ echo '' . __('Docs Breadcrumb: Preview it on a single doc page.', 'wedocs') . '
';
+ }
+ return;
+ }
+
+ // Build breadcrumb items
+ $items = [];
+
+ // Home
+ $items[] = [
+ 'label' => $home_text,
+ 'url' => home_url('/'),
+ 'home' => true,
+ ];
+
+ // Docs home page
+ $docs_home = wedocs_get_general_settings('docs_home');
+ if ($docs_home) {
+ $items[] = [
+ 'label' => __('Docs', 'wedocs'),
+ 'url' => get_permalink($docs_home),
+ ];
+ }
+
+ // Parent hierarchy
+ if ($post->post_parent) {
+ $parent_id = $post->post_parent;
+ $parents = [];
+
+ while ($parent_id) {
+ $page = get_post($parent_id);
+ $parents[] = [
+ 'label' => get_the_title($page->ID),
+ 'url' => get_permalink($page->ID),
+ ];
+ $parent_id = $page->post_parent;
+ }
+
+ $items = array_merge($items, array_reverse($parents));
+ }
+
+ // Current page (no link)
+ $items[] = [
+ 'label' => get_the_title(),
+ 'current' => true,
+ ];
+
+ ?>
+
+
+ $item):
+ $is_current = !empty($item['current']);
+ $is_home = !empty($item['home']);
+ $label = $item['label'];
+ if ($truncate > 0 && mb_strlen($label) > $truncate && !$is_current) {
+ $label = mb_substr($label, 0, $truncate) . '…';
+ }
+ ?>
+ 0): ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <#
+ var homeText = settings.home_text || 'Home';
+ var showHomeIcon = settings.show_home_icon === 'yes';
+ var separator = settings.separator || 'angle';
+ var linkColor = settings.link_color || '#64748b';
+ var currentColor = settings.current_color || '#1e293b';
+ var sepColor = settings.separator_color || '#cbd5e1';
+ var sepSize = settings.separator_size?.size || 14;
+ var iconColor = settings.home_icon_color || '#94a3b8';
+ var iconSize = settings.home_icon_size?.size || 16;
+ var currentWeight = settings.current_font_weight || '600';
+
+ var seps = { angle: '›', slash: '/', arrow: '→', dot: '·', dash: '—' };
+ var sepChar = seps[separator] || '›';
+
+ var items = [
+ { label: homeText, home: true },
+ { label: 'Documentation' },
+ { label: 'Getting Started' },
+ { label: 'Installation Guide', current: true }
+ ];
+ #>
+
+
+
+ <# for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ if (i > 0) { #>
+ {{ sepChar }}
+ <# } #>
+
+ <# if (item.current) { #>
+ {{ item.label }}
+ <# } else { #>
+
+
+ <# if (item.home && showHomeIcon) { #>
+
+
+
+ <# } #>
+ {{ item.label }}
+
+
+ <# } #>
+ <# } #>
+
+
+ start_controls_section(
+ 'content_section',
+ [
+ 'label' => __('Content', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_CONTENT,
+ ]
+ );
+
+ $this->add_control(
+ 'icon_type',
+ [
+ 'label' => __('Trigger Icon', 'wedocs'),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'bars',
+ 'options' => [
+ 'bars' => __('Hamburger Bars', 'wedocs'),
+ 'dots' => __('Dots', 'wedocs'),
+ 'menu_text' => __('Menu + Icon', 'wedocs'),
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'panel_position',
+ [
+ 'label' => __('Panel Position', 'wedocs'),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'left',
+ 'options' => [
+ 'left' => __('Left', 'wedocs'),
+ 'right' => __('Right', 'wedocs'),
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'show_search',
+ [
+ 'label' => __('Show Quick Search', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->add_control(
+ 'search_placeholder',
+ [
+ 'label' => __('Search Placeholder', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Quick search...', 'wedocs'),
+ 'condition' => ['show_search' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'show_title',
+ [
+ 'label' => __('Show Doc Title', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Trigger Button
+ $this->start_controls_section(
+ 'style_trigger',
+ [
+ 'label' => __('Trigger Button', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_color',
+ [
+ 'label' => __('Icon Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#1e293b',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__trigger' => 'color: {{VALUE}};',
+ '{{WRAPPER}} .wedocs-hamburger__trigger svg' => 'fill: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'trigger_bg',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__trigger' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'trigger_size',
+ [
+ 'label' => __('Icon Size', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 16, 'max' => 48]],
+ 'default' => ['size' => 24],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__trigger svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'trigger_padding',
+ [
+ 'label' => __('Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px'],
+ 'default' => ['top' => 8, 'right' => 8, 'bottom' => 8, 'left' => 8, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__trigger' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'trigger_border_radius',
+ [
+ 'label' => __('Border Radius', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', '%'],
+ 'default' => ['top' => 6, 'right' => 6, 'bottom' => 6, 'left' => 6, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__trigger' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Panel
+ $this->start_controls_section(
+ 'style_panel',
+ [
+ 'label' => __('Panel', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'panel_bg',
+ [
+ 'label' => __('Background Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#ffffff',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__panel' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'panel_width',
+ [
+ 'label' => __('Width', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 240, 'max' => 500]],
+ 'default' => ['size' => 320],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__panel' => 'width: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'panel_padding',
+ [
+ 'label' => __('Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', 'em'],
+ 'default' => ['top' => 20, 'right' => 20, 'bottom' => 20, 'left' => 20, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__panel' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Box_Shadow::get_type(),
+ [
+ 'name' => 'panel_shadow',
+ 'selector' => '{{WRAPPER}} .wedocs-hamburger__panel',
+ 'fields_options' => [
+ 'box_shadow_type' => ['default' => 'yes'],
+ 'box_shadow' => ['default' => ['horizontal' => 4, 'vertical' => 0, 'blur' => 20, 'spread' => 0, 'color' => 'rgba(0,0,0,0.15)']],
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'overlay_color',
+ [
+ 'label' => __('Overlay Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => 'rgba(0,0,0,0.4)',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__overlay' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Title
+ $this->start_controls_section(
+ 'style_title',
+ [
+ 'label' => __('Doc Title', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ 'condition' => ['show_title' => 'yes'],
+ ]
+ );
+
+ $this->add_control(
+ 'title_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#1e293b',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__title' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'title_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-hamburger__title',
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Navigation Items
+ $this->start_controls_section(
+ 'style_nav',
+ [
+ 'label' => __('Navigation Items', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'link_color',
+ [
+ 'label' => __('Link Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#475569',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__nav a' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'link_hover_color',
+ [
+ 'label' => __('Hover Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__nav a:hover' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'active_color',
+ [
+ 'label' => __('Active Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#0073aa',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__nav .current_page_item > a' => 'color: {{VALUE}}; font-weight: 600;',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'link_typography',
+ 'selector' => '{{WRAPPER}} .wedocs-hamburger__nav a',
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'item_padding',
+ [
+ 'label' => __('Item Padding', 'wedocs'),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => ['px', 'em'],
+ 'default' => ['top' => 8, 'right' => 0, 'bottom' => 8, 'left' => 0, 'unit' => 'px'],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__nav a' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Section - Close Button
+ $this->start_controls_section(
+ 'style_close',
+ [
+ 'label' => __('Close Button', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'close_color',
+ [
+ 'label' => __('Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#64748b',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__close' => 'color: {{VALUE}};',
+ '{{WRAPPER}} .wedocs-hamburger__close svg' => 'fill: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'close_size',
+ [
+ 'label' => __('Size', 'wedocs'),
+ 'type' => Controls_Manager::SLIDER,
+ 'range' => ['px' => ['min' => 16, 'max' => 40]],
+ 'default' => ['size' => 24],
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-hamburger__close svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ protected function render() {
+ $settings = $this->get_settings_for_display();
+
+ $icon_type = $settings['icon_type'] ?? 'bars';
+ $panel_position = $settings['panel_position'] ?? 'left';
+ $show_search = ($settings['show_search'] ?? 'yes') === 'yes';
+ $search_placeholder = $settings['search_placeholder'] ?? __('Quick search...', 'wedocs');
+ $show_title = ($settings['show_title'] ?? 'yes') === 'yes';
+
+ global $post;
+
+ // Determine the parent doc
+ $ancestors = [];
+ $parent = false;
+
+ if (!empty($post->post_parent)) {
+ $ancestors = get_post_ancestors($post->ID);
+ $root = count($ancestors) - 1;
+ $parent = $ancestors[$root];
+ } else {
+ $parent = !empty($post->ID) ? $post->ID : '';
+ }
+
+ if (!$parent) {
+ if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
+ echo '' . __('Hamburger Menu: Preview it on a single doc page.', 'wedocs') . '
';
+ }
+ return;
+ }
+
+ $walker = new \WeDevs\WeDocs\Walker();
+ $children = wp_list_pages([
+ 'title_li' => '',
+ 'order' => 'menu_order',
+ 'child_of' => $parent,
+ 'echo' => false,
+ 'post_type' => 'docs',
+ 'walker' => $walker,
+ ]);
+
+ $widget_id = $this->get_id();
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <#
+ var iconType = settings.icon_type || 'bars';
+ var triggerColor = settings.trigger_color || '#1e293b';
+ var triggerBg = settings.trigger_bg || '';
+ #>
+
+
+ <# if (iconType === 'bars') { #>
+
+ <# } else if (iconType === 'dots') { #>
+
+ <# } else if (iconType === 'menu_text') { #>
+
+ Menu
+ <# } #>
+
+
+
+ Off-canvas panel opens on the frontend when clicked. Position: {{ settings.panel_position || 'left' }}.
+
+
Date: Wed, 18 Feb 2026 13:43:15 +0600
Subject: [PATCH 3/4] Unify feedback meta keys and Elementor previews
Switch feedback storage to unified 'positive'/'negative' meta keys (Ajax, admin metabox, list table) and update code to read/write those keys. Add editor-aware context and preview rendering for Elementor widgets (DocNavigation, DocsBreadcrumb, DocsSidebar), plus new responsive controls (mobile stacking/toggle/hamburger) and related CSS for better editor UX and mobile behavior. Include a new three_column Elementor template and multiple formatting/whitespace cleanups across API and admin code. These changes improve consistency of feedback data and provide accurate previews in Elementor editor.
---
includes/API/API.php | 7 +-
includes/Admin/Docs_List_Table.php | 72 +--
includes/Ajax.php | 6 +-
.../Elementor/Templates/three_column.json | 1 +
includes/Elementor/Widgets/DocNavigation.php | 268 +++++++---
includes/Elementor/Widgets/DocsBreadcrumb.php | 209 ++++++--
includes/Elementor/Widgets/DocsSidebar.php | 497 +++++++++++++++---
.../Elementor/Widgets/TableOfContents.php | 350 ++++++++++--
includes/Elementor/Widgets/WasThisHelpful.php | 23 +-
9 files changed, 1161 insertions(+), 272 deletions(-)
create mode 100644 includes/Elementor/Templates/three_column.json
diff --git a/includes/API/API.php b/includes/API/API.php
index 67edd1dd..3508df69 100644
--- a/includes/API/API.php
+++ b/includes/API/API.php
@@ -756,8 +756,9 @@ public function get_helpful_docs() {
continue;
}
- $positive = (int) get_post_meta( $doc->ID, 'positive', true );
- $negative = (int) get_post_meta( $doc->ID, 'negative', true );
+ // Get feedback counts
+ $positive = (int) get_post_meta($doc->ID, 'positive', true);
+ $negative = (int) get_post_meta($doc->ID, 'negative', true);
if ( empty( $positive ) && empty( $negative ) ) {
continue;
}
@@ -1231,7 +1232,7 @@ public function get_promotional_notice() {
return false;
}
- /**
+ /**
* Handle promotional notice hidden action
*
* @since 2.1.11
diff --git a/includes/Admin/Docs_List_Table.php b/includes/Admin/Docs_List_Table.php
index 1a9bed30..8b903442 100644
--- a/includes/Admin/Docs_List_Table.php
+++ b/includes/Admin/Docs_List_Table.php
@@ -11,49 +11,59 @@ class Docs_List_Table {
* Constructor
*/
public function __construct() {
- add_filter( 'manage_docs_posts_columns', [ $this, 'docs_list_columns' ] );
- add_action( 'manage_docs_posts_custom_column', [ $this, 'docs_list_columns_row' ], 10, 2 );
- add_filter( 'manage_edit-docs_sortable_columns', [ $this, 'docs_sortable_columns' ] );
+ add_filter('manage_docs_posts_columns', [$this, 'docs_list_columns']);
+ add_action('manage_docs_posts_custom_column', [$this, 'docs_list_columns_row'], 10, 2);
+ add_filter('manage_edit-docs_sortable_columns', [$this, 'docs_sortable_columns']);
- add_action( 'load-edit.php', [ $this, 'edit_docs_load' ] );
- add_action( 'load-post.php', [ $this, 'add_meta_box' ] );
+ add_action('load-edit.php', [$this, 'edit_docs_load']);
+ add_action('load-post.php', [$this, 'add_meta_box']);
// load css
- add_action( 'admin_print_styles-post.php', [ $this, 'helpfulness_css' ] );
- add_action( 'admin_print_styles-edit.php', [ $this, 'helpfulness_css' ] );
+ add_action('admin_print_styles-post.php', [$this, 'helpfulness_css']);
+ add_action('admin_print_styles-edit.php', [$this, 'helpfulness_css']);
}
public function add_meta_box() {
- add_meta_box( 'op-menu-meta-box-id', __( 'Helpfulness', 'wedocs' ), [ $this, 'helpfulness_metabox' ], 'docs', 'side', 'core' );
+ add_meta_box('op-menu-meta-box-id', __('Helpfulness', 'wedocs'), [$this, 'helpfulness_metabox'], 'docs', 'side', 'core');
}
public function helpfulness_css() {
- if ( 'docs' != get_current_screen()->post_type ) {
+ if ('docs' != get_current_screen()->post_type) {
return;
} ?>
-
+ global $post;
+
+ $positive = (int) get_post_meta($post->ID, 'positive', true);
+ $negative = (int) get_post_meta($post->ID, 'negative', true);
+ ?>
- ID, 'positive', true ) ); ?>
+
- ID, 'negative', true ) ); ?>
+
- __( 'Votes', 'wedocs' ) ];
+ public function docs_list_columns($columns) {
+ $vote = ['votes' => __('Votes', 'wedocs')];
// insert before last element, date
- $first_items = array_splice( $columns, 0, 3 ); // remove first 3 items and store to $first_items, date remains to $columns
- $new_columns = array_merge( $first_items, $vote, $columns ); // merge all those
+ $first_items = array_splice($columns, 0, 3); // remove first 3 items and store to $first_items, date remains to $columns
+ $new_columns = array_merge($first_items, $vote, $columns); // merge all those
return $new_columns;
}
- public function docs_sortable_columns( $columns ) {
- $columns['votes'] = [ 'votes', true ];
+ public function docs_sortable_columns($columns) {
+ $columns['votes'] = ['votes', true];
return $columns;
}
- public function docs_list_columns_row( $column_name, $post_id ) {
- if ( 'votes' == $column_name ) {
- $positive = get_post_meta( $post_id, 'positive', true );
- $negative = get_post_meta( $post_id, 'negative', true );
+ public function docs_list_columns_row($column_name, $post_id) {
+ if ('votes' == $column_name) {
+ $positive = get_post_meta($post_id, 'positive', true);
+ $negative = get_post_meta($post_id, 'negative', true);
- printf( '%d /%d ', $positive, $negative );
+ printf('%d /%d ', $positive, $negative);
}
}
public function edit_docs_load() {
- add_filter( 'request', [ $this, 'sort_docs' ] );
+ add_filter('request', [$this, 'sort_docs']);
}
// Sorts the movies.
- public function sort_docs( $vars ) {
+ public function sort_docs($vars) {
// Check if we're viewing the 'movie' post type.
- if ( isset( $vars['post_type'] ) && 'docs' == $vars['post_type'] ) {
+ if (isset($vars['post_type']) && 'docs' == $vars['post_type']) {
// Check if 'orderby' is set to 'duration'.
- if ( isset( $vars['orderby'] ) && 'votes' == $vars['orderby'] ) {
+ if (isset($vars['orderby']) && 'votes' == $vars['orderby']) {
$vars = array_merge(
$vars,
[
diff --git a/includes/Ajax.php b/includes/Ajax.php
index 6ad3270c..7104c21f 100644
--- a/includes/Ajax.php
+++ b/includes/Ajax.php
@@ -600,13 +600,13 @@ public function handle_helpful_vote() {
wp_send_json_error(['message' => __('Invalid vote.', 'wedocs')]);
}
- $meta_key = $vote === 'yes' ? '_wedocs_helpful_yes' : '_wedocs_helpful_no';
+ $meta_key = $vote === 'yes' ? 'positive' : 'negative';
$current = (int) get_post_meta($post_id, $meta_key, true);
update_post_meta($post_id, $meta_key, $current + 1);
wp_send_json_success([
- 'yes' => (int) get_post_meta($post_id, '_wedocs_helpful_yes', true),
- 'no' => (int) get_post_meta($post_id, '_wedocs_helpful_no', true),
+ 'yes' => (int) get_post_meta($post_id, 'positive', true),
+ 'no' => (int) get_post_meta($post_id, 'negative', true),
]);
}
diff --git a/includes/Elementor/Templates/three_column.json b/includes/Elementor/Templates/three_column.json
new file mode 100644
index 00000000..71d7c2e8
--- /dev/null
+++ b/includes/Elementor/Templates/three_column.json
@@ -0,0 +1 @@
+{"content":[{"id":"66627e54","settings":{"flex_direction":"row","flex_gap":{"unit":"px","size":0,"column":"0","row":"0"},"content_width":"full","width":{"unit":"%","size":83,"sizes":[]}},"elements":[{"id":"751203","settings":{"flex_direction":"column","content_width":"full","width":{"unit":"%","size":"25"}},"elements":[{"id":"5494ee5","settings":{"search_placeholder":"Quick search...","mobile_toggle_text":"Navigation"},"elements":[],"isInner":false,"widgetType":"wedocs-docs-sidebar","elType":"widget"}],"isInner":true,"elType":"container"},{"id":"3f1364d7","settings":{"flex_direction":"column","content_width":"full","width":{"unit":"%","size":"50"}},"elements":[{"id":"11b33a2e","settings":{"content_width":"full"},"elements":[{"id":"56992cab","settings":{"__dynamic__":{"title":"[elementor-tag id=\"\" name=\"post-title\" settings=\"%7B%22before%22%3A%22%22%2C%22after%22%3A%22%22%2C%22fallback%22%3A%22%22%7D\"]"},"title":"Add Your Heading Text Here","title_color":"#142932"},"elements":[],"isInner":false,"widgetType":"theme-post-title","elType":"widget"},{"id":"62e424ef","settings":{"home_text":"Home"},"elements":[],"isInner":false,"widgetType":"wedocs-breadcrumb","elType":"widget"},{"id":"429504be","settings":[],"elements":[],"isInner":false,"widgetType":"theme-post-content","elType":"widget"},{"id":"736e93eb","settings":{"question_text":"Was this article helpful?","yes_text":"Yes","no_text":"No","show_count":"yes","thank_you_message":"Thank you for your feedback!","follow_up_placeholder":"How can we improve this article?"},"elements":[],"isInner":false,"widgetType":"wedocs-was-helpful","elType":"widget"},{"id":"360e1b81","settings":{"trigger_heading":"Need More Help?","trigger_description":"Can't find what you're looking for? Reach out to our support team.","button_text":"Contact Support","layout":"inline","modal_title":"Contact Support","modal_description":"Fill out the form below and our team will get back to you as soon as possible.","submit_text":"Send Message","success_message":"Thank you! Your message has been sent successfully.","recipient_email":"dev-email@wpengine.local","icon_color":"#364248","btn_bg_color":"#202527","btn_hover_bg_color":"#000000"},"elements":[],"isInner":false,"widgetType":"wedocs-need-help","elType":"widget"}],"isInner":true,"elType":"container"}],"isInner":true,"elType":"container"},{"id":"42bb9ff6","settings":{"flex_direction":"column","content_width":"full","width":{"unit":"%","size":"25"}},"elements":[{"id":"417d6e7f","settings":{"title":"On This Page"},"elements":[],"isInner":false,"widgetType":"wedocs-toc","elType":"widget"}],"isInner":true,"elType":"container"}],"isInner":false,"elType":"container"}],"page_settings":{"page_template":"elementor_header_footer"},"version":"0.4","title":"WeDocs Single Page","type":"single-post"}
diff --git a/includes/Elementor/Widgets/DocNavigation.php b/includes/Elementor/Widgets/DocNavigation.php
index 7c4577a7..cc4e4c9f 100644
--- a/includes/Elementor/Widgets/DocNavigation.php
+++ b/includes/Elementor/Widgets/DocNavigation.php
@@ -33,6 +33,31 @@ public function get_keywords() {
return ['navigation', 'next', 'previous', 'prev', 'wedocs', 'docs'];
}
+ /**
+ * Get the proper post context for editor mode
+ */
+ protected function get_editor_post_context() {
+ global $post;
+
+ // If we have a valid docs post, use it
+ if ($post && $post->post_type === 'docs') {
+ return $post;
+ }
+
+ // In editor mode, try to get the post being edited
+ if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
+ $document = \Elementor\Plugin::$instance->documents->get_current();
+ if ($document) {
+ $edit_post = get_post($document->get_main_id());
+ if ($edit_post && $edit_post->post_type === 'docs') {
+ return $edit_post;
+ }
+ }
+ }
+
+ return null;
+ }
+
protected function register_controls() {
// Content Section
@@ -113,6 +138,20 @@ protected function register_controls() {
]
);
+ $this->add_control(
+ 'mobile_stack',
+ [
+ 'label' => __('Stack on Mobile', 'wedocs'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'label_on' => __('Yes', 'wedocs'),
+ 'label_off' => __('No', 'wedocs'),
+ 'return_value' => 'yes',
+ 'default' => 'yes',
+ 'description' => __('Stack prev/next vertically on screens ≤768px', 'wedocs'),
+ 'condition' => ['layout' => 'side-by-side'],
+ ]
+ );
+
$this->end_controls_section();
// Style Section - Container
@@ -344,21 +383,23 @@ protected function render() {
$show_arrows = ($settings['show_arrows'] ?? 'yes') === 'yes';
$layout = $settings['layout'] ?? 'side-by-side';
- global $post, $wpdb;
+ $current_post = $this->get_editor_post_context();
- if (empty($post) || $post->post_type !== 'docs') {
+ if (!$current_post) {
if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
- echo '' . __('Doc Navigation: Preview it on a single doc page.', 'wedocs') . '
';
+ $this->render_editor_preview($settings);
}
return;
}
+ global $wpdb;
+
$next_post_id = 0;
$prev_post_id = 0;
if ($show_next) {
$next_query = "SELECT ID FROM {$wpdb->posts}
- WHERE post_parent = {$post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order > {$post->menu_order}
+ WHERE post_parent = {$current_post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order > {$current_post->menu_order}
ORDER BY menu_order ASC
LIMIT 0, 1";
$next_post_id = (int) $wpdb->get_var($next_query);
@@ -366,7 +407,7 @@ protected function render() {
if ($show_prev) {
$prev_query = "SELECT ID FROM {$wpdb->posts}
- WHERE post_parent = {$post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order < {$post->menu_order}
+ WHERE post_parent = {$current_post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order < {$current_post->menu_order}
ORDER BY menu_order DESC
LIMIT 0, 1";
$prev_post_id = (int) $wpdb->get_var($prev_query);
@@ -374,13 +415,18 @@ protected function render() {
if (!$next_post_id && !$prev_post_id) {
if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
- echo '' . __('Doc Navigation: No adjacent docs found.', 'wedocs') . '
';
+ $this->render_editor_preview($settings);
}
return;
}
+ $mobile_stack = ($settings['mobile_stack'] ?? 'yes') === 'yes';
+
$nav_class = 'wedocs-el-nav wedocs-el-nav--' . $layout;
- ?>
+ if ($mobile_stack && $layout === 'side-by-side') {
+ $nav_class .= ' wedocs-el-nav--mobile-stack';
+ }
+?>
@@ -389,7 +435,10 @@ protected function render() {
-
+
+
+
+
@@ -416,7 +465,10 @@ protected function render() {
-
+
+
+
+
@@ -442,7 +494,7 @@ protected function render() {
min-width: 0;
}
- .wedocs-el-nav--stacked .wedocs-el-nav__item + .wedocs-el-nav__item {
+ .wedocs-el-nav--stacked .wedocs-el-nav__item+.wedocs-el-nav__item {
border-top: 1px solid;
margin-top: 12px;
padding-top: 12px;
@@ -512,6 +564,28 @@ protected function render() {
.wedocs-el-nav__item--empty {
visibility: hidden;
}
+
+ @media screen and (max-width: 768px) {
+ .wedocs-el-nav--mobile-stack {
+ flex-direction: column;
+ gap: 0;
+ }
+
+ .wedocs-el-nav--mobile-stack .wedocs-el-nav__separator {
+ display: none;
+ }
+
+ .wedocs-el-nav--mobile-stack .wedocs-el-nav__item+.wedocs-el-nav__item {
+ border-top: 1px solid #e2e8f0;
+ margin-top: 12px;
+ padding-top: 12px;
+ }
+
+ .wedocs-el-nav--mobile-stack .wedocs-el-nav__item--next .wedocs-el-nav__link {
+ justify-content: flex-start;
+ text-align: left;
+ }
+ }
<#
- var showPrev = settings.show_prev === 'yes';
- var showNext = settings.show_next === 'yes';
- var showArrows = settings.show_arrows === 'yes';
- var layout = settings.layout || 'side-by-side';
- var prevLabel = settings.prev_label || 'Previous';
- var nextLabel = settings.next_label || 'Next';
- var arrowColor = settings.arrow_color || '#94a3b8';
- var labelColor = settings.label_color || '#94a3b8';
- var titleColor = settings.title_color || '#1e293b';
- var arrowSize = settings.arrow_size?.size || 20;
- #>
-
-
- <# if (showPrev) { #>
-
-
- <# if (showArrows) { #>
-
-
+ var showPrev=settings.show_prev==='yes' ;
+ var showNext=settings.show_next==='yes' ;
+ var showArrows=settings.show_arrows==='yes' ;
+ var layout=settings.layout || 'side-by-side' ;
+ var prevLabel=settings.prev_label || 'Previous' ;
+ var nextLabel=settings.next_label || 'Next' ;
+ var arrowColor=settings.arrow_color || '#94a3b8' ;
+ var labelColor=settings.label_color || '#94a3b8' ;
+ var titleColor=settings.title_color || '#1e293b' ;
+ var arrowSize=settings.arrow_size?.size || 20;
+ #>
+
+
+ <# if (showPrev) { #>
+
+ <# } #>
+
+ <# if (showPrev && showNext && layout==='side-by-side' ) { #>
+
+ <# } #>
+
+ <# if (showPrev && showNext && layout==='stacked' ) { #>
+
+ <# } #>
+
+ <# if (showNext) { #>
+
+ <# } #>
+
+
+
+
+
+
- <# } #>
-
- <# if (showPrev && showNext && layout === 'side-by-side') { #>
-
- <# } #>
-
- <# if (showPrev && showNext && layout === 'stacked') { #>
-
- <# } #>
-
- <# if (showNext) { #>
-
+
+
+
+
+
+
+
+
+
+
+
+ 📝
- <# } #>
-
+
post_type === 'docs') {
+ return $post;
+ }
+
+ // In editor mode, try to get the post being edited
+ if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
+ $document = \Elementor\Plugin::$instance->documents->get_current();
+ if ($document) {
+ $edit_post = get_post($document->get_main_id());
+ if ($edit_post && $edit_post->post_type === 'docs') {
+ return $edit_post;
+ }
+ }
+ }
+
+ return null;
+ }
+
protected function register_controls() {
// Content Section
@@ -316,11 +341,11 @@ protected function render() {
];
$sep_char = $separators[$separator] ?? '›';
- global $post;
+ $current_post = $this->get_editor_post_context();
- if (empty($post) || $post->post_type !== 'docs') {
+ if (!$current_post) {
if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
- echo '' . __('Docs Breadcrumb: Preview it on a single doc page.', 'wedocs') . '
';
+ $this->render_editor_preview($settings);
}
return;
}
@@ -345,8 +370,8 @@ protected function render() {
}
// Parent hierarchy
- if ($post->post_parent) {
- $parent_id = $post->post_parent;
+ if ($current_post->post_parent) {
+ $parent_id = $current_post->post_parent;
$parents = [];
while ($parent_id) {
@@ -367,7 +392,7 @@ protected function render() {
'current' => true,
];
- ?>
+?>
$item):
@@ -391,7 +416,9 @@ protected function render() {
-
+
+
+
@@ -456,53 +483,137 @@ protected function render() {
protected function content_template() {
?>
<#
- var homeText = settings.home_text || 'Home';
- var showHomeIcon = settings.show_home_icon === 'yes';
- var separator = settings.separator || 'angle';
- var linkColor = settings.link_color || '#64748b';
- var currentColor = settings.current_color || '#1e293b';
- var sepColor = settings.separator_color || '#cbd5e1';
- var sepSize = settings.separator_size?.size || 14;
- var iconColor = settings.home_icon_color || '#94a3b8';
- var iconSize = settings.home_icon_size?.size || 16;
- var currentWeight = settings.current_font_weight || '600';
-
- var seps = { angle: '›', slash: '/', arrow: '→', dot: '·', dash: '—' };
- var sepChar = seps[separator] || '›';
-
- var items = [
+ var homeText=settings.home_text || 'Home' ;
+ var showHomeIcon=settings.show_home_icon==='yes' ;
+ var separator=settings.separator || 'angle' ;
+ var linkColor=settings.link_color || '#64748b' ;
+ var currentColor=settings.current_color || '#1e293b' ;
+ var sepColor=settings.separator_color || '#cbd5e1' ;
+ var sepSize=settings.separator_size?.size || 14;
+ var iconColor=settings.home_icon_color || '#94a3b8' ;
+ var iconSize=settings.home_icon_size?.size || 16;
+ var currentWeight=settings.current_font_weight || '600' ;
+
+ var seps={ angle: '›' , slash: '/' , arrow: '→' , dot: '·' , dash: '—' };
+ var sepChar=seps[separator] || '›' ;
+
+ var items=[
{ label: homeText, home: true },
{ label: 'Documentation' },
{ label: 'Getting Started' },
- { label: 'Installation Guide', current: true }
- ];
- #>
+ { label: 'Installation Guide' , current: true }
+ ];
+ #>
-
-
- <# for (var i = 0; i < items.length; i++) {
- var item = items[i];
- if (i > 0) { #>
+
+
+ <# for (var i=0; i < items.length; i++) {
+ var item=items[i];
+ if (i> 0) { #>
{{ sepChar }}
- <# } #>
-
- <# if (item.current) { #>
- {{ item.label }}
- <# } else { #>
-
-
- <# if (item.home && showHomeIcon) { #>
-
-
-
- <# } #>
- {{ item.label }}
-
-
- <# } #>
- <# } #>
-
-
+ <# } #>
+
+ <# if (item.current) { #>
+ {{ item.label }}
+ <# } else { #>
+
+
+ <# if (item.home && showHomeIcon) { #>
+
+
+
+
+
+ <# } #>
+ {{ item.label }}
+
+
+ <# } #>
+ <# } #>
+
+
+ '›',
+ 'slash' => '/',
+ 'arrow' => '→',
+ 'dot' => '·',
+ 'dash' => '—',
+ ];
+ $sep_char = $separators[$separator] ?? '›';
+
+ // Sample breadcrumb items for preview
+ $items = [
+ [
+ 'label' => $home_text,
+ 'url' => '#',
+ 'home' => true,
+ ],
+ [
+ 'label' => __('Documentation', 'wedocs'),
+ 'url' => '#',
+ ],
+ [
+ 'label' => __('Getting Started', 'wedocs'),
+ 'url' => '#',
+ ],
+ [
+ 'label' => __('Installation Guide', 'wedocs'),
+ 'current' => true,
+ ]
+ ];
+
+ ?>
+
+
+ $item):
+ $is_current = !empty($item['current']);
+ $is_home = !empty($item['home']);
+ $label = $item['label'];
+ if ($truncate > 0 && mb_strlen($label) > $truncate && !$is_current) {
+ $label = mb_substr($label, 0, $truncate) . '…';
+ }
+ ?>
+ 0): ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 📝
+
+
post_type === 'docs') {
+ return $post;
+ }
+
+ // In editor mode, try to get the post being edited
+ if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
+ $document = \Elementor\Plugin::$instance->documents->get_current();
+ if ($document) {
+ $edit_post = get_post($document->get_main_id());
+ if ($edit_post && $edit_post->post_type === 'docs') {
+ return $edit_post;
+ }
+ }
+
+ // Fallback: try to find any published doc
+ $fallback_doc = get_posts([
+ 'post_type' => 'docs',
+ 'post_status' => 'publish',
+ 'posts_per_page' => 1,
+ 'meta_query' => [
+ 'relation' => 'OR',
+ [
+ 'key' => '_wp_page_template',
+ 'value' => 'elementor_header_footer',
+ 'compare' => 'NOT EXISTS'
+ ],
+ [
+ 'key' => '_wp_page_template',
+ 'value' => 'elementor_header_footer',
+ 'compare' => '!='
+ ]
+ ]
+ ]);
+
+ if (!empty($fallback_doc)) {
+ return $fallback_doc[0];
+ }
+ }
+
+ return null;
+ }
+
protected function register_controls() {
// Content Section
@@ -108,6 +157,69 @@ protected function register_controls() {
$this->end_controls_section();
+ // Responsive Section
+ $this->start_controls_section(
+ 'responsive_section',
+ [
+ 'label' => __('Responsive', 'wedocs'),
+ 'tab' => Controls_Manager::TAB_CONTENT,
+ ]
+ );
+
+ $this->add_control(
+ 'mobile_display',
+ [
+ 'label' => __('Mobile Display Mode', 'wedocs'),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'normal',
+ 'options' => [
+ 'normal' => __('Normal (Always Visible)', 'wedocs'),
+ 'hamburger' => __('Hamburger Toggle', 'wedocs'),
+ 'hidden' => __('Hidden on Mobile', 'wedocs'),
+ ],
+ 'description' => __('How to display the sidebar on screens ≤768px', 'wedocs'),
+ ]
+ );
+
+ $this->add_control(
+ 'mobile_toggle_text',
+ [
+ 'label' => __('Toggle Button Text', 'wedocs'),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => __('Navigation', 'wedocs'),
+ 'condition' => ['mobile_display' => 'hamburger'],
+ ]
+ );
+
+ $this->add_control(
+ 'mobile_toggle_color',
+ [
+ 'label' => __('Toggle Button Color', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#1e293b',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar__toggle' => 'color: {{VALUE}};',
+ '{{WRAPPER}} .wedocs-el-sidebar__toggle svg' => 'fill: {{VALUE}};',
+ ],
+ 'condition' => ['mobile_display' => 'hamburger'],
+ ]
+ );
+
+ $this->add_control(
+ 'mobile_toggle_bg',
+ [
+ 'label' => __('Toggle Button Background', 'wedocs'),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#f1f5f9',
+ 'selectors' => [
+ '{{WRAPPER}} .wedocs-el-sidebar__toggle' => 'background-color: {{VALUE}};',
+ ],
+ 'condition' => ['mobile_display' => 'hamburger'],
+ ]
+ );
+
+ $this->end_controls_section();
+
// Style Section - Container
$this->start_controls_section(
'style_container',
@@ -481,24 +593,35 @@ protected function render() {
$search_placeholder = $settings['search_placeholder'] ?? __('Quick search...', 'wedocs');
$collapse_behavior = $settings['collapse_behavior'] ?? 'expand_active';
$show_dividers = ($settings['show_dividers'] ?? '') === 'yes';
+ $mobile_display = $settings['mobile_display'] ?? 'normal';
+ $mobile_toggle_text = $settings['mobile_toggle_text'] ?? __('Navigation', 'wedocs');
- global $post;
+ // Get the proper post context
+ $current_post = $this->get_editor_post_context();
+
+ if (!$current_post) {
+ if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
+ // Show preview with sample data
+ $this->render_editor_preview($settings);
+ }
+ return;
+ }
// Determine the parent doc
$ancestors = [];
$parent = false;
- if (!empty($post->post_parent)) {
- $ancestors = get_post_ancestors($post->ID);
+ if (!empty($current_post->post_parent)) {
+ $ancestors = get_post_ancestors($current_post->ID);
$root = count($ancestors) - 1;
$parent = $ancestors[$root];
} else {
- $parent = !empty($post->ID) ? $post->ID : '';
+ $parent = !empty($current_post->ID) ? $current_post->ID : '';
}
if (!$parent) {
if (\Elementor\Plugin::$instance->editor->is_edit_mode()) {
- echo '' . __('Docs Sidebar: This widget displays the documentation navigation. Preview it on a single doc page.', 'wedocs') . '
';
+ $this->render_editor_preview($settings);
}
return;
}
@@ -519,9 +642,31 @@ protected function render() {
} elseif ($collapse_behavior === 'collapse_all') {
$sidebar_class .= ' wedocs-el-sidebar--collapse-all';
}
- ?>
+ if ($mobile_display === 'hamburger') {
+ $sidebar_class .= ' wedocs-el-sidebar--mobile-hamburger';
+ } elseif ($mobile_display === 'hidden') {
+ $sidebar_class .= ' wedocs-el-sidebar--mobile-hidden';
+ }
+?>
+
+
+
+