start_controls_section( 'content_section', array( 'label' => __( 'Content', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ) ); // Layout. $this->add_control( 'layout', array( 'label' => __( 'Layout', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'grid', 'options' => array( 'grid' => __( 'Grid', 'a1-tools' ), 'carousel' => __( 'Carousel', 'a1-tools' ), ), ) ); // Columns count. $this->add_responsive_control( 'columns', array( 'label' => __( 'Columns', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::NUMBER, 'min' => 1, 'max' => 4, 'default' => 3, 'condition' => array( 'layout' => 'grid' ), 'selectors' => array( '{{WRAPPER}} .a1tools-reviews-grid' => 'grid-template-columns: repeat({{VALUE}}, 1fr);', ), ) ); // Show stars. $this->add_control( 'show_stars', array( 'label' => __( 'Show Stars', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'label_on' => __( 'Yes', 'a1-tools' ), 'label_off' => __( 'No', 'a1-tools' ), 'return_value' => 'yes', 'default' => 'yes', ) ); // Show source. $this->add_control( 'show_source', array( 'label' => __( 'Show Source', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'label_on' => __( 'Yes', 'a1-tools' ), 'label_off' => __( 'No', 'a1-tools' ), 'return_value' => 'yes', 'default' => 'yes', ) ); // Show date. $this->add_control( 'show_date', array( 'label' => __( 'Show Date', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'label_on' => __( 'Yes', 'a1-tools' ), 'label_off' => __( 'No', 'a1-tools' ), 'return_value' => 'yes', 'default' => 'yes', ) ); // Show image. $this->add_control( 'show_image', array( 'label' => __( 'Show Image', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'label_on' => __( 'Yes', 'a1-tools' ), 'label_off' => __( 'No', 'a1-tools' ), 'return_value' => 'yes', 'default' => 'yes', ) ); // Featured only. $this->add_control( 'featured_only', array( 'label' => __( 'Featured Only', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'label_on' => __( 'Yes', 'a1-tools' ), 'label_off' => __( 'No', 'a1-tools' ), 'return_value' => 'yes', 'default' => '', ) ); // Limit. $this->add_control( 'limit', array( 'label' => __( 'Limit', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::NUMBER, 'min' => 1, 'max' => 50, 'default' => 6, ) ); $this->end_controls_section(); // ── Style: Card ──────────────────────────────────────────── $this->start_controls_section( 'style_card_section', array( 'label' => __( 'Card', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, ) ); $this->add_control( 'card_bg_color', array( 'label' => __( 'Background Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-review-card' => 'background-color: {{VALUE}};', ), ) ); $this->add_group_control( \Elementor\Group_Control_Border::get_type(), array( 'name' => 'card_border', 'selector' => '{{WRAPPER}} .a1tools-review-card', ) ); $this->add_control( 'card_border_radius', array( 'label' => __( 'Border Radius', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::DIMENSIONS, 'size_units' => array( 'px', '%' ), 'selectors' => array( '{{WRAPPER}} .a1tools-review-card' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', ), ) ); $this->add_responsive_control( 'card_padding', array( 'label' => __( 'Padding', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::DIMENSIONS, 'size_units' => array( 'px', 'em' ), 'selectors' => array( '{{WRAPPER}} .a1tools-review-card' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', ), ) ); $this->add_group_control( \Elementor\Group_Control_Box_Shadow::get_type(), array( 'name' => 'card_shadow', 'selector' => '{{WRAPPER}} .a1tools-review-card', ) ); $this->end_controls_section(); // ── Style: Reviewer Name ─────────────────────────────────── $this->start_controls_section( 'style_name_section', array( 'label' => __( 'Reviewer Name', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, ) ); $this->add_group_control( \Elementor\Group_Control_Typography::get_type(), array( 'name' => 'name_typography', 'selector' => '{{WRAPPER}} .a1tools-review-name', ) ); $this->add_control( 'name_color', array( 'label' => __( 'Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-review-name' => 'color: {{VALUE}};', ), ) ); $this->end_controls_section(); // ── Style: Review Text ───────────────────────────────────── $this->start_controls_section( 'style_text_section', array( 'label' => __( 'Review Text', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, ) ); $this->add_group_control( \Elementor\Group_Control_Typography::get_type(), array( 'name' => 'text_typography', 'selector' => '{{WRAPPER}} .a1tools-review-text', ) ); $this->add_control( 'text_color', array( 'label' => __( 'Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-review-text' => 'color: {{VALUE}};', ), ) ); $this->end_controls_section(); // ── Style: Stars ─────────────────────────────────────────── $this->start_controls_section( 'style_stars_section', array( 'label' => __( 'Stars', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, ) ); $this->add_control( 'stars_color', array( 'label' => __( 'Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-review-stars' => 'color: {{VALUE}};', ), ) ); $this->add_responsive_control( 'stars_size', array( 'label' => __( 'Size', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'range' => array( 'px' => array( 'min' => 10, 'max' => 40 ) ), 'default' => array( 'size' => 16, 'unit' => 'px' ), 'selectors' => array( '{{WRAPPER}} .a1tools-review-stars' => 'font-size: {{SIZE}}{{UNIT}};', ), ) ); $this->end_controls_section(); // ── Style: Column Layout ─────────────────────────────────── $this->start_controls_section( 'style_columns_section', array( 'label' => __( 'Column Layout', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, 'condition' => array( 'layout' => 'grid' ), ) ); $this->add_responsive_control( 'column_gap', array( 'label' => __( 'Gap', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'range' => array( 'px' => array( 'min' => 0, 'max' => 60 ) ), 'default' => array( 'size' => 20, 'unit' => 'px' ), 'selectors' => array( '{{WRAPPER}} .a1tools-reviews-grid' => 'gap: {{SIZE}}{{UNIT}};', ), ) ); $this->end_controls_section(); } /** * Render widget output on the frontend. */ protected function render() { $settings = $this->get_settings_for_display(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped inside shortcode function. echo a1tools_shortcode_reviews( array( 'layout' => $settings['layout'] ?? 'grid', 'columns' => $settings['columns'] ?? '3', 'show_stars' => $settings['show_stars'] ?? 'yes', 'show_source' => $settings['show_source'] ?? 'yes', 'show_date' => $settings['show_date'] ?? 'yes', 'show_image' => $settings['show_image'] ?? 'yes', 'featured_only' => $settings['featured_only'] ?? '', 'limit' => $settings['limit'] ?? '6', '_elementor' => 'yes', ) ); } /** * Render widget preview in the Elementor editor. */ protected function content_template() { ?> <# var isGrid = (settings.layout === 'grid'); var showStars = (settings.show_stars === 'yes'); var showSrc = (settings.show_source === 'yes'); var showDate = (settings.show_date === 'yes'); var showImg = (settings.show_image === 'yes'); var reviews = [ { name: 'John D.', text: 'Excellent service! The team was professional and thorough with our chimney cleaning.', stars: 5, source: 'Google', date: 'Jan 15, 2025' }, { name: 'Sarah M.', text: 'Very happy with the repair work. They fixed our chimney cap and it looks great.', stars: 5, source: 'Yelp', date: 'Feb 3, 2025' } ]; #>
<# _.each( reviews, function( rev ) { #>
<# if(showImg){#>
☺
<#}#> <# if(showStars){#>
<# for(var i=0;i★<#}#>
<#}#>

{{ rev.text }}

{{ rev.name }}

<# if(showSrc || showDate){#>

<# if(showSrc){#>{{ rev.source }}<#}#> <# if(showSrc && showDate){#> · <#}#> <# if(showDate){#>{{ rev.date }}<#}#>

<#}#>
<# }); #>
Note: Actual reviews load on the frontend from the A1 Tools API. <# if(settings.layout === 'carousel'){#>
Carousel navigation is active on the frontend.<#}#>