PluginProbe
Elementor Website Builder – more than just a page builder / 3.24.0-dev3
Elementor Website Builder – more than just a page builder v3.24.0-dev3
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / modules / nested-tabs / widgets / nested-tabs.php

nested-tabs.php in Elementor Website Builder – more than just a page builder 3.24.0-dev3, at modules/nested-tabs/widgets/nested-tabs.php

1,338 lines 39.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Modules\NestedTabs\Widgets;
3
4 use Elementor\Controls_Manager;
5 use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
6 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
7 use Elementor\Group_Control_Background;
8 use Elementor\Group_Control_Border;
9 use Elementor\Group_Control_Box_Shadow;
10 use Elementor\Group_Control_Text_Shadow;
11 use Elementor\Group_Control_Text_Stroke;
12 use Elementor\Group_Control_Typography;
13 use Elementor\Icons_Manager;
14 use Elementor\Modules\NestedElements\Base\Widget_Nested_Base;
15 use Elementor\Modules\NestedElements\Controls\Control_Nested_Repeater;
16 use Elementor\Plugin;
17 use Elementor\Repeater;
18
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit; // Exit if accessed directly
21 }
22
23 class NestedTabs extends Widget_Nested_Base {
24
25 private $tab_item_settings = [];
26
27 public function get_name() {
28 return 'nested-tabs';
29 }
30
31 public function get_title() {
32 return esc_html__( 'Tabs', 'elementor' );
33 }
34
35 public function get_icon() {
36 return 'eicon-tabs';
37 }
38
39 public function get_keywords() {
40 return [ 'nested', 'tabs', 'accordion', 'toggle' ];
41 }
42
43 public function get_style_depends(): array {
44 return [ 'widget-nested-tabs' ];
45 }
46
47 protected function tab_content_container( int $index ) {
48 return [
49 'elType' => 'container',
50 'settings' => [
51 '_title' => sprintf( __( 'Tab #%s', 'elementor' ), $index ),
52 'content_width' => 'full',
53 ],
54 ];
55 }
56
57 protected function get_default_children_elements() {
58 return [
59 $this->tab_content_container( 1 ),
60 $this->tab_content_container( 2 ),
61 $this->tab_content_container( 3 ),
62 ];
63 }
64
65 protected function get_default_repeater_title_setting_key() {
66 return 'tab_title';
67 }
68
69 protected function get_default_children_title() {
70 return esc_html__( 'Tab #%d', 'elementor' );
71 }
72
73 protected function get_default_children_placeholder_selector() {
74 return '.e-n-tabs-content';
75 }
76
77 protected function get_html_wrapper_class() {
78 return 'elementor-widget-n-tabs';
79 }
80
81 protected function register_controls() {
82 $start = is_rtl() ? 'right' : 'left';
83 $end = is_rtl() ? 'left' : 'right';
84 $start_logical = is_rtl() ? 'end' : 'start';
85 $end_logical = is_rtl() ? 'start' : 'end';
86 $heading_selector_non_touch_device = '{{WRAPPER}}.elementor-widget-n-tabs > .elementor-widget-container > .e-n-tabs[data-touch-mode="false"] > .e-n-tabs-heading';
87 $heading_selector_touch_device = '{{WRAPPER}}.elementor-widget-n-tabs > .elementor-widget-container > .e-n-tabs[data-touch-mode="true"] > .e-n-tabs-heading';
88 $heading_selector = '{{WRAPPER}}.elementor-widget-n-tabs > .elementor-widget-container > .e-n-tabs > .e-n-tabs-heading';
89 $content_selector = ':where( {{WRAPPER}}.elementor-widget-n-tabs > .elementor-widget-container > .e-n-tabs > .e-n-tabs-content ) > .e-con';
90
91 $this->start_controls_section( 'section_tabs', [
92 'label' => esc_html__( 'Tabs', 'elementor' ),
93 ] );
94
95 $repeater = new Repeater();
96
97 $repeater->add_control( 'tab_title', [
98 'label' => esc_html__( 'Title', 'elementor' ),
99 'type' => Controls_Manager::TEXT,
100 'default' => esc_html__( 'Tab Title', 'elementor' ),
101 'placeholder' => esc_html__( 'Tab Title', 'elementor' ),
102 'label_block' => true,
103 'dynamic' => [
104 'active' => true,
105 ],
106 ] );
107
108 $repeater->add_control(
109 'tab_icon',
110 [
111 'label' => esc_html__( 'Icon', 'elementor' ),
112 'type' => Controls_Manager::ICONS,
113 'fa4compatibility' => 'icon',
114 'skin' => 'inline',
115 'label_block' => false,
116 ]
117 );
118
119 $repeater->add_control(
120 'tab_icon_active',
121 [
122 'label' => esc_html__( 'Active Icon', 'elementor' ),
123 'type' => Controls_Manager::ICONS,
124 'fa4compatibility' => 'icon',
125 'skin' => 'inline',
126 'label_block' => false,
127 'condition' => [
128 'tab_icon[value]!' => '',
129 ],
130 ]
131 );
132
133 $repeater->add_control(
134 'element_id',
135 [
136 'label' => esc_html__( 'CSS ID', 'elementor' ),
137 'type' => Controls_Manager::TEXT,
138 'default' => '',
139 'ai' => [
140 'active' => false,
141 ],
142 'dynamic' => [
143 'active' => true,
144 ],
145 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
146 'style_transfer' => false,
147 'classes' => 'elementor-control-direction-ltr',
148 ]
149 );
150
151 $this->add_control( 'tabs', [
152 'label' => esc_html__( 'Tabs Items', 'elementor' ),
153 'type' => Control_Nested_Repeater::CONTROL_TYPE,
154 'fields' => $repeater->get_controls(),
155 'default' => [
156 [
157 'tab_title' => esc_html__( 'Tab #1', 'elementor' ),
158 ],
159 [
160 'tab_title' => esc_html__( 'Tab #2', 'elementor' ),
161 ],
162 [
163 'tab_title' => esc_html__( 'Tab #3', 'elementor' ),
164 ],
165 ],
166 'title_field' => '{{{ tab_title }}}',
167 'button_text' => 'Add Tab',
168 ] );
169
170 $styling_block_start = '--n-tabs-direction: column; --n-tabs-heading-direction: row; --n-tabs-heading-width: initial; --n-tabs-title-flex-basis: content; --n-tabs-title-flex-shrink: 0;';
171 $styling_block_end = '--n-tabs-direction: column-reverse; --n-tabs-heading-direction: row; --n-tabs-heading-width: initial; --n-tabs-title-flex-basis: content; --n-tabs-title-flex-shrink: 0';
172 $styling_inline_end = '--n-tabs-direction: row-reverse; --n-tabs-heading-direction: column; --n-tabs-heading-width: 240px; --n-tabs-title-flex-basis: initial; --n-tabs-title-flex-shrink: initial;';
173 $styling_inline_start = '--n-tabs-direction: row; --n-tabs-heading-direction: column; --n-tabs-heading-width: 240px; --n-tabs-title-flex-basis: initial; --n-tabs-title-flex-shrink: initial;';
174
175 $this->add_responsive_control( 'tabs_direction', [
176 'label' => esc_html__( 'Direction', 'elementor' ),
177 'type' => Controls_Manager::CHOOSE,
178 'options' => [
179 'block-start' => [
180 'title' => esc_html__( 'Above', 'elementor' ),
181 'icon' => 'eicon-v-align-top',
182 ],
183 'block-end' => [
184 'title' => esc_html__( 'Below', 'elementor' ),
185 'icon' => 'eicon-v-align-bottom',
186 ],
187 'inline-end' => [
188 'title' => esc_html__( 'After', 'elementor' ),
189 'icon' => 'eicon-h-align-' . $end,
190 ],
191 'inline-start' => [
192 'title' => esc_html__( 'Before', 'elementor' ),
193 'icon' => 'eicon-h-align-' . $start,
194 ],
195 ],
196 'separator' => 'before',
197 'selectors_dictionary' => [
198 'block-start' => $styling_block_start,
199 'block-end' => $styling_block_end,
200 'inline-end' => $styling_inline_end,
201 'inline-start' => $styling_inline_start,
202 // Styling duplication for BC reasons.
203 'top' => $styling_block_start,
204 'bottom' => $styling_block_end,
205 'end' => $styling_inline_end,
206 'start' => $styling_inline_start,
207 ],
208 'selectors' => [
209 '{{WRAPPER}}' => '{{VALUE}}',
210 ],
211 'control_type' => 'content',
212 ] );
213
214 $this->add_responsive_control( 'tabs_justify_horizontal', [
215 'label' => esc_html__( 'Justify', 'elementor' ),
216 'type' => Controls_Manager::CHOOSE,
217 'options' => [
218 'start' => [
219 'title' => esc_html__( 'Start', 'elementor' ),
220 'icon' => "eicon-align-$start_logical-h",
221 ],
222 'center' => [
223 'title' => esc_html__( 'Center', 'elementor' ),
224 'icon' => 'eicon-align-center-h',
225 ],
226 'end' => [
227 'title' => esc_html__( 'End', 'elementor' ),
228 'icon' => "eicon-align-$end_logical-h",
229 ],
230 'stretch' => [
231 'title' => esc_html__( 'Stretch', 'elementor' ),
232 'icon' => 'eicon-align-stretch-h',
233 ],
234 ],
235 'selectors_dictionary' => [
236 'start' => '--n-tabs-heading-justify-content: flex-start; --n-tabs-title-width: initial; --n-tabs-title-height: initial; --n-tabs-title-align-items: center; --n-tabs-title-flex-grow: 0;',
237 'center' => '--n-tabs-heading-justify-content: center; --n-tabs-title-width: initial; --n-tabs-title-height: initial; --n-tabs-title-align-items: center; --n-tabs-title-flex-grow: 0;',
238 'end' => '--n-tabs-heading-justify-content: flex-end; --n-tabs-title-width: initial; --n-tabs-title-height: initial; --n-tabs-title-align-items: center; --n-tabs-title-flex-grow: 0;',
239 'stretch' => '--n-tabs-heading-justify-content: initial; --n-tabs-title-width: 100%; --n-tabs-title-height: initial; --n-tabs-title-align-items: center; --n-tabs-title-flex-grow: 1;',
240 ],
241 'selectors' => [
242 '{{WRAPPER}}' => '{{VALUE}}',
243 ],
244 'condition' => [
245 'tabs_direction' => [
246 '',
247 'block-start',
248 'block-end',
249 'top',
250 'bottom',
251 ],
252 ],
253 'frontend_available' => true,
254 ] );
255
256 $this->add_responsive_control( 'tabs_justify_vertical', [
257 'label' => esc_html__( 'Justify', 'elementor' ),
258 'type' => Controls_Manager::CHOOSE,
259 'options' => [
260 'start' => [
261 'title' => esc_html__( 'Start', 'elementor' ),
262 'icon' => 'eicon-align-start-v',
263 ],
264 'center' => [
265 'title' => esc_html__( 'Center', 'elementor' ),
266 'icon' => 'eicon-align-center-v',
267 ],
268 'end' => [
269 'title' => esc_html__( 'End', 'elementor' ),
270 'icon' => 'eicon-align-end-v',
271 ],
272 'stretch' => [
273 'title' => esc_html__( 'Stretch', 'elementor' ),
274 'icon' => 'eicon-align-stretch-v',
275 ],
276 ],
277 'selectors_dictionary' => [
278 'start' => '--n-tabs-heading-justify-content: flex-start; --n-tabs-title-width: initial; --n-tabs-title-height: initial; --n-tabs-title-align-items: initial; --n-tabs-heading-wrap: wrap; --n-tabs-title-flex-basis: content',
279 'center' => '--n-tabs-heading-justify-content: center; --n-tabs-title-width: initial; --n-tabs-title-height: initial; --n-tabs-title-align-items: initial; --n-tabs-heading-wrap: wrap; --n-tabs-title-flex-basis: content',
280 'end' => '--n-tabs-heading-justify-content: flex-end; --n-tabs-title-width: initial; --n-tabs-title-height: initial; --n-tabs-title-align-items: initial; --n-tabs-heading-wrap: wrap; --n-tabs-title-flex-basis: content',
281 'stretch' => '--n-tabs-heading-justify-content: flex-start; --n-tabs-title-width: initial; --n-tabs-title-height: 100%; --n-tabs-title-align-items: center; --n-tabs-heading-wrap: nowrap; --n-tabs-title-flex-basis: auto',
282 ],
283 'selectors' => [
284 '{{WRAPPER}}' => '{{VALUE}}',
285 ],
286 'condition' => [
287 'tabs_direction' => [
288 'inline-start',
289 'inline-end',
290 'start',
291 'end',
292 ],
293 ],
294 ] );
295
296 $this->add_responsive_control( 'tabs_width', [
297 'label' => esc_html__( 'Width', 'elementor' ),
298 'type' => Controls_Manager::SLIDER,
299 'range' => [
300 '%' => [
301 'min' => 10,
302 'max' => 50,
303 ],
304 'px' => [
305 'min' => 20,
306 'max' => 600,
307 ],
308 ],
309 'default' => [
310 'unit' => '%',
311 ],
312 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
313 'selectors' => [
314 '{{WRAPPER}}' => '--n-tabs-heading-width: {{SIZE}}{{UNIT}}',
315 ],
316 'condition' => [
317 'tabs_direction' => [
318 'inline-start',
319 'inline-end',
320 'start',
321 'end',
322 ],
323 ],
324 ] );
325
326 $this->add_responsive_control( 'title_alignment', [
327 'label' => esc_html__( 'Align Title', 'elementor' ),
328 'type' => Controls_Manager::CHOOSE,
329 'options' => [
330 'start' => [
331 'title' => esc_html__( 'Start', 'elementor' ),
332 'icon' => 'eicon-text-align-left',
333 ],
334 'center' => [
335 'title' => esc_html__( 'Center', 'elementor' ),
336 'icon' => 'eicon-text-align-center',
337 ],
338 'end' => [
339 'title' => esc_html__( 'End', 'elementor' ),
340 'icon' => 'eicon-text-align-right',
341 ],
342 ],
343 'selectors_dictionary' => [
344 'start' => '--n-tabs-title-justify-content: flex-start; --n-tabs-title-align-items: flex-start; --n-tabs-title-text-align: start;',
345 'center' => '--n-tabs-title-justify-content: center; --n-tabs-title-align-items: center; --n-tabs-title-text-align: center;',
346 'end' => '--n-tabs-title-justify-content: flex-end; --n-tabs-title-align-items: flex-end; --n-tabs-title-text-align: end;',
347 ],
348 'selectors' => [
349 '{{WRAPPER}}' => '{{VALUE}}',
350 ],
351 ] );
352
353 $this->end_controls_section();
354
355 $this->start_controls_section( 'section_tabs_responsive', [
356 'label' => esc_html__( 'Additional Settings', 'elementor' ),
357 ] );
358
359 $this->add_responsive_control(
360 'horizontal_scroll',
361 [
362 'label' => esc_html__( 'Horizontal Scroll', 'elementor' ),
363 'type' => Controls_Manager::SELECT,
364 'description' => esc_html__( 'Note: Scroll tabs if they don’t fit into their parent container.', 'elementor' ),
365 'options' => [
366 'disable' => esc_html__( 'Disable', 'elementor' ),
367 'enable' => esc_html__( 'Enable', 'elementor' ),
368 ],
369 'default' => 'disable',
370 'selectors_dictionary' => [
371 'disable' => '--n-tabs-heading-wrap: wrap; --n-tabs-heading-overflow-x: initial; --n-tabs-title-white-space: initial;',
372 'enable' => '--n-tabs-heading-wrap: nowrap; --n-tabs-heading-overflow-x: scroll; --n-tabs-title-white-space: nowrap;',
373 ],
374 'selectors' => [
375 '{{WRAPPER}}' => '{{VALUE}}',
376 ],
377 'frontend_available' => true,
378 'condition' => [
379 'tabs_direction' => [
380 '',
381 'block-start',
382 'block-end',
383 'top',
384 'bottom',
385 ],
386 ],
387 ]
388 );
389
390 $dropdown_options = [
391 'none' => esc_html__( 'None', 'elementor' ),
392 ];
393 $excluded_breakpoints = [
394 'laptop',
395 'tablet_extra',
396 'widescreen',
397 ];
398
399 foreach ( Plugin::$instance->breakpoints->get_active_breakpoints() as $breakpoint_key => $breakpoint_instance ) {
400 // Exclude the larger breakpoints from the dropdown selector.
401 if ( in_array( $breakpoint_key, $excluded_breakpoints, true ) ) {
402 continue;
403 }
404
405 $dropdown_options[ $breakpoint_key ] = sprintf(
406 /* translators: 1: Breakpoint label, 2: `>` character, 3: Breakpoint value. */
407 esc_html__( '%1$s (%2$s %3$dpx)', 'elementor' ),
408 $breakpoint_instance->get_label(),
409 '>',
410 $breakpoint_instance->get_value()
411 );
412 }
413
414 $this->add_control(
415 'breakpoint_selector',
416 [
417 'label' => esc_html__( 'Breakpoint', 'elementor' ),
418 'type' => Controls_Manager::SELECT,
419 'description' => esc_html__( 'Note: Choose at which breakpoint tabs will automatically switch to a vertical (“accordion”) layout.', 'elementor' ),
420 'options' => $dropdown_options,
421 'default' => 'mobile',
422 'prefix_class' => 'e-n-tabs-',
423 ]
424 );
425
426 $this->end_controls_section();
427
428 $this->start_controls_section( 'section_tabs_style', [
429 'label' => esc_html__( 'Tabs', 'elementor' ),
430 'tab' => Controls_Manager::TAB_STYLE,
431 ] );
432
433 $this->add_responsive_control( 'tabs_title_space_between', [
434 'label' => esc_html__( 'Gap between tabs', 'elementor' ),
435 'type' => Controls_Manager::SLIDER,
436 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
437 'range' => [
438 'px' => [
439 'max' => 400,
440 ],
441 'em' => [
442 'max' => 40,
443 ],
444 'rem' => [
445 'max' => 40,
446 ],
447 ],
448 'selectors' => [
449 '{{WRAPPER}}' => '--n-tabs-title-gap: {{SIZE}}{{UNIT}}',
450 ],
451 ] );
452
453 $this->add_responsive_control( 'tabs_title_spacing', [
454 'label' => esc_html__( 'Distance from content', 'elementor' ),
455 'type' => Controls_Manager::SLIDER,
456 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
457 'range' => [
458 'px' => [
459 'max' => 400,
460 ],
461 'em' => [
462 'max' => 40,
463 ],
464 'rem' => [
465 'max' => 40,
466 ],
467 ],
468 'selectors' => [
469 '{{WRAPPER}}' => '--n-tabs-gap: {{SIZE}}{{UNIT}}',
470 ],
471 ] );
472
473 $this->start_controls_tabs( 'tabs_title_style' );
474
475 $this->start_controls_tab(
476 'tabs_title_normal',
477 [
478 'label' => esc_html__( 'Normal', 'elementor' ),
479 ]
480 );
481
482 $this->add_group_control(
483 Group_Control_Background::get_type(),
484 [
485 'name' => 'tabs_title_background_color',
486 'types' => [ 'classic', 'gradient' ],
487 'exclude' => [ 'image' ],
488 'selector' => '{{WRAPPER}} > .elementor-widget-container > .e-n-tabs > .e-n-tabs-heading > .e-n-tab-title[aria-selected="false"]:not( :hover )',
489 'fields_options' => [
490 'color' => [
491 'label' => esc_html__( 'Background Color', 'elementor' ),
492 'selectors' => [
493 '{{SELECTOR}}' => 'background: {{VALUE}}',
494 ],
495 ],
496 ],
497 ]
498 );
499
500 $this->add_group_control(
501 Group_Control_Border::get_type(),
502 [
503 'name' => 'tabs_title_border',
504 'selector' => "{$heading_selector} > .e-n-tab-title[aria-selected=\"false\"]:not( :hover )",
505 'fields_options' => [
506 'color' => [
507 'label' => esc_html__( 'Border Color', 'elementor' ),
508 ],
509 'width' => [
510 'label' => esc_html__( 'Border Width', 'elementor' ),
511 ],
512 ],
513 ]
514 );
515
516 $this->add_group_control(
517 Group_Control_Box_Shadow::get_type(),
518 [
519 'name' => 'tabs_title_box_shadow',
520 'label' => esc_html__( 'Shadow', 'elementor' ),
521 'separator' => 'after',
522 'selector' => "{$heading_selector} > .e-n-tab-title[aria-selected=\"false\"]:not( :hover )",
523 ]
524 );
525
526 $this->end_controls_tab();
527
528 $this->start_controls_tab(
529 'tabs_title_hover',
530 [
531 'label' => esc_html__( 'Hover', 'elementor' ),
532 ]
533 );
534
535 $this->add_group_control(
536 Group_Control_Background::get_type(),
537 [
538 'name' => 'tabs_title_background_color_hover',
539 'types' => [ 'classic', 'gradient' ],
540 'exclude' => [ 'image' ],
541 'selector' => "{$heading_selector_non_touch_device} > .e-n-tab-title[aria-selected=\"false\"]:hover",
542 'fields_options' => [
543 'background' => [
544 'default' => 'classic',
545 ],
546 'color' => [
547 'global' => [
548 'default' => Global_Colors::COLOR_ACCENT,
549 ],
550 'label' => esc_html__( 'Background Color', 'elementor' ),
551 'selectors' => [
552 '{{SELECTOR}}' => 'background: {{VALUE}};',
553 ],
554 ],
555 ],
556 ]
557 );
558
559 $this->add_group_control(
560 Group_Control_Border::get_type(),
561 [
562 'name' => 'tabs_title_border_hover',
563 'selector' => "{$heading_selector_non_touch_device} > .e-n-tab-title[aria-selected=\"false\"]:hover",
564 'fields_options' => [
565 'color' => [
566 'label' => esc_html__( 'Border Color', 'elementor' ),
567 ],
568 'width' => [
569 'label' => esc_html__( 'Border Width', 'elementor' ),
570 ],
571 ],
572 ]
573 );
574
575 $this->add_group_control(
576 Group_Control_Box_Shadow::get_type(),
577 [
578 'name' => 'tabs_title_box_shadow_hover',
579 'label' => esc_html__( 'Shadow', 'elementor' ),
580 'separator' => 'after',
581 'selector' => "{$heading_selector_non_touch_device} > .e-n-tab-title[aria-selected=\"false\"]:hover",
582 ]
583 );
584
585 $this->add_control(
586 'hover_animation',
587 [
588 'label' => esc_html__( 'Hover Animation', 'elementor' ),
589 'type' => Controls_Manager::HOVER_ANIMATION,
590 ]
591 );
592
593 $this->add_control(
594 'tabs_title_transition_duration',
595 [
596 'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
597 'type' => Controls_Manager::SLIDER,
598 'selectors' => [
599 '{{WRAPPER}}' => '--n-tabs-title-transition: {{SIZE}}s',
600 ],
601 'range' => [
602 'px' => [
603 'min' => 0,
604 'max' => 3,
605 'step' => 0.1,
606 ],
607 ],
608 ]
609 );
610
611 $this->end_controls_tab();
612
613 $this->start_controls_tab(
614 'tabs_title_active',
615 [
616 'label' => esc_html__( 'Active', 'elementor' ),
617 ]
618 );
619
620 $this->add_group_control(
621 Group_Control_Background::get_type(),
622 [
623 'name' => 'tabs_title_background_color_active',
624 'types' => [ 'classic', 'gradient' ],
625 'exclude' => [ 'image' ],
626 'selector' => "{$heading_selector} > .e-n-tab-title[aria-selected=\"true\"], {$heading_selector_touch_device} > .e-n-tab-title[aria-selected=\"false\"]:hover",
627 'fields_options' => [
628 'background' => [
629 'default' => 'classic',
630 ],
631 'color' => [
632 'global' => [
633 'default' => Global_Colors::COLOR_ACCENT,
634 ],
635 'label' => esc_html__( 'Background Color', 'elementor' ),
636 'selectors' => [
637 '{{SELECTOR}}' => 'background: {{VALUE}};',
638 ],
639 ],
640 ],
641 ]
642 );
643
644 $this->add_group_control(
645 Group_Control_Border::get_type(),
646 [
647 'name' => 'tabs_title_border_active',
648 'selector' => "{$heading_selector} > .e-n-tab-title[aria-selected=\"true\"], {$heading_selector_touch_device} > .e-n-tab-title[aria-selected=\"false\"]:hover",
649 'fields_options' => [
650 'color' => [
651 'label' => esc_html__( 'Border Color', 'elementor' ),
652 ],
653 'width' => [
654 'label' => esc_html__( 'Border Width', 'elementor' ),
655 ],
656 ],
657 ]
658 );
659
660 $this->add_group_control(
661 Group_Control_Box_Shadow::get_type(),
662 [
663 'name' => 'tabs_title_box_shadow_active',
664 'label' => esc_html__( 'Shadow', 'elementor' ),
665 'selector' => "{$heading_selector} > .e-n-tab-title[aria-selected=\"true\"], {$heading_selector_touch_device} > .e-n-tab-title[aria-selected=\"false\"]:hover",
666 ]
667 );
668
669 $this->end_controls_tab();
670
671 $this->end_controls_tabs();
672
673 $this->add_responsive_control(
674 'tabs_title_border_radius',
675 [
676 'label' => esc_html__( 'Border Radius', 'elementor' ),
677 'type' => Controls_Manager::DIMENSIONS,
678 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
679 'separator' => 'before',
680 'selectors' => [
681 '{{WRAPPER}}' => '--n-tabs-title-border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
682 ],
683 ]
684 );
685
686 $this->add_responsive_control(
687 'padding',
688 [
689 'label' => esc_html__( 'Padding', 'elementor' ),
690 'type' => Controls_Manager::DIMENSIONS,
691 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
692 'selectors' => [
693 '{{WRAPPER}}' => '--n-tabs-title-padding-top: {{TOP}}{{UNIT}}; --n-tabs-title-padding-right: {{RIGHT}}{{UNIT}}; --n-tabs-title-padding-bottom: {{BOTTOM}}{{UNIT}}; --n-tabs-title-padding-left: {{LEFT}}{{UNIT}};',
694 ],
695 ]
696 );
697
698 $this->end_controls_section();
699
700 $this->start_controls_section( 'section_title_style', [
701 'label' => esc_html__( 'Titles', 'elementor' ),
702 'tab' => Controls_Manager::TAB_STYLE,
703 ] );
704
705 $this->add_group_control( Group_Control_Typography::get_type(), [
706 'name' => 'title_typography',
707 'global' => [
708 'default' => Global_Typography::TYPOGRAPHY_ACCENT,
709 ],
710 'selector' => "{$heading_selector} > :is( .e-n-tab-title > .e-n-tab-title-text, .e-n-tab-title )",
711 'fields_options' => [
712 'font_size' => [
713 'selectors' => [
714 '{{WRAPPER}}' => '--n-tabs-title-font-size: {{SIZE}}{{UNIT}}',
715 ],
716 ],
717 ],
718 ] );
719
720 $this->start_controls_tabs( 'title_style' );
721
722 $this->start_controls_tab(
723 'title_normal',
724 [
725 'label' => esc_html__( 'Normal', 'elementor' ),
726 ]
727 );
728
729 $this->add_control(
730 'title_text_color',
731 [
732 'label' => esc_html__( 'Color', 'elementor' ),
733 'type' => Controls_Manager::COLOR,
734 'selectors' => [
735 '{{WRAPPER}}' => '--n-tabs-title-color: {{VALUE}}',
736 ],
737 ]
738 );
739
740 $this->add_group_control(
741 Group_Control_Text_Shadow::get_type(),
742 [
743 'name' => 'title_text_shadow',
744 'selector' => "{$heading_selector} > .e-n-tab-title[aria-selected=\"false\"]:not( :hover )",
745 'fields_options' => [
746 'text_shadow_type' => [
747 'label' => esc_html__( 'Shadow', 'elementor' ),
748 ],
749 ],
750 ]
751 );
752
753 $this->add_group_control(
754 Group_Control_Text_Stroke::get_type(),
755 [
756 'name' => 'title_text_stroke',
757 'selector' => "{$heading_selector} > .e-n-tab-title[aria-selected=\"false\"]:not( :hover ) :is( span, a, i )",
758 'fields_options' => [
759 'text_stroke_type' => [
760 'label' => esc_html__( 'Stroke', 'elementor' ),
761 ],
762 ],
763 ]
764 );
765
766 $this->end_controls_tab();
767
768 $this->start_controls_tab(
769 'title_hover',
770 [
771 'label' => esc_html__( 'Hover', 'elementor' ),
772 ]
773 );
774
775 $this->add_control(
776 'title_text_color_hover',
777 [
778 'label' => esc_html__( 'Color', 'elementor' ),
779 'type' => Controls_Manager::COLOR,
780 'selectors' => [
781 '{{WRAPPER}} [data-touch-mode="false"] .e-n-tab-title[aria-selected="false"]:hover' => '--n-tabs-title-color-hover: {{VALUE}}',
782 ],
783 ]
784 );
785
786 $this->add_group_control(
787 Group_Control_Text_Shadow::get_type(),
788 [
789 'name' => 'title_text_shadow_hover',
790 'selector' => "{$heading_selector_non_touch_device} > .e-n-tab-title[aria-selected=\"false\"]:hover",
791 'fields_options' => [
792 'text_shadow_type' => [
793 'label' => esc_html__( 'Shadow', 'elementor' ),
794 ],
795 ],
796
797 ]
798 );
799
800 $this->add_group_control(
801 Group_Control_Text_Stroke::get_type(),
802 [
803 'name' => 'title_text_stroke_hover',
804 'selector' => "{$heading_selector_non_touch_device} > .e-n-tab-title[aria-selected=\"false\"]:hover :is( span, a, i )",
805 'fields_options' => [
806 'text_stroke_type' => [
807 'label' => esc_html__( 'Stroke', 'elementor' ),
808 ],
809 ],
810 ]
811 );
812
813 $this->end_controls_tab();
814
815 $this->start_controls_tab(
816 'title_active',
817 [
818 'label' => esc_html__( 'Active', 'elementor' ),
819 ]
820 );
821
822 $this->add_control(
823 'title_text_color_active',
824 [
825 'label' => esc_html__( 'Color', 'elementor' ),
826 'type' => Controls_Manager::COLOR,
827 'selectors' => [
828 '{{WRAPPER}}' => '--n-tabs-title-color-active: {{VALUE}}',
829 ],
830 ]
831 );
832
833 $this->add_group_control(
834 Group_Control_Text_Shadow::get_type(),
835 [
836 'name' => 'title_text_shadow_active',
837 'selector' => "{$heading_selector} > .e-n-tab-title[aria-selected=\"true\"], {$heading_selector_touch_device} > .e-n-tab-title[aria-selected=\"false\"]:hover",
838 'fields_options' => [
839 'text_shadow_type' => [
840 'label' => esc_html__( 'Shadow', 'elementor' ),
841 ],
842 ],
843 ]
844 );
845
846 $this->add_group_control(
847 Group_Control_Text_Stroke::get_type(),
848 [
849 'name' => 'title_text_stroke_active',
850 'selector' => "{$heading_selector} > .e-n-tab-title[aria-selected=\"true\"] :is( span, a, i ), {$heading_selector_touch_device} > .e-n-tab-title[aria-selected=\"false\"]:hover :is( span, a, i )",
851 'fields_options' => [
852 'text_stroke_type' => [
853 'label' => esc_html__( 'Stroke', 'elementor' ),
854 ],
855 ],
856 ]
857 );
858
859 $this->end_controls_tab();
860
861 $this->end_controls_tabs();
862
863 $this->end_controls_section();
864
865 $this->start_controls_section( 'icon_section_style', [
866 'label' => esc_html__( 'Icon', 'elementor' ),
867 'tab' => Controls_Manager::TAB_STYLE,
868 ] );
869
870 $styling_block_start = '--n-tabs-title-direction: column; --n-tabs-icon-order: initial; --n-tabs-title-justify-content-toggle: center; --n-tabs-title-align-items-toggle: initial;';
871 $styling_block_end = '--n-tabs-title-direction: column; --n-tabs-icon-order: 1; --n-tabs-title-justify-content-toggle: center; --n-tabs-title-align-items-toggle: initial;';
872 $styling_inline_start = '--n-tabs-title-direction: row; --n-tabs-icon-order: initial; --n-tabs-title-justify-content-toggle: initial; --n-tabs-title-align-items-toggle: center;';
873 $styling_inline_end = '--n-tabs-title-direction: row; --n-tabs-icon-order: 1; --n-tabs-title-justify-content-toggle: initial; --n-tabs-title-align-items-toggle: center;';
874
875 $this->add_responsive_control( 'icon_position', [
876 'label' => esc_html__( 'Position', 'elementor' ),
877 'type' => Controls_Manager::CHOOSE,
878 'options' => [
879 'block-start' => [
880 'title' => esc_html__( 'Above', 'elementor' ),
881 'icon' => 'eicon-v-align-top',
882 ],
883 'inline-end' => [
884 'title' => esc_html__( 'After', 'elementor' ),
885 'icon' => 'eicon-h-align-' . $end,
886 ],
887 'block-end' => [
888 'title' => esc_html__( 'Below', 'elementor' ),
889 'icon' => 'eicon-v-align-bottom',
890 ],
891 'inline-start' => [
892 'title' => esc_html__( 'Before', 'elementor' ),
893 'icon' => 'eicon-h-align-' . $start,
894 ],
895 ],
896 'selectors_dictionary' => [
897 // The toggle variables for 'align items' and 'justify content' have been added to separate the styling of the two 'flex direction' modes.
898 'block-start' => $styling_block_start,
899 'inline-end' => $styling_inline_end,
900 'block-end' => $styling_block_end,
901 'inline-start' => $styling_inline_start,
902 // Styling duplication for BC reasons.
903 'top' => $styling_block_start,
904 'bottom' => $styling_block_end,
905 'start' => $styling_inline_start,
906 'end' => $styling_inline_end,
907 ],
908 'selectors' => [
909 '{{WRAPPER}}' => '{{VALUE}}',
910 ],
911 ] );
912
913 $this->add_responsive_control( 'icon_size', [
914 'label' => esc_html__( 'Size', 'elementor' ),
915 'type' => Controls_Manager::SLIDER,
916 'range' => [
917 'px' => [
918 'max' => 100,
919 ],
920 'em' => [
921 'max' => 10,
922 ],
923 'rem' => [
924 'max' => 10,
925 ],
926 ],
927 'size_units' => [ 'px', 'em', 'rem', 'vw', 'custom' ],
928 'selectors' => [
929 '{{WRAPPER}}' => '--n-tabs-icon-size: {{SIZE}}{{UNIT}}',
930 ],
931 ] );
932
933 $this->add_responsive_control( 'icon_spacing', [
934 'label' => esc_html__( 'Spacing', 'elementor' ),
935 'type' => Controls_Manager::SLIDER,
936 'range' => [
937 'px' => [
938 'max' => 400,
939 ],
940 'vw' => [
941 'max' => 50,
942 'step' => 0.1,
943 ],
944 ],
945 'size_units' => [ 'px', 'em', 'rem', 'vw', 'custom' ],
946 'selectors' => [
947 '{{WRAPPER}}' => '--n-tabs-icon-gap: {{SIZE}}{{UNIT}}',
948 ],
949 ] );
950
951 $this->start_controls_tabs( 'icon_style_states' );
952
953 $this->start_controls_tab(
954 'icon_section_normal',
955 [
956 'label' => esc_html__( 'Normal', 'elementor' ),
957 ]
958 );
959
960 $this->add_control( 'icon_color', [
961 'label' => esc_html__( 'Color', 'elementor' ),
962 'type' => Controls_Manager::COLOR,
963 'selectors' => [
964 '{{WRAPPER}}' => '--n-tabs-icon-color: {{VALUE}};',
965 ],
966 ] );
967
968 $this->end_controls_tab();
969
970 $this->start_controls_tab(
971 'icon_section_hover',
972 [
973 'label' => esc_html__( 'Hover', 'elementor' ),
974 ]
975 );
976
977 $this->add_control( 'icon_color_hover', [
978 'label' => esc_html__( 'Color', 'elementor' ),
979 'type' => Controls_Manager::COLOR,
980 'selectors' => [
981 '{{WRAPPER}} [data-touch-mode="false"] .e-n-tab-title[aria-selected="false"]:hover' => '--n-tabs-icon-color-hover: {{VALUE}};',
982 ],
983 ] );
984
985 $this->end_controls_tab();
986
987 $this->start_controls_tab(
988 'icon_section_active',
989 [
990 'label' => esc_html__( 'Active', 'elementor' ),
991 ]
992 );
993
994 $this->add_control( 'icon_color_active', [
995 'label' => esc_html__( 'Color', 'elementor' ),
996 'type' => Controls_Manager::COLOR,
997 'selectors' => [
998 '{{WRAPPER}}' => '--n-tabs-icon-color-active: {{VALUE}};',
999 ],
1000 ] );
1001
1002 $this->end_controls_tab();
1003
1004 $this->end_controls_tabs();
1005
1006 $this->end_controls_section();
1007
1008 $this->start_controls_section( 'section_box_style', [
1009 'label' => esc_html__( 'Content', 'elementor' ),
1010 'tab' => Controls_Manager::TAB_STYLE,
1011 ] );
1012
1013 $this->add_group_control(
1014 Group_Control_Background::get_type(),
1015 [
1016 'name' => 'box_background_color',
1017 'types' => [ 'classic', 'gradient' ],
1018 'exclude' => [ 'image' ],
1019 'selector' => $content_selector,
1020 'fields_options' => [
1021 'color' => [
1022 'label' => esc_html__( 'Background Color', 'elementor' ),
1023 ],
1024 ],
1025 ]
1026 );
1027
1028 $this->add_group_control(
1029 Group_Control_Border::get_type(),
1030 [
1031 'name' => 'box_border',
1032 'selector' => $content_selector,
1033 'fields_options' => [
1034 'color' => [
1035 'label' => esc_html__( 'Border Color', 'elementor' ),
1036 ],
1037 'width' => [
1038 'label' => esc_html__( 'Border Width', 'elementor' ),
1039 ],
1040 ],
1041 ]
1042 );
1043
1044 $this->add_responsive_control(
1045 'box_border_radius',
1046 [
1047 'label' => esc_html__( 'Border Radius', 'elementor' ),
1048 'type' => Controls_Manager::DIMENSIONS,
1049 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
1050 'selectors' => [
1051 $content_selector => '--border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1052 ],
1053 ]
1054 );
1055
1056 $this->add_group_control(
1057 Group_Control_Box_Shadow::get_type(),
1058 [
1059 'name' => 'box_shadow_box_shadow',
1060 'selector' => $content_selector,
1061 'condition' => [
1062 'box_height!' => 'height',
1063 ],
1064 ]
1065 );
1066
1067 $this->add_responsive_control(
1068 'box_padding',
1069 [
1070 'label' => esc_html__( 'Padding', 'elementor' ),
1071 'type' => Controls_Manager::DIMENSIONS,
1072 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1073 'selectors' => [
1074 $content_selector => '--padding-top: {{TOP}}{{UNIT}}; --padding-right: {{RIGHT}}{{UNIT}}; --padding-bottom: {{BOTTOM}}{{UNIT}}; --padding-left: {{LEFT}}{{UNIT}};',
1075 ],
1076 ]
1077 );
1078
1079 $this->end_controls_section();
1080 }
1081
1082 protected function render_tab_titles_html( $item_settings ): void {
1083 $setting_key = $this->get_repeater_setting_key( 'tab_title', 'tabs', $item_settings['index'] );
1084 $title = $item_settings['item']['tab_title'];
1085 $css_classes = [ 'e-n-tab-title' ];
1086
1087 if ( $item_settings['settings']['hover_animation'] ) {
1088 $css_classes[] = 'elementor-animation-' . $item_settings['settings']['hover_animation'];
1089 }
1090
1091 $this->add_render_attribute( $setting_key, [
1092 'id' => $item_settings['tab_id'],
1093 'class' => $css_classes,
1094 'aria-selected' => 1 === $item_settings['tab_count'] ? 'true' : 'false',
1095 'data-tab-index' => $item_settings['tab_count'],
1096 'role' => 'tab',
1097 'tabindex' => 1 === $item_settings['tab_count'] ? '0' : '-1',
1098 'aria-controls' => $item_settings['container_id'],
1099 'style' => '--n-tabs-title-order: ' . $item_settings['tab_count'] . ';',
1100 ] );
1101 ?>
1102 <button <?php $this->print_render_attribute_string( $setting_key ); ?>>
1103 <?php $this->maybe_render_tab_icons_html( $item_settings ); ?>
1104 <span <?php $this->print_render_attribute_string( 'tab-title-text' ); ?>>
1105 <?php echo wp_kses_post( $title ); ?>
1106 </span>
1107 </button>
1108 <?php
1109 }
1110
1111 protected function maybe_render_tab_icons_html( $item_settings ): void {
1112 $icon_settings = $item_settings['item']['tab_icon'];
1113
1114 if ( empty( $icon_settings['value'] ) ) {
1115 return;
1116 }
1117
1118 $active_icon_settings = $this->is_active_icon_exist( $item_settings['item'] )
1119 ? $item_settings['item']['tab_icon_active']
1120 : $icon_settings;
1121 ?>
1122 <span <?php $this->print_render_attribute_string( 'tab-icon' ); ?>>
1123 <?php Icons_Manager::render_icon( $icon_settings, [ 'aria-hidden' => 'true' ] ); ?>
1124 <?php Icons_Manager::render_icon( $active_icon_settings, [ 'aria-hidden' => 'true' ] ); ?>
1125 </span>
1126 <?php
1127 }
1128
1129 protected function render_tab_containers_html( $settings ): void {
1130 foreach ( $settings['tabs'] as $index => $item ) {
1131 $item_settings = $this->tab_item_settings[ $index ];
1132 $this->print_child( $item_settings['index'], $item_settings );
1133 }
1134 }
1135
1136
1137 /**
1138 * Print the content area.
1139 *
1140 * @param int $index
1141 * @param array $item_settings
1142 */
1143 public function print_child( $index, $item_settings = [] ) {
1144 $children = $this->get_children();
1145 $child_ids = [];
1146
1147 foreach ( $children as $child ) {
1148 $child_ids[] = $child->get_id();
1149 }
1150
1151 // Add data-tab-index attribute to the content area.
1152 $add_attribute_to_container = function ( $should_render, $container ) use ( $item_settings, $child_ids ) {
1153 if ( in_array( $container->get_id(), $child_ids ) ) {
1154 $this->add_attributes_to_container( $container, $item_settings );
1155 }
1156
1157 return $should_render;
1158 };
1159
1160 add_filter( 'elementor/frontend/container/should_render', $add_attribute_to_container, 10, 3 );
1161 if ( isset( $children[ $index ] ) ) {
1162 $children[ $index ]->print_element();
1163 }
1164 remove_filter( 'elementor/frontend/container/should_render', $add_attribute_to_container );
1165 }
1166
1167 protected function add_attributes_to_container( $container, $item_settings ) {
1168 $container->add_render_attribute( '_wrapper', [
1169 'id' => $item_settings['container_id'],
1170 'role' => 'tabpanel',
1171 'aria-labelledby' => $item_settings['tab_id'],
1172 'data-tab-index' => $item_settings['tab_count'],
1173 'style' => '--n-tabs-title-order: ' . $item_settings['tab_count'] . ';',
1174 'class' => 0 === $item_settings['index'] ? 'e-active' : '',
1175 ] );
1176 }
1177
1178 protected function render() {
1179 $settings = $this->get_settings_for_display();
1180 $widget_number = $this->get_id_int();
1181
1182 if ( ! empty( $settings['link'] ) ) {
1183 $this->add_link_attributes( 'elementor-tabs', $settings['link'] );
1184 }
1185
1186 $this->add_render_attribute( 'elementor-tabs', [
1187 'class' => 'e-n-tabs',
1188 'data-widget-number' => $widget_number,
1189 'aria-label' => esc_html__( 'Tabs. Open items with Enter or Space, close with Escape and navigate using the Arrow keys.', 'elementor' ),
1190 ] );
1191
1192 $this->add_render_attribute( 'tab-title-text', 'class', 'e-n-tab-title-text' );
1193 $this->add_render_attribute( 'tab-icon', 'class', 'e-n-tab-icon' );
1194 $this->add_render_attribute( 'tab-icon-active', 'class', [ 'e-n-tab-icon' ] );
1195 ?>
1196 <div <?php $this->print_render_attribute_string( 'elementor-tabs' ); ?>>
1197 <div class="e-n-tabs-heading" role="tablist">
1198 <?php
1199 foreach ( $settings['tabs'] as $index => $item ) {
1200 $tab_count = $index + 1;
1201
1202 $tab_id = empty( $item['element_id'] )
1203 ? 'e-n-tab-title-' . $widget_number . $tab_count
1204 : $item['element_id'];
1205
1206 $item_settings = [
1207 'index' => $index,
1208 'tab_count' => $tab_count,
1209 'tab_id' => $tab_id,
1210 'container_id' => 'e-n-tab-content-' . $widget_number . $tab_count,
1211 'widget_number' => $widget_number,
1212 'item' => $item,
1213 'settings' => $settings,
1214 ];
1215
1216 $this->tab_item_settings[] = $item_settings;
1217
1218 $this->render_tab_titles_html( $item_settings );
1219 }
1220 ?>
1221 </div>
1222 <div class="e-n-tabs-content">
1223 <?php $this->render_tab_containers_html( $settings ); ?>
1224 </div>
1225 </div>
1226 <?php
1227 }
1228
1229 protected function get_initial_config(): array {
1230 if ( Plugin::$instance->experiments->is_feature_active( 'e_nested_atomic_repeaters' ) ) {
1231 return array_merge( parent::get_initial_config(), [
1232 'support_improved_repeaters' => true,
1233 'target_container' => [ '.e-n-tabs-heading' ],
1234 'node' => 'button',
1235 ] );
1236 }
1237
1238 return parent::get_initial_config();
1239 }
1240
1241 protected function content_template_single_repeater_item() {
1242 ?>
1243 <#
1244 const tabIndex = view.collection.length,
1245 elementUid = view.getIDInt().toString(),
1246 item = data,
1247 hoverAnimationSetting = view?.container?.settings?.attributes?.hover_animation;
1248 hoverAnimationClass = hoverAnimationSetting
1249 ? `elementor-animation-${ hoverAnimationSetting }`
1250 : '';
1251 #>
1252 <?php $this->content_template_single_item( '{{ tabIndex }}', '{{ item }}', '{{ elementUid }}', '{{ hoverAnimationClass }}' );
1253 }
1254
1255 protected function content_template() {
1256 ?>
1257 <# const elementUid = view.getIDInt().toString(); #>
1258 <div class="e-n-tabs" data-widget-number="{{ elementUid }}" aria-label="<?php echo esc_html__( 'Tabs. Open items with Enter or Space, close with Escape and navigate using the Arrow keys.', 'elementor' ); ?>">
1259 <# if ( settings['tabs'] ) { #>
1260 <div class="e-n-tabs-heading" role="tablist">
1261 <# _.each( settings['tabs'], function( item, index ) {
1262 const tabIndex = index,
1263 hoverAnimationSetting = settings['hover_animation'],
1264 hoverAnimationClass = hoverAnimationSetting
1265 ? `elementor-animation-${ hoverAnimationSetting }`
1266 : '';
1267 #>
1268 <?php $this->content_template_single_item( '{{ tabIndex }}', '{{ item }}', '{{ elementUid }}', '{{ hoverAnimationClass }}' ); ?>
1269 <# } ); #>
1270 </div>
1271 <div class="e-n-tabs-content"></div>
1272 <# } #>
1273 </div>
1274 <?php
1275 }
1276
1277 private function content_template_single_item( $tab_index, $item, $element_uid, $hover_animation_class ) {
1278 ?>
1279 <#
1280 const tabCount = tabIndex + 1,
1281 tabId = item.element_id
1282 ? item.element_id
1283 : 'e-n-tab-title-' + elementUid + ( tabIndex + 1 ),
1284 tabUid = elementUid + tabCount,
1285 tabIcon = elementor.helpers.renderIcon( view, item.tab_icon, { 'aria-hidden': true }, 'i' , 'object' ),
1286 activeTabIcon = item.tab_icon_active.value
1287 ? elementor.helpers.renderIcon( view, item.tab_icon_active, { 'aria-hidden': true }, 'i' , 'object' )
1288 : tabIcon,
1289 escapedHoverAnimationClass = _.escape( hoverAnimationClass );
1290
1291 view.addRenderAttribute( 'tab-title', {
1292 'id': tabId,
1293 'class': [ 'e-n-tab-title',escapedHoverAnimationClass ],
1294 'data-tab-index': tabCount,
1295 'role': 'tab',
1296 'aria-selected': 1 === tabCount ? 'true' : 'false',
1297 'tabindex': 1 === tabCount ? '0' : '-1',
1298 'aria-controls': 'e-n-tab-content-' + tabUid,
1299 'style': '--n-tabs-title-order: ' + tabCount + ';',
1300 }, null, true );
1301
1302 view.addRenderAttribute( 'tab-title-text', {
1303 'class': [ 'e-n-tab-title-text' ],
1304 'data-binding-type': 'repeater-item',
1305 'data-binding-repeater-name': 'tabs',
1306 'data-binding-setting': [ 'tab_title' ],
1307 'data-binding-index': tabCount,
1308 'data-binding-dynamic': 'true',
1309 }, null, true );
1310
1311 view.addRenderAttribute( 'tab-icon', {
1312 'class': [ 'e-n-tab-icon' ],
1313 'data-binding-type': 'repeater-item',
1314 'data-binding-repeater-name': 'tabs',
1315 'data-binding-setting': [ 'tab_icon', 'tab_icon_active' ],
1316 'data-binding-index': tabCount,
1317 }, null, true );
1318 #>
1319
1320 <button {{{ view.getRenderAttributeString( 'tab-title' ) }}}>
1321 <# if ( !! item.tab_icon.value ) { #>
1322 <span {{{ view.getRenderAttributeString( 'tab-icon' ) }}}>{{{ tabIcon.value }}}{{{ activeTabIcon.value }}}</span>
1323 <# } #>
1324
1325 <span {{{ view.getRenderAttributeString( 'tab-title-text' ) }}}>{{{ item.tab_title }}}</span>
1326 </button>
1327 <?php
1328 }
1329
1330 /**
1331 * @param $item
1332 * @return bool
1333 */
1334 private function is_active_icon_exist( $item ) {
1335 return array_key_exists( 'tab_icon_active', $item ) && ! empty( $item['tab_icon_active'] ) && ! empty( $item['tab_icon_active']['value'] );
1336 }
1337 }
1338