PluginProbe
Elementor Website Builder – more than just a page builder / 3.25.8
Elementor Website Builder – more than just a page builder v3.25.8
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.25.8, at modules/nested-tabs/widgets/nested-tabs.php

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