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

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