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

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