icon-box.php (19145B)
1 <?php 2 namespace Elementor; 3 4 if ( ! defined( 'ABSPATH' ) ) { 5 exit; // Exit if accessed directly. 6 } 7 8 use Elementor\Core\Kits\Documents\Tabs\Global_Colors; 9 use Elementor\Core\Kits\Documents\Tabs\Global_Typography; 10 11 /** 12 * Elementor icon box widget. 13 * 14 * Elementor widget that displays an icon, a headline and a text. 15 * 16 * @since 1.0.0 17 */ 18 class Widget_Icon_Box extends Widget_Base { 19 20 /** 21 * Get widget name. 22 * 23 * Retrieve icon box widget name. 24 * 25 * @since 1.0.0 26 * @access public 27 * 28 * @return string Widget name. 29 */ 30 public function get_name() { 31 return 'icon-box'; 32 } 33 34 /** 35 * Get widget title. 36 * 37 * Retrieve icon box widget title. 38 * 39 * @since 1.0.0 40 * @access public 41 * 42 * @return string Widget title. 43 */ 44 public function get_title() { 45 return esc_html__( 'Icon Box', 'elementor' ); 46 } 47 48 /** 49 * Get widget icon. 50 * 51 * Retrieve icon box widget icon. 52 * 53 * @since 1.0.0 54 * @access public 55 * 56 * @return string Widget icon. 57 */ 58 public function get_icon() { 59 return 'eicon-icon-box'; 60 } 61 62 /** 63 * Get widget keywords. 64 * 65 * Retrieve the list of keywords the widget belongs to. 66 * 67 * @since 2.1.0 68 * @access public 69 * 70 * @return array Widget keywords. 71 */ 72 public function get_keywords() { 73 return [ 'icon box', 'icon' ]; 74 } 75 76 /** 77 * Register icon box widget controls. 78 * 79 * Adds different input fields to allow the user to change and customize the widget settings. 80 * 81 * @since 3.1.0 82 * @access protected 83 */ 84 protected function register_controls() { 85 $this->start_controls_section( 86 'section_icon', 87 [ 88 'label' => esc_html__( 'Icon Box', 'elementor' ), 89 ] 90 ); 91 92 $this->add_control( 93 'selected_icon', 94 [ 95 'label' => esc_html__( 'Icon', 'elementor' ), 96 'type' => Controls_Manager::ICONS, 97 'fa4compatibility' => 'icon', 98 'default' => [ 99 'value' => 'fas fa-star', 100 'library' => 'fa-solid', 101 ], 102 ] 103 ); 104 105 $this->add_control( 106 'view', 107 [ 108 'label' => esc_html__( 'View', 'elementor' ), 109 'type' => Controls_Manager::SELECT, 110 'options' => [ 111 'default' => esc_html__( 'Default', 'elementor' ), 112 'stacked' => esc_html__( 'Stacked', 'elementor' ), 113 'framed' => esc_html__( 'Framed', 'elementor' ), 114 ], 115 'default' => 'default', 116 'prefix_class' => 'elementor-view-', 117 ] 118 ); 119 120 $this->add_control( 121 'shape', 122 [ 123 'label' => esc_html__( 'Shape', 'elementor' ), 124 'type' => Controls_Manager::SELECT, 125 'options' => [ 126 'circle' => esc_html__( 'Circle', 'elementor' ), 127 'square' => esc_html__( 'Square', 'elementor' ), 128 ], 129 'default' => 'circle', 130 'condition' => [ 131 'view!' => 'default', 132 'selected_icon[value]!' => '', 133 ], 134 'prefix_class' => 'elementor-shape-', 135 ] 136 ); 137 138 $this->add_control( 139 'title_text', 140 [ 141 'label' => esc_html__( 'Title & Description', 'elementor' ), 142 'type' => Controls_Manager::TEXT, 143 'dynamic' => [ 144 'active' => true, 145 ], 146 'default' => esc_html__( 'This is the heading', 'elementor' ), 147 'placeholder' => esc_html__( 'Enter your title', 'elementor' ), 148 'label_block' => true, 149 ] 150 ); 151 152 $this->add_control( 153 'description_text', 154 [ 155 'label' => '', 156 'type' => Controls_Manager::TEXTAREA, 157 'dynamic' => [ 158 'active' => true, 159 ], 160 'default' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ), 161 'placeholder' => esc_html__( 'Enter your description', 'elementor' ), 162 'rows' => 10, 163 'separator' => 'none', 164 'show_label' => false, 165 ] 166 ); 167 168 $this->add_control( 169 'link', 170 [ 171 'label' => esc_html__( 'Link', 'elementor' ), 172 'type' => Controls_Manager::URL, 173 'dynamic' => [ 174 'active' => true, 175 ], 176 'placeholder' => esc_html__( 'https://your-link.com', 'elementor' ), 177 'separator' => 'before', 178 ] 179 ); 180 181 $this->add_control( 182 'position', 183 [ 184 'label' => esc_html__( 'Icon Position', 'elementor' ), 185 'type' => Controls_Manager::CHOOSE, 186 'default' => 'top', 187 'options' => [ 188 'left' => [ 189 'title' => esc_html__( 'Left', 'elementor' ), 190 'icon' => 'eicon-h-align-left', 191 ], 192 'top' => [ 193 'title' => esc_html__( 'Top', 'elementor' ), 194 'icon' => 'eicon-v-align-top', 195 ], 196 'right' => [ 197 'title' => esc_html__( 'Right', 'elementor' ), 198 'icon' => 'eicon-h-align-right', 199 ], 200 ], 201 'prefix_class' => 'elementor-position-', 202 'toggle' => false, 203 'conditions' => [ 204 'relation' => 'or', 205 'terms' => [ 206 [ 207 'name' => 'selected_icon[value]', 208 'operator' => '!=', 209 'value' => '', 210 ], 211 ], 212 ], 213 ] 214 ); 215 216 $this->add_control( 217 'title_size', 218 [ 219 'label' => esc_html__( 'Title HTML Tag', 'elementor' ), 220 'type' => Controls_Manager::SELECT, 221 'options' => [ 222 'h1' => 'H1', 223 'h2' => 'H2', 224 'h3' => 'H3', 225 'h4' => 'H4', 226 'h5' => 'H5', 227 'h6' => 'H6', 228 'div' => 'div', 229 'span' => 'span', 230 'p' => 'p', 231 ], 232 'default' => 'h3', 233 ] 234 ); 235 236 $this->end_controls_section(); 237 238 $this->start_controls_section( 239 'section_style_icon', 240 [ 241 'label' => esc_html__( 'Icon', 'elementor' ), 242 'tab' => Controls_Manager::TAB_STYLE, 243 'conditions' => [ 244 'relation' => 'or', 245 'terms' => [ 246 [ 247 'name' => 'selected_icon[value]', 248 'operator' => '!=', 249 'value' => '', 250 ], 251 ], 252 ], 253 ] 254 ); 255 256 $this->start_controls_tabs( 'icon_colors' ); 257 258 $this->start_controls_tab( 259 'icon_colors_normal', 260 [ 261 'label' => esc_html__( 'Normal', 'elementor' ), 262 ] 263 ); 264 265 $this->add_control( 266 'primary_color', 267 [ 268 'label' => esc_html__( 'Primary Color', 'elementor' ), 269 'type' => Controls_Manager::COLOR, 270 'global' => [ 271 'default' => Global_Colors::COLOR_PRIMARY, 272 ], 273 'default' => '', 274 'selectors' => [ 275 '{{WRAPPER}}.elementor-view-stacked .elementor-icon' => 'background-color: {{VALUE}};', 276 '{{WRAPPER}}.elementor-view-framed .elementor-icon, {{WRAPPER}}.elementor-view-default .elementor-icon' => 'fill: {{VALUE}}; color: {{VALUE}}; border-color: {{VALUE}};', 277 ], 278 ] 279 ); 280 281 $this->add_control( 282 'secondary_color', 283 [ 284 'label' => esc_html__( 'Secondary Color', 'elementor' ), 285 'type' => Controls_Manager::COLOR, 286 'default' => '', 287 'condition' => [ 288 'view!' => 'default', 289 ], 290 'selectors' => [ 291 '{{WRAPPER}}.elementor-view-framed .elementor-icon' => 'background-color: {{VALUE}};', 292 '{{WRAPPER}}.elementor-view-stacked .elementor-icon' => 'fill: {{VALUE}}; color: {{VALUE}};', 293 ], 294 ] 295 ); 296 297 $this->end_controls_tab(); 298 299 $this->start_controls_tab( 300 'icon_colors_hover', 301 [ 302 'label' => esc_html__( 'Hover', 'elementor' ), 303 ] 304 ); 305 306 $this->add_control( 307 'hover_primary_color', 308 [ 309 'label' => esc_html__( 'Primary Color', 'elementor' ), 310 'type' => Controls_Manager::COLOR, 311 'default' => '', 312 'selectors' => [ 313 '{{WRAPPER}}.elementor-view-stacked .elementor-icon:hover' => 'background-color: {{VALUE}};', 314 '{{WRAPPER}}.elementor-view-framed .elementor-icon:hover, {{WRAPPER}}.elementor-view-default .elementor-icon:hover' => 'fill: {{VALUE}}; color: {{VALUE}}; border-color: {{VALUE}};', 315 ], 316 ] 317 ); 318 319 $this->add_control( 320 'hover_secondary_color', 321 [ 322 'label' => esc_html__( 'Secondary Color', 'elementor' ), 323 'type' => Controls_Manager::COLOR, 324 'default' => '', 325 'condition' => [ 326 'view!' => 'default', 327 ], 328 'selectors' => [ 329 '{{WRAPPER}}.elementor-view-framed .elementor-icon:hover' => 'background-color: {{VALUE}};', 330 '{{WRAPPER}}.elementor-view-stacked .elementor-icon:hover' => 'fill: {{VALUE}}; color: {{VALUE}};', 331 ], 332 ] 333 ); 334 335 $this->add_control( 336 'hover_animation', 337 [ 338 'label' => esc_html__( 'Hover Animation', 'elementor' ), 339 'type' => Controls_Manager::HOVER_ANIMATION, 340 ] 341 ); 342 343 $this->end_controls_tab(); 344 345 $this->end_controls_tabs(); 346 347 $this->add_responsive_control( 348 'icon_space', 349 [ 350 'label' => esc_html__( 'Spacing', 'elementor' ), 351 'type' => Controls_Manager::SLIDER, 352 'default' => [ 353 'size' => 15, 354 ], 355 'range' => [ 356 'px' => [ 357 'min' => 0, 358 'max' => 100, 359 ], 360 ], 361 'selectors' => [ 362 '{{WRAPPER}}.elementor-position-right .elementor-icon-box-icon' => 'margin-left: {{SIZE}}{{UNIT}};', 363 '{{WRAPPER}}.elementor-position-left .elementor-icon-box-icon' => 'margin-right: {{SIZE}}{{UNIT}};', 364 '{{WRAPPER}}.elementor-position-top .elementor-icon-box-icon' => 'margin-bottom: {{SIZE}}{{UNIT}};', 365 '(mobile){{WRAPPER}} .elementor-icon-box-icon' => 'margin-bottom: {{SIZE}}{{UNIT}};', 366 ], 367 ] 368 ); 369 370 $this->add_responsive_control( 371 'icon_size', 372 [ 373 'label' => esc_html__( 'Size', 'elementor' ), 374 'type' => Controls_Manager::SLIDER, 375 'range' => [ 376 'px' => [ 377 'min' => 6, 378 'max' => 300, 379 ], 380 ], 381 'selectors' => [ 382 '{{WRAPPER}} .elementor-icon' => 'font-size: {{SIZE}}{{UNIT}};', 383 ], 384 ] 385 ); 386 387 $this->add_control( 388 'icon_padding', 389 [ 390 'label' => esc_html__( 'Padding', 'elementor' ), 391 'type' => Controls_Manager::SLIDER, 392 'selectors' => [ 393 '{{WRAPPER}} .elementor-icon' => 'padding: {{SIZE}}{{UNIT}};', 394 ], 395 'range' => [ 396 'em' => [ 397 'min' => 0, 398 'max' => 5, 399 ], 400 ], 401 'condition' => [ 402 'view!' => 'default', 403 ], 404 ] 405 ); 406 407 $this->add_control( 408 'rotate', 409 [ 410 'label' => esc_html__( 'Rotate', 'elementor' ), 411 'type' => Controls_Manager::SLIDER, 412 'default' => [ 413 'size' => 0, 414 'unit' => 'deg', 415 ], 416 'selectors' => [ 417 '{{WRAPPER}} .elementor-icon i' => 'transform: rotate({{SIZE}}{{UNIT}});', 418 ], 419 ] 420 ); 421 422 $this->add_control( 423 'border_width', 424 [ 425 'label' => esc_html__( 'Border Width', 'elementor' ), 426 'type' => Controls_Manager::DIMENSIONS, 427 'selectors' => [ 428 '{{WRAPPER}} .elementor-icon' => 'border-width: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', 429 ], 430 'condition' => [ 431 'view' => 'framed', 432 ], 433 ] 434 ); 435 436 $this->add_control( 437 'border_radius', 438 [ 439 'label' => esc_html__( 'Border Radius', 'elementor' ), 440 'type' => Controls_Manager::DIMENSIONS, 441 'size_units' => [ 'px', '%' ], 442 'selectors' => [ 443 '{{WRAPPER}} .elementor-icon' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', 444 ], 445 'condition' => [ 446 'view!' => 'default', 447 ], 448 ] 449 ); 450 451 $this->end_controls_section(); 452 453 $this->start_controls_section( 454 'section_style_content', 455 [ 456 'label' => esc_html__( 'Content', 'elementor' ), 457 'tab' => Controls_Manager::TAB_STYLE, 458 ] 459 ); 460 461 $this->add_responsive_control( 462 'text_align', 463 [ 464 'label' => esc_html__( 'Alignment', 'elementor' ), 465 'type' => Controls_Manager::CHOOSE, 466 'options' => [ 467 'left' => [ 468 'title' => esc_html__( 'Left', 'elementor' ), 469 'icon' => 'eicon-text-align-left', 470 ], 471 'center' => [ 472 'title' => esc_html__( 'Center', 'elementor' ), 473 'icon' => 'eicon-text-align-center', 474 ], 475 'right' => [ 476 'title' => esc_html__( 'Right', 'elementor' ), 477 'icon' => 'eicon-text-align-right', 478 ], 479 'justify' => [ 480 'title' => esc_html__( 'Justified', 'elementor' ), 481 'icon' => 'eicon-text-align-justify', 482 ], 483 ], 484 'selectors' => [ 485 '{{WRAPPER}} .elementor-icon-box-wrapper' => 'text-align: {{VALUE}};', 486 ], 487 ] 488 ); 489 490 $this->add_control( 491 'content_vertical_alignment', 492 [ 493 'label' => esc_html__( 'Vertical Alignment', 'elementor' ), 494 'type' => Controls_Manager::SELECT, 495 'options' => [ 496 'top' => esc_html__( 'Top', 'elementor' ), 497 'middle' => esc_html__( 'Middle', 'elementor' ), 498 'bottom' => esc_html__( 'Bottom', 'elementor' ), 499 ], 500 'default' => 'top', 501 'prefix_class' => 'elementor-vertical-align-', 502 ] 503 ); 504 505 $this->add_control( 506 'heading_title', 507 [ 508 'label' => esc_html__( 'Title', 'elementor' ), 509 'type' => Controls_Manager::HEADING, 510 'separator' => 'before', 511 ] 512 ); 513 514 $this->add_responsive_control( 515 'title_bottom_space', 516 [ 517 'label' => esc_html__( 'Spacing', 'elementor' ), 518 'type' => Controls_Manager::SLIDER, 519 'range' => [ 520 'px' => [ 521 'min' => 0, 522 'max' => 100, 523 ], 524 ], 525 'selectors' => [ 526 '{{WRAPPER}} .elementor-icon-box-title' => 'margin-bottom: {{SIZE}}{{UNIT}};', 527 ], 528 ] 529 ); 530 531 $this->add_control( 532 'title_color', 533 [ 534 'label' => esc_html__( 'Color', 'elementor' ), 535 'type' => Controls_Manager::COLOR, 536 'default' => '', 537 'selectors' => [ 538 '{{WRAPPER}} .elementor-icon-box-title' => 'color: {{VALUE}};', 539 ], 540 'global' => [ 541 'default' => Global_Colors::COLOR_PRIMARY, 542 ], 543 ] 544 ); 545 546 $this->add_group_control( 547 Group_Control_Typography::get_type(), 548 [ 549 'name' => 'title_typography', 550 'selector' => '{{WRAPPER}} .elementor-icon-box-title, {{WRAPPER}} .elementor-icon-box-title a', 551 'global' => [ 552 'default' => Global_Typography::TYPOGRAPHY_PRIMARY, 553 ], 554 ] 555 ); 556 557 $this->add_group_control( 558 Group_Control_Text_Shadow::get_type(), 559 [ 560 'name' => 'title_shadow', 561 'selector' => '{{WRAPPER}} .elementor-icon-box-title', 562 ] 563 ); 564 565 $this->add_control( 566 'heading_description', 567 [ 568 'label' => esc_html__( 'Description', 'elementor' ), 569 'type' => Controls_Manager::HEADING, 570 'separator' => 'before', 571 ] 572 ); 573 574 $this->add_control( 575 'description_color', 576 [ 577 'label' => esc_html__( 'Color', 'elementor' ), 578 'type' => Controls_Manager::COLOR, 579 'default' => '', 580 'selectors' => [ 581 '{{WRAPPER}} .elementor-icon-box-description' => 'color: {{VALUE}};', 582 ], 583 'global' => [ 584 'default' => Global_Colors::COLOR_TEXT, 585 ], 586 ] 587 ); 588 589 $this->add_group_control( 590 Group_Control_Typography::get_type(), 591 [ 592 'name' => 'description_typography', 593 'selector' => '{{WRAPPER}} .elementor-icon-box-description', 594 'global' => [ 595 'default' => Global_Typography::TYPOGRAPHY_TEXT, 596 ], 597 ] 598 ); 599 600 $this->add_group_control( 601 Group_Control_Text_Shadow::get_type(), 602 [ 603 'name' => 'description_shadow', 604 'selector' => '{{WRAPPER}} .elementor-icon-box-description', 605 ] 606 ); 607 608 $this->end_controls_section(); 609 } 610 611 /** 612 * Render icon box widget output on the frontend. 613 * 614 * Written in PHP and used to generate the final HTML. 615 * 616 * @since 1.0.0 617 * @access protected 618 */ 619 protected function render() { 620 $settings = $this->get_settings_for_display(); 621 622 $this->add_render_attribute( 'icon', 'class', [ 'elementor-icon', 'elementor-animation-' . $settings['hover_animation'] ] ); 623 624 $icon_tag = 'span'; 625 626 if ( ! isset( $settings['icon'] ) && ! Icons_Manager::is_migration_allowed() ) { 627 // add old default 628 $settings['icon'] = 'fa fa-star'; 629 } 630 631 $has_icon = ! empty( $settings['icon'] ); 632 633 if ( ! empty( $settings['link']['url'] ) ) { 634 $icon_tag = 'a'; 635 636 $this->add_link_attributes( 'link', $settings['link'] ); 637 } 638 639 if ( $has_icon ) { 640 $this->add_render_attribute( 'i', 'class', $settings['icon'] ); 641 $this->add_render_attribute( 'i', 'aria-hidden', 'true' ); 642 } 643 644 $this->add_render_attribute( 'description_text', 'class', 'elementor-icon-box-description' ); 645 646 $this->add_inline_editing_attributes( 'title_text', 'none' ); 647 $this->add_inline_editing_attributes( 'description_text' ); 648 if ( ! $has_icon && ! empty( $settings['selected_icon']['value'] ) ) { 649 $has_icon = true; 650 } 651 $migrated = isset( $settings['__fa4_migrated']['selected_icon'] ); 652 $is_new = ! isset( $settings['icon'] ) && Icons_Manager::is_migration_allowed(); 653 654 ?> 655 <div class="elementor-icon-box-wrapper"> 656 <?php if ( $has_icon ) : ?> 657 <div class="elementor-icon-box-icon"> 658 <<?php Utils::print_validated_html_tag( $icon_tag ); ?> <?php $this->print_render_attribute_string( 'icon' ); ?> <?php $this->print_render_attribute_string( 'link' ); ?>> 659 <?php 660 if ( $is_new || $migrated ) { 661 Icons_Manager::render_icon( $settings['selected_icon'], [ 'aria-hidden' => 'true' ] ); 662 } elseif ( ! empty( $settings['icon'] ) ) { 663 ?><i <?php $this->print_render_attribute_string( 'i' ); ?>></i><?php 664 } 665 ?> 666 </<?php Utils::print_validated_html_tag( $icon_tag ); ?>> 667 </div> 668 <?php endif; ?> 669 <div class="elementor-icon-box-content"> 670 <<?php Utils::print_validated_html_tag( $settings['title_size'] ); ?> class="elementor-icon-box-title"> 671 <<?php Utils::print_validated_html_tag( $icon_tag ); ?> <?php $this->print_render_attribute_string( 'link' ); ?> <?php $this->print_render_attribute_string( 'title_text' ); ?>> 672 <?php $this->print_unescaped_setting( 'title_text' ); ?> 673 </<?php Utils::print_validated_html_tag( $icon_tag ); ?>> 674 </<?php Utils::print_validated_html_tag( $settings['title_size'] ); ?>> 675 <?php if ( ! Utils::is_empty( $settings['description_text'] ) ) : ?> 676 <p <?php $this->print_render_attribute_string( 'description_text' ); ?>> 677 <?php $this->print_unescaped_setting( 'description_text' ); ?> 678 </p> 679 <?php endif; ?> 680 </div> 681 </div> 682 <?php 683 } 684 685 /** 686 * Render icon box widget output in the editor. 687 * 688 * Written as a Backbone JavaScript template and used to generate the live preview. 689 * 690 * @since 2.9.0 691 * @access protected 692 */ 693 protected function content_template() { 694 ?> 695 <# 696 var link = settings.link.url ? 'href="' + settings.link.url + '"' : '', 697 iconTag = link ? 'a' : 'span', 698 iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, { 'aria-hidden': true }, 'i' , 'object' ), 699 migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' ); 700 701 view.addRenderAttribute( 'description_text', 'class', 'elementor-icon-box-description' ); 702 703 view.addInlineEditingAttributes( 'title_text', 'none' ); 704 view.addInlineEditingAttributes( 'description_text' ); 705 #> 706 <div class="elementor-icon-box-wrapper"> 707 <?php // settings.icon is needed for older version ?> 708 <# if ( settings.icon || settings.selected_icon.value ) { #> 709 <div class="elementor-icon-box-icon"> 710 <{{{ iconTag + ' ' + link }}} class="elementor-icon elementor-animation-{{ settings.hover_animation }}"> 711 <# if ( iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #> 712 {{{ iconHTML.value }}} 713 <# } else { #> 714 <i class="{{ settings.icon }}" aria-hidden="true"></i> 715 <# } #> 716 </{{{ iconTag }}}> 717 </div> 718 <# } #> 719 <div class="elementor-icon-box-content"> 720 <# var titleSizeTag = elementor.helpers.validateHTMLTag( settings.title_size ); #> 721 <{{{ titleSizeTag }}} class="elementor-icon-box-title"> 722 <{{{ iconTag + ' ' + link }}} {{{ view.getRenderAttributeString( 'title_text' ) }}}>{{{ settings.title_text }}}</{{{ iconTag }}}> 723 </{{{ titleSizeTag }}}> 724 <# if ( settings.description_text ) { #> 725 <p {{{ view.getRenderAttributeString( 'description_text' ) }}}>{{{ settings.description_text }}}</p> 726 <# } #> 727 </div> 728 </div> 729 <?php 730 } 731 732 public function on_import( $element ) { 733 return Icons_Manager::on_import_migration( $element, 'icon', 'selected_icon', true ); 734 } 735 }