Changeset 3458205
- Timestamp:
- 02/10/2026 04:00:10 PM (12 days ago)
- Location:
- a1-tools/trunk
- Files:
-
- 3 edited
-
a1-tools.php (modified) (2 diffs)
-
includes/class-a1-tools-elementor-widget.php (modified) (21 diffs)
-
readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
a1-tools/trunk/a1-tools.php
r3458190 r3458205 4 4 * Plugin URI: https://tools.a-1chimney.com 5 5 * Description: Connects your WordPress site to the A1 Tools platform for centralized management of contact information, social media links, and business details. 6 * Version: 1.4. 76 * Version: 1.4.8 7 7 * Requires at least: 5.0 8 8 * Requires PHP: 7.4 … … 21 21 22 22 // Plugin constants. 23 define( 'A1TOOLS_VERSION', '1.4. 7' );23 define( 'A1TOOLS_VERSION', '1.4.8' ); 24 24 define( 'A1TOOLS_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 25 25 define( 'A1TOOLS_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); -
a1-tools/trunk/includes/class-a1-tools-elementor-widget.php
r3458190 r3458205 4 4 * 5 5 * Provides an Elementor widget for Social Media Icons with full styling controls. 6 * Uses Elementor's selectors system for CSS so global colors work properly. 6 7 * 7 8 * @package A1_Tools … … 90 91 /** 91 92 * Register widget controls. 93 * 94 * Uses Elementor's selectors system for all color controls so that 95 * global colors are properly resolved on both frontend and editor. 92 96 */ 93 97 protected function register_controls() { … … 166 170 'square' => __( 'Square', 'a1-tools' ), 167 171 ), 172 'selectors_dictionary' => array( 173 'rounded' => '8px', 174 'circle' => '50%', 175 'square' => '0', 176 ), 177 'selectors' => array( 178 '{{WRAPPER}} .a1tools-social-icon' => 'border-radius: {{VALUE}};', 179 ), 168 180 ) 169 181 ); … … 186 198 'size' => 40, 187 199 ), 200 'selectors' => array( 201 '{{WRAPPER}} .a1tools-social-icon' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}}; line-height: {{SIZE}}{{UNIT}};', 202 ), 188 203 ) 189 204 ); … … 206 221 'size' => 18, 207 222 ), 223 'selectors' => array( 224 '{{WRAPPER}} .a1tools-social-icon' => 'font-size: {{SIZE}}{{UNIT}};', 225 ), 208 226 ) 209 227 ); … … 226 244 'size' => 8, 227 245 ), 246 'selectors' => array( 247 '{{WRAPPER}} .a1tools-social-icon' => 'margin: 0 calc({{SIZE}}{{UNIT}} / 2) {{SIZE}}{{UNIT}};', 248 ), 228 249 ) 229 250 ); … … 249 270 ), 250 271 'default' => 'left', 251 ) 252 ); 253 254 // Custom Colors Section (only shown when style is "custom") 272 'selectors' => array( 273 '{{WRAPPER}} .a1tools-social-icons-styled' => 'text-align: {{VALUE}};', 274 ), 275 ) 276 ); 277 278 // Custom Colors - Normal state 279 $this->add_control( 280 'custom_colors_heading', 281 array( 282 'label' => __( 'Custom Colors', 'a1-tools' ), 283 'type' => \Elementor\Controls_Manager::HEADING, 284 'separator' => 'before', 285 'condition' => array( 286 'icon_style' => 'custom', 287 ), 288 ) 289 ); 290 255 291 $this->add_control( 256 292 'custom_icon_color', … … 262 298 'icon_style' => 'custom', 263 299 ), 300 'selectors' => array( 301 '{{WRAPPER}} .a1tools-social-icon' => 'color: {{VALUE}};', 302 '{{WRAPPER}} .a1tools-social-icon i' => 'color: {{VALUE}};', 303 ), 264 304 ) 265 305 ); … … 274 314 'icon_style' => 'custom', 275 315 ), 316 'selectors' => array( 317 '{{WRAPPER}} .a1tools-social-icon' => 'background-color: {{VALUE}};', 318 ), 276 319 ) 277 320 ); … … 285 328 'condition' => array( 286 329 'icon_style' => 'custom', 330 ), 331 'selectors' => array( 332 '{{WRAPPER}} .a1tools-social-icon' => 'border-color: {{VALUE}};', 287 333 ), 288 334 ) … … 309 355 'icon_style' => 'custom', 310 356 ), 357 'selectors' => array( 358 '{{WRAPPER}} .a1tools-social-icon' => 'border-width: {{SIZE}}{{UNIT}}; border-style: solid;', 359 ), 360 ) 361 ); 362 363 // Custom Colors - Hover state 364 $this->add_control( 365 'custom_hover_heading', 366 array( 367 'label' => __( 'Hover Colors', 'a1-tools' ), 368 'type' => \Elementor\Controls_Manager::HEADING, 369 'separator' => 'before', 370 'condition' => array( 371 'icon_style' => 'custom', 372 ), 311 373 ) 312 374 ); … … 321 383 'icon_style' => 'custom', 322 384 ), 385 'selectors' => array( 386 '{{WRAPPER}} .a1tools-social-icon:hover' => 'color: {{VALUE}};', 387 '{{WRAPPER}} .a1tools-social-icon:hover i' => 'color: {{VALUE}};', 388 ), 323 389 ) 324 390 ); … … 333 399 'icon_style' => 'custom', 334 400 ), 401 'selectors' => array( 402 '{{WRAPPER}} .a1tools-social-icon:hover' => 'background-color: {{VALUE}};', 403 ), 335 404 ) 336 405 ); … … 344 413 'condition' => array( 345 414 'icon_style' => 'custom', 415 ), 416 'selectors' => array( 417 '{{WRAPPER}} .a1tools-social-icon:hover' => 'border-color: {{VALUE}};', 346 418 ), 347 419 ) … … 372 444 'pulse' => __( 'Pulse', 'a1-tools' ), 373 445 ), 446 'prefix_class' => 'a1tools-hover-', 374 447 ) 375 448 ); … … 380 453 /** 381 454 * Render widget output on the frontend. 455 * 456 * Custom colors are handled entirely by Elementor's selectors system. 457 * Only non-custom styles (Official, Outline, etc.) need inline styles 458 * because each icon has a different platform-specific color. 382 459 */ 383 460 protected function render() { … … 389 466 } 390 467 391 // Get settings 392 $style = ! empty( $settings['icon_style'] ) ? $settings['icon_style'] : 'default'; 393 $shape = ! empty( $settings['shape'] ) ? $settings['shape'] : 'rounded'; 394 $size = ! empty( $settings['size']['size'] ) ? (int) $settings['size']['size'] : 40; 395 $icon_size = ! empty( $settings['icon_size']['size'] ) ? (int) $settings['icon_size']['size'] : 18; 396 $spacing = isset( $settings['spacing']['size'] ) ? (int) $settings['spacing']['size'] : 8; 397 $alignment = ! empty( $settings['alignment'] ) ? $settings['alignment'] : 'left'; 398 $hover_effect = ! empty( $settings['hover_effect'] ) ? $settings['hover_effect'] : 'scale'; 399 400 // Custom style colors - these can be hex colors OR CSS variables from Elementor global colors 401 $custom_icon_color = ! empty( $settings['custom_icon_color'] ) ? $settings['custom_icon_color'] : '#ffffff'; 402 $custom_bg_color = ! empty( $settings['custom_bg_color'] ) ? $settings['custom_bg_color'] : '#F7941E'; 403 $custom_border_color = ! empty( $settings['custom_border_color'] ) ? $settings['custom_border_color'] : ''; 404 $custom_border_width = isset( $settings['custom_border_width']['size'] ) ? (int) $settings['custom_border_width']['size'] : 0; 405 $custom_hover_icon_color = ! empty( $settings['custom_hover_icon_color'] ) ? $settings['custom_hover_icon_color'] : ''; 406 $custom_hover_bg_color = ! empty( $settings['custom_hover_bg_color'] ) ? $settings['custom_hover_bg_color'] : ''; 407 $custom_hover_border_color = ! empty( $settings['custom_hover_border_color'] ) ? $settings['custom_hover_border_color'] : ''; 408 409 // Generate unique ID for this widget instance 410 $widget_id = 'a1tools-elementor-' . $this->get_id(); 411 412 // Border radius based on shape 413 $border_radius = '8px'; 414 if ( 'circle' === $shape ) { 415 $border_radius = '50%'; 416 } elseif ( 'square' === $shape ) { 417 $border_radius = '0'; 468 $style = ! empty( $settings['icon_style'] ) ? $settings['icon_style'] : 'default'; 469 470 // Base CSS for all styles (layout only - colors handled by selectors or inline) 471 $base_css = '.a1tools-social-icons-styled { line-height: 0; }'; 472 $base_css .= '.a1tools-social-icons-styled .a1tools-social-icon { '; 473 $base_css .= 'display: inline-flex; align-items: center; justify-content: center;'; 474 $base_css .= 'vertical-align: middle; text-decoration: none !important;'; 475 $base_css .= 'transition: all 0.3s ease; box-sizing: border-box;'; 476 $base_css .= '}'; 477 $base_css .= '.a1tools-social-icons-styled .a1tools-social-icon i { '; 478 $base_css .= 'color: inherit; line-height: 1;'; 479 $base_css .= '}'; 480 481 // Hover effect CSS (using prefix_class a1tools-hover-*) 482 $base_css .= '.a1tools-hover-scale .a1tools-social-icon:hover { transform: scale(1.1); }'; 483 $base_css .= '.a1tools-hover-lift .a1tools-social-icon:hover { transform: translateY(-3px); box-shadow: 0 4px 12px rgba(0,0,0,0.2); }'; 484 $base_css .= '.a1tools-hover-rotate .a1tools-social-icon:hover { transform: rotate(15deg); }'; 485 $base_css .= '.a1tools-hover-pulse .a1tools-social-icon:hover { animation: a1tools-pulse 0.5s ease; }'; 486 $base_css .= '@keyframes a1tools-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.15); } }'; 487 488 // Style-specific base CSS for non-custom styles 489 if ( 'default' === $style || 'official' === $style ) { 490 $base_css .= '.a1tools-social-icons-styled .a1tools-social-icon { color: #fff; }'; 491 $base_css .= '.a1tools-social-icons-styled .a1tools-social-icon i { color: #fff; }'; 492 } elseif ( 'outline' === $style ) { 493 $base_css .= '.a1tools-social-icons-styled .a1tools-social-icon { background: transparent; border: 2px solid; }'; 494 } elseif ( 'minimal' === $style ) { 495 $base_css .= '.a1tools-social-icons-styled .a1tools-social-icon { background: transparent; }'; 496 } elseif ( 'light' === $style ) { 497 $base_css .= '.a1tools-social-icons-styled .a1tools-social-icon { background: #f5f5f5; }'; 498 } elseif ( 'dark' === $style ) { 499 $base_css .= '.a1tools-social-icons-styled .a1tools-social-icon { background: #333; color: #fff; }'; 500 $base_css .= '.a1tools-social-icons-styled .a1tools-social-icon i { color: #fff; }'; 418 501 } 419 502 420 // Build CSS - use high specificity selectors to ensure styles apply 421 $selector = '#' . esc_attr( $widget_id ); 422 423 $css = $selector . ' { text-align:' . esc_attr( $alignment ) . '; line-height: 0; }'; 424 $css .= $selector . ' .a1tools-social-icon { '; 425 $css .= 'width:' . $size . 'px;'; 426 $css .= 'height:' . $size . 'px;'; 427 $css .= 'margin:0 ' . ( $spacing / 2 ) . 'px ' . $spacing . 'px;'; 428 $css .= 'font-size:' . $icon_size . 'px;'; 429 $css .= 'line-height:' . $size . 'px;'; 430 $css .= 'display:inline-flex;'; 431 $css .= 'align-items:center;'; 432 $css .= 'justify-content:center;'; 433 $css .= 'vertical-align:middle;'; 434 $css .= 'text-decoration:none;'; 435 $css .= 'transition:all 0.3s ease;'; 436 $css .= 'border-radius:' . esc_attr( $border_radius ) . ';'; 437 $css .= 'box-sizing:border-box;'; 438 $css .= '}'; 439 440 // Icon element styling - ensure it inherits color properly 441 $css .= $selector . ' .a1tools-social-icon i { '; 442 $css .= 'display:flex;'; 443 $css .= 'align-items:center;'; 444 $css .= 'justify-content:center;'; 445 $css .= 'width:100%;'; 446 $css .= 'height:100%;'; 447 $css .= 'line-height:1;'; 448 $css .= '}'; 449 450 // Style-specific CSS 451 if ( 'custom' === $style ) { 452 // Apply custom colors with high specificity 453 $css .= $selector . ' .a1tools-social-icon,'; 454 $css .= $selector . ' .a1tools-social-icon i { '; 455 $css .= 'color:' . $custom_icon_color . ' !important;'; 456 $css .= '}'; 457 $css .= $selector . ' .a1tools-social-icon { '; 458 $css .= 'background-color:' . $custom_bg_color . ' !important;'; 459 if ( $custom_border_width > 0 && $custom_border_color ) { 460 $css .= 'border:' . $custom_border_width . 'px solid ' . $custom_border_color . ' !important;'; 461 } else { 462 $css .= 'border:none;'; 463 } 464 $css .= '}'; 465 466 // Custom hover colors 467 if ( $custom_hover_icon_color || $custom_hover_bg_color || $custom_hover_border_color ) { 468 $css .= $selector . ' .a1tools-social-icon:hover,'; 469 $css .= $selector . ' .a1tools-social-icon:hover i { '; 470 if ( $custom_hover_icon_color ) { 471 $css .= 'color:' . $custom_hover_icon_color . ' !important;'; 472 } 473 $css .= '}'; 474 $css .= $selector . ' .a1tools-social-icon:hover { '; 475 if ( $custom_hover_bg_color ) { 476 $css .= 'background-color:' . $custom_hover_bg_color . ' !important;'; 477 } 478 if ( $custom_hover_border_color && $custom_border_width > 0 ) { 479 $css .= 'border-color:' . $custom_hover_border_color . ' !important;'; 480 } 481 $css .= '}'; 482 } 483 } elseif ( 'default' === $style || 'official' === $style ) { 484 $css .= $selector . ' .a1tools-social-icon,' . $selector . ' .a1tools-social-icon i { color: #fff; }'; 485 } elseif ( 'outline' === $style ) { 486 $css .= $selector . ' .a1tools-social-icon { background: transparent; border: 2px solid; }'; 487 } elseif ( 'minimal' === $style ) { 488 $css .= $selector . ' .a1tools-social-icon { background: transparent; }'; 489 } elseif ( 'light' === $style ) { 490 $css .= $selector . ' .a1tools-social-icon { background: #f5f5f5; }'; 491 } elseif ( 'dark' === $style ) { 492 $css .= $selector . ' .a1tools-social-icon,' . $selector . ' .a1tools-social-icon i { background: #333; color: #fff; }'; 493 } 494 495 // Hover effects 496 if ( 'scale' === $hover_effect ) { 497 $css .= $selector . ' .a1tools-social-icon:hover { transform: scale(1.1); }'; 498 } elseif ( 'lift' === $hover_effect ) { 499 $css .= $selector . ' .a1tools-social-icon:hover { transform: translateY(-3px); box-shadow: 0 4px 12px rgba(0,0,0,0.2); }'; 500 } elseif ( 'rotate' === $hover_effect ) { 501 $css .= $selector . ' .a1tools-social-icon:hover { transform: rotate(15deg); }'; 502 } elseif ( 'pulse' === $hover_effect ) { 503 $css .= $selector . ' .a1tools-social-icon:hover { animation: a1tools-pulse 0.5s ease; }'; 504 $css .= '@keyframes a1tools-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.15); } }'; 505 } 506 507 // Output inline CSS 508 echo '<style>' . $css . '</style>'; 503 // Output base CSS once 504 echo '<style>' . $base_css . '</style>'; 509 505 510 506 // Output HTML 511 echo '<div id="' . esc_attr( $widget_id ) . '"class="a1tools-social-icons-styled">';507 echo '<div class="a1tools-social-icons-styled">'; 512 508 513 509 foreach ( $platforms as $key => $data ) { 514 510 $inline_style = ''; 515 511 516 // For non-custom styles, apply p latform-specific colors512 // For non-custom styles, apply per-platform colors via inline style 517 513 if ( 'custom' !== $style ) { 518 514 $item_color = $data['color']; … … 526 522 } 527 523 528 echo '<a href="' . esc_url( $data['url'] ) . '" class="a1tools-social-icon" target="_blank" rel="noopener noreferrer" title="' . esc_attr( $data['label'] ) . '" style="' . esc_attr( $inline_style ) . '">'; 524 echo '<a href="' . esc_url( $data['url'] ) . '" class="a1tools-social-icon" target="_blank" rel="noopener noreferrer" title="' . esc_attr( $data['label'] ) . '"'; 525 if ( $inline_style ) { 526 echo ' style="' . esc_attr( $inline_style ) . '"'; 527 } 528 echo '>'; 529 529 echo '<i class="' . esc_attr( $data['icon'] ) . '" aria-hidden="true"></i>'; 530 530 echo '<span class="screen-reader-text">' . esc_html( $data['label'] ) . '</span>'; … … 537 537 /** 538 538 * Render widget output in the editor. 539 * Uses PHP to get actual available platforms. 539 * 540 * The editor template handles the live preview. Colors for "Custom" style 541 * are applied via Elementor's selectors (same as frontend). Non-custom styles 542 * use inline styles for per-platform colors. 540 543 */ 541 544 protected function content_template() { … … 546 549 $js_platforms = array(); 547 550 foreach ( $platforms as $key => $data ) { 548 // Extract just the icon class name (e.g., "fa-facebook-f" from "fab fa-facebook-f") 549 $icon_parts = explode( ' ', $data['icon'] ); 550 $icon_class = end( $icon_parts ); 551 $icon_parts = explode( ' ', $data['icon'] ); 552 $icon_class = end( $icon_parts ); 551 553 $icon_prefix = count( $icon_parts ) > 1 ? $icon_parts[0] : 'fab'; 552 554 … … 571 573 <# 572 574 var style = settings.icon_style || 'default'; 573 var shape = settings.shape || 'rounded';574 var size = settings.size.size || 40;575 var iconSize = settings.icon_size.size || 18;576 var spacing = settings.spacing.size || 8;577 var alignment = settings.alignment || 'left';578 var hoverEffect = settings.hover_effect || 'scale';579 580 // Custom style colors581 var customIconColor = settings.custom_icon_color || '#ffffff';582 var customBgColor = settings.custom_bg_color || '#F7941E';583 var customBorderColor = settings.custom_border_color || '';584 var customBorderWidth = settings.custom_border_width ? settings.custom_border_width.size : 0;585 var customHoverIconColor = settings.custom_hover_icon_color || '';586 var customHoverBgColor = settings.custom_hover_bg_color || '';587 var customHoverBorderColor = settings.custom_hover_border_color || '';588 589 var borderRadius = shape === 'circle' ? '50%' : (shape === 'rounded' ? '8px' : '0');590 var justifyContent = alignment === 'center' ? 'center' : (alignment === 'right' ? 'flex-end' : 'flex-start');591 592 // Generate unique class for this widget instance593 var widgetClass = 'a1tools-editor-' + view.getID();594 575 595 576 // Actual available platforms from the site 596 577 var platforms = <?php echo wp_json_encode( $js_platforms ); ?>; 597 598 // Build hover CSS599 var hoverCSS = '';600 if (hoverEffect === 'scale') {601 hoverCSS += '.' + widgetClass + ' .a1tools-ed-icon:hover { transform: scale(1.1); }';602 } else if (hoverEffect === 'lift') {603 hoverCSS += '.' + widgetClass + ' .a1tools-ed-icon:hover { transform: translateY(-3px); box-shadow: 0 4px 12px rgba(0,0,0,0.2); }';604 } else if (hoverEffect === 'rotate') {605 hoverCSS += '.' + widgetClass + ' .a1tools-ed-icon:hover { transform: rotate(15deg); }';606 } else if (hoverEffect === 'pulse') {607 hoverCSS += '.' + widgetClass + ' .a1tools-ed-icon:hover { animation: a1tools-pulse 0.5s ease; }';608 hoverCSS += '@keyframes a1tools-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.15); } }';609 }610 611 // Custom hover colors612 if (style === 'custom' && (customHoverIconColor || customHoverBgColor || customHoverBorderColor)) {613 var hoverRules = '';614 if (customHoverIconColor) {615 hoverRules += 'color:' + customHoverIconColor + ' !important;';616 }617 if (customHoverBgColor) {618 hoverRules += 'background-color:' + customHoverBgColor + ' !important;';619 }620 if (customHoverBorderColor && customBorderWidth > 0) {621 hoverRules += 'border-color:' + customHoverBorderColor + ' !important;';622 }623 if (hoverRules) {624 hoverCSS += '.' + widgetClass + ' .a1tools-ed-icon:hover { ' + hoverRules + ' }';625 if (customHoverIconColor) {626 hoverCSS += '.' + widgetClass + ' .a1tools-ed-icon:hover i { color:' + customHoverIconColor + ' !important; }';627 }628 }629 }630 578 #> 631 <style>{{{ hoverCSS }}}</style> 632 <div class="a1tools-social-icons-wrapper {{ widgetClass }}" style="display: flex; flex-wrap: wrap; gap: {{ spacing }}px; justify-content: {{ justifyContent }};"> 579 <div class="a1tools-social-icons-styled"> 633 580 <# _.each(platforms, function(platform) { 634 var bgColor = ''; 635 var iconColor = ''; 636 var border = 'none'; 637 638 if (style === 'custom') { 639 bgColor = customBgColor; 640 iconColor = customIconColor; 641 if (customBorderWidth > 0 && customBorderColor) { 642 border = customBorderWidth + 'px solid ' + customBorderColor; 643 } 644 } else { 581 var inlineStyle = ''; 582 583 // For non-custom styles, apply per-platform colors inline 584 if (style !== 'custom') { 645 585 switch(style) { 646 586 case 'outline': 647 bgColor = 'transparent'; 648 iconColor = platform.color; 649 border = '2px solid ' + platform.color; 587 inlineStyle = 'background:transparent; border:2px solid ' + platform.color + '; color:' + platform.color + ';'; 650 588 break; 651 589 case 'minimal': 652 bgColor = 'transparent'; 653 iconColor = platform.color; 590 inlineStyle = 'background:transparent; color:' + platform.color + ';'; 654 591 break; 655 592 case 'light': 656 bgColor = '#f5f5f5'; 657 iconColor = platform.color; 593 inlineStyle = 'background:#f5f5f5; color:' + platform.color + ';'; 658 594 break; 659 595 case 'dark': 660 bgColor = '#333'; 661 iconColor = '#fff'; 596 inlineStyle = 'background:#333; color:#fff;'; 662 597 break; 663 598 default: 664 bgColor = platform.color; 665 iconColor = '#fff'; 599 inlineStyle = 'background-color:' + platform.color + '; color:#fff;'; 666 600 } 667 601 } 668 602 #> 669 <a href="#" class="a1tools- ed-icon" style="display: inline-flex; align-items: center; justify-content: center; width: {{ size }}px; height: {{ size }}px; background: {{ bgColor }}; color: {{ iconColor }}; border-radius: {{ borderRadius }}; border: {{ border }}; text-decoration: none; transition: all 0.3s ease; box-sizing: border-box;">670 <i class="{{ platform.prefix }} {{ platform.icon }}" style=" font-size: {{ iconSize }}px; color: inherit;"></i>603 <a href="#" class="a1tools-social-icon" style="display:inline-flex; align-items:center; justify-content:center; vertical-align:middle; text-decoration:none; transition:all 0.3s ease; box-sizing:border-box; {{ inlineStyle }}"> 604 <i class="{{ platform.prefix }} {{ platform.icon }}" style="color:inherit; line-height:1;"></i> 671 605 </a> 672 606 <# }); #> -
a1-tools/trunk/readme.txt
r3458190 r3458205 4 4 Requires at least: 5.0 5 5 Tested up to: 6.9 6 Stable tag: 1.4. 76 Stable tag: 1.4.8 7 7 Requires PHP: 7.4 8 8 License: GPLv2 or later … … 151 151 152 152 == Changelog == 153 154 = 1.4.8 = 155 * Rewrote Elementor widget to use Elementor's selectors system for all color controls 156 * Fixed Elementor global colors not applying (colors were empty when using global color picker) 157 * Fixed alignment control not working in editor or frontend 158 * Fixed icons shifting position when widget is not selected in editor 159 * Hover effects now use CSS class-based approach (prefix_class) for reliability in both editor and frontend 160 * Size, spacing, shape, and icon size controls now use Elementor selectors for instant preview updates 153 161 154 162 = 1.4.7 =
Note: See TracChangeset
for help on using the changeset viewer.