PluginProbe
UiCore Elements – Free widgets and templates for Elementor / 1.0.16
UiCore Elements – Free widgets and templates for Elementor v1.0.16
1.3.17 1.3.16 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 All 41 releases
uicore-elements / includes / widgets / tabs.php

tabs.php in UiCore Elements – Free widgets and templates for Elementor 1.0.16, at includes/widgets/tabs.php

1,607 lines 51.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace UiCoreElements;
3
4 use Elementor\Controls_Manager;
5 use Elementor\Repeater;
6 use Elementor\Plugin;
7 use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
8 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
9 use Elementor\Group_Control_Background;
10 use Elementor\Group_Control_Border;
11 use Elementor\Group_Control_Box_Shadow;
12 use Elementor\Group_Control_Typography;
13 use Elementor\Icons_Manager;
14 use Elementor\Modules\NestedElements\Controls\Control_Nested_Repeater;
15
16 defined('ABSPATH') || exit();
17
18 /**
19 * Tabs
20 *
21 * @author Lucas Marini Falbo <lucas@uicore.co>
22 * @since 1.0.6
23 */
24
25 class Tabs extends UiCoreNestedWidget {
26
27 public function get_name() {
28 return 'uicore-tabs';
29 }
30 public function get_title() {
31 return esc_html__( 'Tabs', 'uicore-elements' );
32 }
33 public function get_icon() {
34 return 'eicon-tabs ui-e-widget';
35 }
36 public function get_categories()
37 {
38 return ['uicore'];
39 }
40 public function get_keywords() {
41 return [ 'tabs', 'tab', 'content' ];
42 }
43 public function get_styles()
44 {
45 return ['tabs'];
46 }
47 public function get_scripts()
48 {
49 return ['tabs'];
50 }
51
52 // Nested required functions
53 protected function tab_content_container( int $index ) {
54 return [
55 'elType' => 'container',
56 'settings' => [
57 '_title' => sprintf( __( 'Tab #%s', 'uicore-elements' ), $index ),
58 'content_width' => 'full',
59 ],
60 ];
61 }
62 protected function get_default_children_elements() {
63 return [
64 $this->tab_content_container( 1 ),
65 $this->tab_content_container( 2 ),
66 $this->tab_content_container( 3 ),
67 ];
68 }
69 protected function get_default_repeater_title_setting_key() {
70 return 'tab_title';
71 }
72 protected function get_default_children_title() {
73 return esc_html__( 'Tab #%d', 'uicore-elements' );
74 }
75 protected function get_default_children_placeholder_selector() {
76 return '.ui-e-tabs-content';
77 }
78
79 protected function register_controls() {
80
81 if( !Plugin::$instance->experiments->is_feature_active('nested-elements') ){
82 $this->nesting_fallback('controls');
83 return;
84 }
85
86 // Helper properties
87 $start = is_rtl() ? 'right' : 'left';
88 $end = is_rtl() ? 'left' : 'right';
89 $start_logical = is_rtl() ? 'end' : 'start';
90 $end_logical = is_rtl() ? 'start' : 'end';
91 $heading_selector = '{{WRAPPER}} > .elementor-widget-container > .ui-e-tabs > .ui-e-tabs-heading';
92 $content_selector = ':where( {{WRAPPER}} > .elementor-widget-container > .ui-e-tabs > .ui-e-tabs-content ) > .e-con';
93
94 $this->start_controls_section(
95 'section_tabs',
96 [
97 'label' => esc_html__( 'Tabs', 'uicore-elements' ),
98 'tab' => Controls_Manager::TAB_CONTENT,
99 ]
100 );
101
102 $repeater = new Repeater();
103
104 $repeater->add_control( 'tab_title', [
105 'label' => esc_html__( 'Title', 'uicore-elements' ),
106 'type' => Controls_Manager::TEXT,
107 'default' => esc_html__( 'Tab Title', 'uicore-elements' ),
108 'placeholder' => esc_html__( 'Tab Title', 'uicore-elements' ),
109 'label_block' => true,
110 'dynamic' => [
111 'active' => true,
112 ],
113 ] );
114
115 $repeater->add_control( 'tab_description', [
116 'label' => esc_html__( 'Description', 'uicore-elements' ),
117 'type' => Controls_Manager::TEXTAREA,
118 'rows' => 2,
119 'placeholder' => esc_html__( 'Tab Title', 'uicore-elements' ),
120 'label_block' => true,
121 'dynamic' => [
122 'active' => true,
123 ],
124 ] );
125
126 $repeater->add_control(
127 'tab_icon',
128 [
129 'label' => esc_html__( 'Icon', 'uicore-elements' ),
130 'type' => Controls_Manager::ICONS,
131 'fa4compatibility' => 'icon',
132 'skin' => 'inline',
133 'label_block' => false,
134 ]
135 );
136
137 $repeater->add_control(
138 'tab_icon_active',
139 [
140 'label' => esc_html__( 'Active Icon', 'uicore-elements' ),
141 'type' => Controls_Manager::ICONS,
142 'fa4compatibility' => 'icon',
143 'skin' => 'inline',
144 'label_block' => false,
145 'condition' => [
146 'tab_icon[value]!' => '',
147 ],
148 ]
149 );
150
151 $repeater->add_control(
152 'tab_id',
153 [
154 'label' => esc_html__( 'CSS ID', 'uicore-elements' ),
155 'type' => Controls_Manager::TEXT,
156 'default' => '',
157 'ai' => [
158 'active' => false,
159 ],
160 'dynamic' => [
161 'active' => true,
162 ],
163 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'uicore-elements' ),
164 'style_transfer' => false,
165 'classes' => 'elementor-control-direction-ltr',
166 ]
167 );
168
169 $this->add_control( 'tabs', [
170 'label' => esc_html__( 'Tabs Items', 'uicore-elements' ),
171 'type' => Control_Nested_Repeater::CONTROL_TYPE,
172 'fields' => $repeater->get_controls(),
173 'default' => [
174 [
175 'tab_title' => esc_html__( 'Tab #1', 'uicore-elements' ),
176 ],
177 [
178 'tab_title' => esc_html__( 'Tab #2', 'uicore-elements' ),
179 ],
180 [
181 'tab_title' => esc_html__( 'Tab #3', 'uicore-elements' ),
182 ],
183 ],
184 'title_field' => '{{{ tab_title }}}',
185 'button_text' => 'Add Tab',
186 ] );
187
188 // Tabs position and alignment group values
189 $styling_block_start = '--ui-e-tabs-direction: column; --ui-e-tabs-head-direction: row; --ui-e-tabs-head-width: initial; --ui-e-tabs-title-flex-basis: content; --ui-e-tabs-title-flex-shrink: initial;';
190 $styling_block_end = '--ui-e-tabs-direction: column-reverse; --ui-e-tabs-head-direction: row; --ui-e-tabs-head-width: initial; --ui-e-tabs-title-flex-basis: content; --ui-e-tabs-title-flex-shrink: initial;';
191 $styling_inline_end = '--ui-e-tabs-direction: row-reverse; --ui-e-tabs-head-direction: column; --ui-e-tabs-head-width: 240px; --ui-e-tabs-title-flex-basis: initial; --ui-e-tabs-title-flex-shrink: 0; --ui-e-tabs-title-width: 100%';
192 $styling_inline_start = '--ui-e-tabs-direction: row; --ui-e-tabs-head-direction: column; --ui-e-tabs-head-width: 240px; --ui-e-tabs-title-flex-basis: initial; --ui-e-tabs-title-flex-shrink: 0; --ui-e-tabs-title-width: 100%';
193
194 $this->add_responsive_control( 'tabs_direction', [
195 'label' => esc_html__( 'Tabs Direction', 'uicore-elements' ),
196 'type' => Controls_Manager::CHOOSE,
197 'options' => [
198 'block-start' => [
199 'title' => esc_html__( 'Above', 'uicore-elements' ),
200 'icon' => 'eicon-v-align-top',
201 ],
202 'block-end' => [
203 'title' => esc_html__( 'Below', 'uicore-elements' ),
204 'icon' => 'eicon-v-align-bottom',
205 ],
206 'inline-end' => [
207 'title' => esc_html__( 'After', 'uicore-elements' ),
208 'icon' => 'eicon-h-align-' . $end,
209 ],
210 'inline-start' => [
211 'title' => esc_html__( 'Before', 'uicore-elements' ),
212 'icon' => 'eicon-h-align-' . $start,
213 ],
214 ],
215 'default' => 'block-start',
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 ],
223 'selectors' => [
224 '{{WRAPPER}}' => '{{VALUE}}',
225 ],
226 ] );
227
228 $this->add_responsive_control( 'tabs_width', [
229 'label' => esc_html__( 'Tabs Width', 'uicore-elements' ),
230 'type' => Controls_Manager::SLIDER,
231 'range' => [
232 '%' => [
233 'min' => 10,
234 'max' => 50,
235 ],
236 'px' => [
237 'min' => 20,
238 'max' => 600,
239 ],
240 ],
241 'default' => [
242 'unit' => '%',
243 ],
244 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
245 'selectors' => [
246 '{{WRAPPER}}' => '--ui-e-tabs-head-width: {{SIZE}}{{UNIT}}',
247 ],
248 'condition' => [
249 'tabs_direction' => [
250 'inline-start',
251 'inline-end',
252 ],
253 ],
254 ] );
255
256 $this->add_responsive_control( 'tabs_justify_horizontal', [
257 'label' => esc_html__( 'Justify', 'uicore-elements' ),
258 'type' => Controls_Manager::CHOOSE,
259 'options' => [
260 'start' => [
261 'title' => esc_html__( 'Start', 'uicore-elements' ),
262 'icon' => "eicon-align-$start_logical-h",
263 ],
264 'center' => [
265 'title' => esc_html__( 'Center', 'uicore-elements' ),
266 'icon' => 'eicon-align-center-h',
267 ],
268 'end' => [
269 'title' => esc_html__( 'End', 'uicore-elements' ),
270 'icon' => "eicon-align-$end_logical-h",
271 ],
272 'stretch' => [
273 'title' => esc_html__( 'Stretch', 'uicore-elements' ),
274 'icon' => 'eicon-align-stretch-h',
275 ],
276 ],
277 'selectors_dictionary' => [
278 'start' => 'justify-content: flex-start; --ui-e-tabs-title-flex-width: initial; --ui-e-tabs-title-justify-content: center; --ui-e-tabs-title-flex-grow: 0;',
279 'center' => 'justify-content: center; --ui-e-tabs-title-flex-width: initial; --ui-e-tabs-title-justify-content: center; --ui-e-tabs-title-flex-grow: 0;',
280 'end' => 'justify-content: flex-end; --ui-e-tabs-title-flex-width: initial; --ui-e-tabs-title-justify-content: center; --ui-e-tabs-title-flex-grow: 0;',
281 'stretch' => 'justify-content: initial; --ui-e-tabs-title-flex-width: 100%; --ui-e-tabs-title-justify-content: center; --ui-e-tabs-title-flex-grow: 1;',
282 ],
283 'selectors' => [
284 '{{WRAPPER}} .ui-e-tabs-heading' => '{{VALUE}}',
285 ],
286 'condition' => [
287 'tabs_direction' => [
288 'block-start',
289 'block-end',
290 ],
291 ],
292 'frontend_available' => true,
293 ] );
294
295 $this->add_responsive_control( 'tabs_justify_vertical', [
296 'label' => esc_html__( 'Tabs alignment', 'uicore-elements' ),
297 'type' => Controls_Manager::CHOOSE,
298 'options' => [
299 'start' => [
300 'title' => esc_html__( 'Start', 'uicore-elements' ),
301 'icon' => 'eicon-align-start-v',
302 ],
303 'center' => [
304 'title' => esc_html__( 'Center', 'uicore-elements' ),
305 'icon' => 'eicon-align-center-v',
306 ],
307 'end' => [
308 'title' => esc_html__( 'End', 'uicore-elements' ),
309 'icon' => 'eicon-align-end-v',
310 ],
311 'stretch' => [
312 'title' => esc_html__( 'Stretch', 'uicore-elements' ),
313 'icon' => 'eicon-align-stretch-v',
314 ],
315 ],
316 'selectors_dictionary' => [
317 'start' => 'justify-content: flex-start; --ui-e-tabs-title-height: initial; --ui-e-tabs-title-justify-content: initial; --ui-e-tabs-heading-wrap: wrap; --ui-e-tabs-title-flex-basis: content; --ui-e-tabs-title-flex-grow: 0;',
318 'center' => 'justify-content: center; --ui-e-tabs-title-height: initial; --ui-e-tabs-title-justify-content: initial; --ui-e-tabs-heading-wrap: wrap; --ui-e-tabs-title-flex-basis: content; --ui-e-tabs-title-flex-grow: 0;',
319 'end' => 'justify-content: flex-end; --ui-e-tabs-title-height: initial; --ui-e-tabs-title-justify-content: initial; --ui-e-tabs-heading-wrap: wrap; --ui-e-tabs-title-flex-basis: content; --ui-e-tabs-title-flex-grow: 0;',
320 'stretch' => 'justify-content: flex-start; --ui-e-tabs-title-height: 100%; --ui-e-tabs-title-justify-content: center; --ui-e-tabs-heading-wrap: nowrap; --ui-e-tabs-title-flex-basis: auto; --ui-e-tabs-title-flex-grow: 1;',
321 ],
322 'selectors' => [
323 '{{WRAPPER}} .ui-e-tabs-heading' => '{{VALUE}}',
324 ],
325 'condition' => [
326 'tabs_direction' => [
327 'inline-start',
328 'inline-end',
329 ],
330 ],
331 ] );
332
333 $styling_icon_above = '--ui-e-tabs-title-direction: column; --ui-e-tabs-icon-order: initial;';
334 $styling_icon_before = '--ui-e-tabs-title-direction: row; --ui-e-tabs-icon-order: initial';
335 $styling_icon_after = '--ui-e-tabs-title-direction: row; --ui-e-tabs-icon-order: 1;';
336
337 $this->add_responsive_control( 'icon_position', [
338 'label' => esc_html__( 'Icon Position', 'uicore-elements' ),
339 'type' => Controls_Manager::CHOOSE,
340 'options' => [
341 'above' => [
342 'title' => esc_html__( 'Before', 'uicore-elements' ),
343 'icon' => 'eicon-v-align-top',
344 ],
345 'before' => [
346 'title' => esc_html__( 'Before', 'uicore-elements' ),
347 'icon' => 'eicon-h-align-' . $start,
348 ],
349 'after' => [
350 'title' => esc_html__( 'After', 'uicore-elements' ),
351 'icon' => 'eicon-h-align-' . $end,
352 ],
353 ],
354 'default' => 'before',
355 'selectors_dictionary' => [
356 'above' => $styling_icon_above,
357 'before' => $styling_icon_before,
358 'after' => $styling_icon_after,
359 ],
360 'separator' => 'before',
361 'selectors' => [
362 '{{WRAPPER}}' => '{{VALUE}}',
363 ],
364 ] );
365
366 $this->add_responsive_control( 'title_alignment', [
367 'label' => esc_html__( 'Content Alignment', 'uicore-elements' ),
368 'type' => Controls_Manager::CHOOSE,
369 'options' => [
370 'start' => [
371 'title' => esc_html__( 'Start', 'uicore-elements' ),
372 'icon' => 'eicon-text-align-left',
373 ],
374 'center' => [
375 'title' => esc_html__( 'Center', 'uicore-elements' ),
376 'icon' => 'eicon-text-align-center',
377 ],
378 'end' => [
379 'title' => esc_html__( 'End', 'uicore-elements' ),
380 'icon' => 'eicon-text-align-right',
381 ],
382 'justify' => [
383 'title' => esc_html__( 'Justify', 'uicore-elements' ),
384 'icon' => 'eicon-text-align-justify',
385 ],
386 ],
387 'selectors_dictionary' => [
388 'start' => '--ui-e-tabs-title-justify: flex-start; --ui-e-tabs-title-align: flex-start; --ui-e-tabs-title-text-align: start;',
389 'center' => '--ui-e-tabs-title-justify: center; --ui-e-tabs-title-align: flex-start; --ui-e-tabs-title-text-align: center;',
390 'end' => '--ui-e-tabs-title-justify: flex-end; --ui-e-tabs-title-align: flex-start; --ui-e-tabs-title-text-align: end;',
391 'justify' => '--ui-e-tabs-title-justify: space-between; --ui-e-tabs-title-align: flex-start; --ui-e-tabs-title-text-align: start;',
392 ],
393 'condition' => [
394 'icon_position!' => 'above',
395 ],
396 'selectors' => [
397 '{{WRAPPER}}' => '{{VALUE}}',
398 ],
399 ] );
400
401 $this->add_responsive_control( 'title_alignment_above', [
402 'label' => esc_html__( 'Content Alignment', 'uicore-elements' ),
403 'type' => Controls_Manager::CHOOSE,
404 'options' => [
405 'start' => [
406 'title' => esc_html__( 'Start', 'uicore-elements' ),
407 'icon' => 'eicon-text-align-left',
408 ],
409 'center' => [
410 'title' => esc_html__( 'Center', 'uicore-elements' ),
411 'icon' => 'eicon-text-align-center',
412 ],
413 'end' => [
414 'title' => esc_html__( 'End', 'uicore-elements' ),
415 'icon' => 'eicon-text-align-right',
416 ],
417 ],
418 'selectors_dictionary' => [
419 'start' => '--ui-e-tabs-title-justify: flex-start; --ui-e-tabs-title-align: flex-start; --ui-e-tabs-title-text-align: start;',
420 'center' => '--ui-e-tabs-title-justify: flex-start; --ui-e-tabs-title-align: center; --ui-e-tabs-title-text-align: center;',
421 'end' => '--ui-e-tabs-title-justify: flex-start; --ui-e-tabs-title-align: flex-end; --ui-e-tabs-title-text-align: end;',
422 ],
423 'condition' => [
424 'icon_position' => 'above',
425 ],
426 'selectors' => [
427 '{{WRAPPER}}' => '{{VALUE}}',
428 ],
429 ] );
430
431 $this->end_controls_section();
432
433 $this->start_controls_section(
434 'section_tabs_responsive',
435 [
436 'label' => esc_html__( 'Additional Settings', 'uicore-elements' ),
437 ]
438 );
439
440 // Build breakpoint options
441 $dropdown_options = [
442 'none' => esc_html__( 'None', 'uicore-elements' ),
443 ];
444 $excluded_breakpoints = [
445 'laptop',
446 'tablet_extra',
447 'widescreen',
448 ];
449
450 foreach ( Plugin::$instance->breakpoints->get_active_breakpoints() as $breakpoint_key => $breakpoint_instance ) {
451 // Exclude the larger breakpoints from the dropdown selector.
452 if ( in_array( $breakpoint_key, $excluded_breakpoints, true ) ) {
453 continue;
454 }
455
456 $dropdown_options[ $breakpoint_key ] = sprintf(
457 /* translators: 1: Breakpoint label, 2: `>` character, 3: Breakpoint value. */
458 esc_html__( '%1$s (%2$s %3$dpx)', 'uicore-elements' ),
459 $breakpoint_instance->get_label(),
460 '>',
461 $breakpoint_instance->get_value()
462 );
463 }
464
465 $this->add_control(
466 'breakpoint_selector',
467 [
468 'label' => esc_html__( 'Breakpoint', 'uicore-elements' ),
469 'type' => Controls_Manager::SELECT,
470 'description' => esc_html__( 'Note: Choose the breakpoint where tabs automatically switch to a vertical (“accordion”) layout.', 'uicore-elements' ),
471 'options' => $dropdown_options,
472 'default' => 'mobile',
473 'prefix_class' => 'ui-e-tabs-',
474 ]
475 );
476
477 $this->add_control(
478 'show_description',
479 [
480 'label' => esc_html__( 'Toggle Description', 'uicore-elements' ),
481 'type' => Controls_Manager::SWITCHER,
482 'label_on' => esc_html__( 'Show', 'uicore-elements' ),
483 'label_off' => esc_html__( 'Hide', 'uicore-elements' ),
484 'description' => esc_html__('Show descriptions only for active items.', 'uicore-elements'),
485 'return_value' => 'yes',
486 ]
487 );
488
489 $this->end_controls_section();
490
491 $this->start_controls_section(
492 'section_tabs_style',
493 [
494 'label' => esc_html__( 'Tabs', 'uicore-elements' ),
495 'tab' => Controls_Manager::TAB_STYLE,
496 ]
497 );
498
499 $this->add_responsive_control( 'tabs_title_space_between', [
500 'label' => esc_html__( 'Gap between tabs', 'uicore-elements' ),
501 'type' => Controls_Manager::SLIDER,
502 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
503 'range' => [
504 'px' => [
505 'max' => 100,
506 ],
507 'em' => [
508 'max' => 40,
509 ],
510 'rem' => [
511 'max' => 40,
512 ],
513 ],
514 'default' => [
515 'size' => 10,
516 'unit' => 'px',
517 ],
518 'selectors' => [
519 '{{WRAPPER}}' => '--ui-e-tabs-title-gap: {{SIZE}}{{UNIT}}',
520 ],
521 ] );
522
523 $this->add_responsive_control( 'tabs_title_spacing', [
524 'label' => esc_html__( 'Distance from content', 'uicore-elements' ),
525 'type' => Controls_Manager::SLIDER,
526 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
527 'range' => [
528 'px' => [
529 'max' => 100,
530 ],
531 'em' => [
532 'max' => 40,
533 ],
534 'rem' => [
535 'max' => 40,
536 ],
537 ],
538 'selectors' => [
539 '{{WRAPPER}}' => '--ui-e-tabs-gap: {{SIZE}}{{UNIT}}',
540 ],
541 ] );
542
543 $this->start_controls_tabs( 'tabs_title_style' );
544
545 $this->start_controls_tab(
546 'tabs_title_normal',
547 [
548 'label' => esc_html__( 'Normal', 'uicore-elements' ),
549 ]
550 );
551
552 $this->add_group_control(
553 Group_Control_Background::get_type(),
554 [
555 'name' => 'tabs_title_background_color',
556 'types' => [ 'classic', 'gradient' ],
557 'exclude' => [ 'image' ],
558 'selector' => "{$heading_selector} > .ui-e-tab-title[aria-selected=\"false\"]",
559 'fields_options' => [
560 'color' => [
561 'label' => esc_html__( 'Background Color', 'uicore-elements' ),
562 'selectors' => [
563 '{{SELECTOR}}' => 'background: {{VALUE}}',
564 ],
565 ],
566 ],
567 ]
568 );
569
570 $this->add_group_control(
571 Group_Control_Border::get_type(),
572 [
573 'name' => 'tabs_title_border',
574 'selector' => "{$heading_selector} > .ui-e-tab-title[aria-selected=\"false\"]",
575 'fields_options' => [
576 'color' => [
577 'label' => esc_html__( 'Border Color', 'uicore-elements' ),
578 ],
579 'width' => [
580 'label' => esc_html__( 'Border Width', 'uicore-elements' ),
581 ],
582 ],
583 ]
584 );
585
586 $this->add_group_control(
587 Group_Control_Box_Shadow::get_type(),
588 [
589 'name' => 'tabs_title_box_shadow',
590 'label' => esc_html__( 'Shadow', 'uicore-elements' ),
591 'separator' => 'after',
592 'selector' => "{$heading_selector} > .ui-e-tab-title[aria-selected=\"false\"]",
593 ]
594 );
595
596 $this->end_controls_tab();
597
598 $this->start_controls_tab(
599 'tabs_title_hover',
600 [
601 'label' => esc_html__( 'Hover', 'uicore-elements' ),
602 ]
603 );
604
605 $this->add_group_control(
606 Group_Control_Background::get_type(),
607 [
608 'name' => 'tabs_title_background_color_hover',
609 'types' => [ 'classic', 'gradient' ],
610 'exclude' => [ 'image' ],
611 'selector' => "{$heading_selector} > .ui-e-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', 'uicore-elements' ),
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_hover',
633 'selector' => "{$heading_selector} > .ui-e-tab-title[aria-selected=\"false\"]:hover",
634 'fields_options' => [
635 'color' => [
636 'label' => esc_html__( 'Border Color', 'uicore-elements' ),
637 ],
638 'width' => [
639 'label' => esc_html__( 'Border Width', 'uicore-elements' ),
640 ],
641 ],
642 ]
643 );
644
645 $this->add_group_control(
646 Group_Control_Box_Shadow::get_type(),
647 [
648 'name' => 'tabs_title_box_shadow_hover',
649 'label' => esc_html__( 'Shadow', 'uicore-elements' ),
650 'separator' => 'after',
651 'selector' => "{$heading_selector} > .ui-e-tab-title[aria-selected=\"false\"]:hover",
652 ]
653 );
654
655 $this->add_control(
656 'hover_animation',
657 [
658 'label' => esc_html__( 'Hover Animation', 'uicore-elements' ),
659 'type' => Controls_Manager::HOVER_ANIMATION,
660 ]
661 );
662
663 $this->add_control(
664 'tabs_title_transition_duration',
665 [
666 'label' => esc_html__( 'Transition Duration', 'uicore-elements' ) . ' (s)',
667 'type' => Controls_Manager::SLIDER,
668 'selectors' => [
669 '{{WRAPPER}}' => '--ui-e-tabs-title-transition: {{SIZE}}s',
670 ],
671 'range' => [
672 'px' => [
673 'min' => 0,
674 'max' => 3,
675 'step' => 0.1,
676 ],
677 ],
678 ]
679 );
680
681 $this->end_controls_tab();
682
683 $this->start_controls_tab(
684 'tabs_title_active',
685 [
686 'label' => esc_html__( 'Active', 'uicore-elements' ),
687 ]
688 );
689
690 $this->add_group_control(
691 Group_Control_Background::get_type(),
692 [
693 'name' => 'tabs_title_background_color_active',
694 'types' => [ 'classic', 'gradient' ],
695 'exclude' => [ 'image' ],
696 'selector' => "{$heading_selector} > .ui-e-tab-title[aria-selected=\"true\"]",
697 'fields_options' => [
698 'background' => [
699 'default' => 'classic',
700 ],
701 'color' => [
702 'global' => [
703 'default' => Global_Colors::COLOR_ACCENT,
704 ],
705 'label' => esc_html__( 'Background Color', 'uicore-elements' ),
706 'selectors' => [
707 '{{SELECTOR}}' => 'background: {{VALUE}};',
708 ],
709 ],
710 ],
711 ]
712 );
713
714 $this->add_group_control(
715 Group_Control_Border::get_type(),
716 [
717 'name' => 'tabs_title_border_active',
718 'selector' => "{$heading_selector} > .ui-e-tab-title[aria-selected=\"true\"]",
719 'fields_options' => [
720 'color' => [
721 'label' => esc_html__( 'Border Color', 'uicore-elements' ),
722 ],
723 'width' => [
724 'label' => esc_html__( 'Border Width', 'uicore-elements' ),
725 ],
726 ],
727 ]
728 );
729
730 $this->add_group_control(
731 Group_Control_Box_Shadow::get_type(),
732 [
733 'name' => 'tabs_title_box_shadow_active',
734 'label' => esc_html__( 'Shadow', 'uicore-elements' ),
735 'selector' => "{$heading_selector} > .ui-e-tab-title[aria-selected=\"true\"]",
736 ]
737 );
738
739 $this->end_controls_tab();
740
741 $this->end_controls_tabs();
742
743 $this->add_control(
744 'tabs_pill',
745 [
746 'label' => esc_html__( 'Pill Style', 'uicore-elements' ),
747 'type' => Controls_Manager::SWITCHER,
748 'return_value' => 'yes',
749 'prefix_class' => 'ui-e-pill-tabs-',
750 'condition' => [
751 'tabs_direction' => [
752 'block-start',
753 'block-end',
754 ]
755 ],
756 'separator' => 'before',
757 ]
758 );
759
760 $this->add_responsive_control(
761 'tabs_title_border_radius',
762 [
763 'label' => esc_html__( 'Border Radius', 'uicore-elements' ),
764 'type' => Controls_Manager::DIMENSIONS,
765 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
766 'selectors' => [
767 "{$heading_selector}" => '--ui-e-tab-border-top: {{TOP}}{{UNIT}}; --ui-e-tab-border-right: {{RIGHT}}{{UNIT}}; --ui-e-tab-border-bot: {{BOTTOM}}{{UNIT}}; --ui-e-tab-border-left: {{LEFT}}{{UNIT}};',
768 ],
769 ]
770 );
771
772 $this->add_responsive_control(
773 'padding',
774 [
775 'label' => esc_html__( 'Padding', 'uicore-elements' ),
776 'type' => Controls_Manager::DIMENSIONS,
777 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
778 'selectors' => [
779 "{$heading_selector} > .ui-e-tab-title" => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
780 ],
781 ]
782 );
783
784 $this->end_controls_section();
785
786 $this->start_controls_section(
787 'section_title_style',
788 [
789 'label' => esc_html__( 'Titles', 'uicore-elements' ),
790 'tab' => Controls_Manager::TAB_STYLE,
791 ]
792 );
793
794 $this->add_group_control( Group_Control_Typography::get_type(), [
795 'name' => 'title_typography',
796 'global' => [
797 'default' => Global_Typography::TYPOGRAPHY_ACCENT,
798 ],
799 'selector' => "{$heading_selector} .ui-e-tab-texts span",
800 ] );
801
802 $this->start_controls_tabs( 'title_style' );
803
804 $this->start_controls_tab(
805 'title_normal',
806 [
807 'label' => esc_html__( 'Normal', 'uicore-elements' ),
808 ]
809 );
810
811 $this->add_control(
812 'title_text_color',
813 [
814 'label' => esc_html__( 'Color', 'uicore-elements' ),
815 'type' => Controls_Manager::COLOR,
816 'selectors' => [
817 "{$heading_selector} > .ui-e-tab-title[aria-selected=\"false\"] .ui-e-tab-texts > span" => 'color: {{VALUE}}',
818 ],
819 ]
820 );
821
822 $this->end_controls_tab();
823
824 $this->start_controls_tab(
825 'title_hover',
826 [
827 'label' => esc_html__( 'Hover', 'uicore-elements' ),
828 ]
829 );
830
831 $this->add_control(
832 'title_text_color_hover',
833 [
834 'label' => esc_html__( 'Color', 'uicore-elements' ),
835 'type' => Controls_Manager::COLOR,
836 'selectors' => [
837 "{$heading_selector} > .ui-e-tab-title[aria-selected=\"false\"]:hover .ui-e-tab-texts > span" => 'color: {{VALUE}}',
838 ],
839 ]
840 );
841
842 $this->end_controls_tab();
843
844 $this->start_controls_tab(
845 'title_active',
846 [
847 'label' => esc_html__( 'Active', 'uicore-elements' ),
848 ]
849 );
850
851 $this->add_control(
852 'title_text_color_active',
853 [
854 'label' => esc_html__( 'Color', 'uicore-elements' ),
855 'type' => Controls_Manager::COLOR,
856 'selectors' => [
857 "{$heading_selector} > .ui-e-tab-title[aria-selected=\"true\"] .ui-e-tab-texts > span" => 'color: {{VALUE}}',
858 ],
859 ]
860 );
861
862 $this->end_controls_tab();
863
864 $this->end_controls_tabs();
865
866 $this->end_controls_section();
867
868 $this->start_controls_section(
869 'section_description_style',
870 [
871 'label' => esc_html__( 'Description', 'uicore-elements' ),
872 'tab' => Controls_Manager::TAB_STYLE,
873 ]
874 );
875
876 $this->add_group_control( Group_Control_Typography::get_type(), [
877 'name' => 'description_typography',
878 'global' => [
879 'default' => Global_Typography::TYPOGRAPHY_ACCENT,
880 ],
881 'selector' => "{$heading_selector} .ui-e-tab-texts p",
882 ] );
883
884 $this->add_responsive_control(
885 'description_spacing',
886 [
887 'label' => esc_html__( 'Top Spacing', 'uicore-elements' ),
888 'type' => Controls_Manager::SLIDER,
889 'range' => [
890 'px' => [
891 'max' => 50,
892 ],
893 '%' => [
894 'max' => 50,
895 'step' => 0.1,
896 ],
897 ],
898 'default' => [
899 'size' => 0,
900 'unit' => 'px',
901 ],
902 'size_units' => [ 'px', 'em', 'rem', '%'],
903 'selectors' => [
904 "{$heading_selector} .ui-e-tab-texts > p" => 'margin-top: {{SIZE}}{{UNIT}}',
905 ],
906 ]
907 );
908
909 $this->start_controls_tabs( 'description_style' );
910
911 $this->start_controls_tab(
912 'description_normal',
913 [
914 'label' => esc_html__( 'Normal', 'uicore-elements' ),
915 ]
916 );
917
918 $this->add_control(
919 'description_text_color',
920 [
921 'label' => esc_html__( 'Color', 'uicore-elements' ),
922 'type' => Controls_Manager::COLOR,
923 'selectors' => [
924 "{$heading_selector} > .ui-e-tab-title[aria-selected=\"false\"] .ui-e-tab-texts > p" => 'color: {{VALUE}}',
925 ],
926 ]
927 );
928
929 $this->end_controls_tab();
930
931 $this->start_controls_tab(
932 'description_hover',
933 [
934 'label' => esc_html__( 'Hover', 'uicore-elements' ),
935 ]
936 );
937
938 $this->add_control(
939 'description_text_color_hover',
940 [
941 'label' => esc_html__( 'Color', 'uicore-elements' ),
942 'type' => Controls_Manager::COLOR,
943 'selectors' => [
944 "{$heading_selector} > .ui-e-tab-title[aria-selected=\"false\"]:hover .ui-e-tab-texts > p" => 'color: {{VALUE}}',
945 ],
946 ]
947 );
948
949 $this->end_controls_tab();
950
951 $this->start_controls_tab(
952 'description_active',
953 [
954 'label' => esc_html__( 'Active', 'uicore-elements' ),
955 ]
956 );
957
958 $this->add_control(
959 'description_text_color_active',
960 [
961 'label' => esc_html__( 'Color', 'uicore-elements' ),
962 'type' => Controls_Manager::COLOR,
963 'selectors' => [
964 "{$heading_selector} > .ui-e-tab-title[aria-selected=\"true\"] .ui-e-tab-texts > p" => 'color: {{VALUE}}',
965 ],
966 ]
967 );
968
969 $this->end_controls_tab();
970
971 $this->end_controls_tabs();
972
973 $this->end_controls_section();
974
975 $this->start_controls_section(
976 'icon_section_style',
977 [
978 'label' => esc_html__( 'Icon', 'uicore-elements' ),
979 'tab' => Controls_Manager::TAB_STYLE,
980 ]
981 );
982
983 $this->add_responsive_control( 'icon_size', [
984 'label' => esc_html__( 'Size', 'uicore-elements' ),
985 'type' => Controls_Manager::SLIDER,
986 'range' => [
987 'px' => [
988 'max' => 100,
989 ],
990 'em' => [
991 'max' => 10,
992 ],
993 'rem' => [
994 'max' => 10,
995 ],
996 ],
997 'size_units' => [ 'px', 'em', 'rem', 'vw', 'custom' ],
998 'selectors' => [
999 '{{WRAPPER}}' => '--ui-e-tabs-icon-size: {{SIZE}}{{UNIT}}',
1000 ],
1001 ] );
1002
1003 $this->add_responsive_control( 'icon_spacing', [
1004 'label' => esc_html__( 'Spacing', 'uicore-elements' ),
1005 'type' => Controls_Manager::SLIDER,
1006 'range' => [
1007 'px' => [
1008 'max' => 200,
1009 ],
1010 'vw' => [
1011 'max' => 50,
1012 'step' => 0.1,
1013 ],
1014 ],
1015 'size_units' => [ 'px', 'em', 'rem', 'vw', 'custom' ],
1016 'selectors' => [
1017 '{{WRAPPER}} .ui-e-tab-title' => 'gap: {{SIZE}}{{UNIT}}',
1018 ],
1019 ] );
1020
1021 $this->add_control(
1022 'icon_padding',
1023 [
1024 'label' => esc_html__( 'Padding', 'uicore-elements' ),
1025 'type' => Controls_Manager::DIMENSIONS,
1026 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
1027 'selectors' => [
1028 '{{WRAPPER}} .ui-e-tab-title .ui-e-tab-icon' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1029 ],
1030 ]
1031 );
1032
1033 $this->add_control(
1034 'icon_border_radius',
1035 [
1036 'label' => esc_html__( 'Border Radius', 'uicore-elements' ),
1037 'type' => Controls_Manager::DIMENSIONS,
1038 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
1039 'selectors' => [
1040 '{{WRAPPER}} .ui-e-tab-title .ui-e-tab-icon' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1041 ],
1042 ]
1043 );
1044
1045 $this->add_group_control(
1046 Group_Control_Border::get_type(),
1047 [
1048 'name' => 'icon_border',
1049 'selector' => '{{WRAPPER}} .ui-e-tab-title .ui-e-tab-icon',
1050 ]
1051 );
1052
1053 $this->start_controls_tabs( 'icon_style_states' );
1054
1055 $this->start_controls_tab(
1056 'icon_section_normal',
1057 [
1058 'label' => esc_html__( 'Normal', 'uicore-elements' ),
1059 ]
1060 );
1061
1062 $this->add_control( 'icon_color', [
1063 'label' => esc_html__( 'Color', 'uicore-elements' ),
1064 'type' => Controls_Manager::COLOR,
1065 'selectors' => [
1066 '{{WRAPPER}} .ui-e-tab-title .ui-e-tab-icon > i' => 'color: {{VALUE}}',
1067 '{{WRAPPER}} .ui-e-tab-title .ui-e-tab-icon > svg' => 'fill: {{VALUE}}',
1068 ],
1069 ] );
1070
1071 $this->add_control(
1072 'icon_background_color',
1073 [
1074 'label' => esc_html__( 'Background Color', 'uicore-elements' ),
1075 'type' => Controls_Manager::COLOR,
1076 'selectors' => [
1077 '{{WRAPPER}} .ui-e-tab-title .ui-e-tab-icon' => 'background-color: {{VALUE}}',
1078 ],
1079 ]
1080 );
1081
1082 $this->end_controls_tab();
1083
1084 $this->start_controls_tab(
1085 'icon_section_hover',
1086 [
1087 'label' => esc_html__( 'Hover', 'uicore-elements' ),
1088 ]
1089 );
1090
1091 $this->add_control( 'icon_color_hover', [
1092 'label' => esc_html__( 'Color', 'uicore-elements' ),
1093 'type' => Controls_Manager::COLOR,
1094 'selectors' => [
1095 '{{WRAPPER}} .ui-e-tab-title:hover .ui-e-tab-icon > i' => 'color: {{VALUE}}',
1096 '{{WRAPPER}} .ui-e-tab-title:hover .ui-e-tab-icon > svg' => 'fill: {{VALUE}}',
1097 ],
1098 ] );
1099
1100 $this->add_control(
1101 'icon_background_color_hover',
1102 [
1103 'label' => esc_html__( 'Background Color', 'uicore-elements' ),
1104 'type' => Controls_Manager::COLOR,
1105 'selectors' => [
1106 '{{WRAPPER}} .ui-e-tab-title:hover .ui-e-tab-icon' => 'background-color: {{VALUE}}',
1107 ],
1108 ]
1109 );
1110
1111 $this->end_controls_tab();
1112
1113 $this->start_controls_tab(
1114 'icon_section_active',
1115 [
1116 'label' => esc_html__( 'Active', 'uicore-elements' ),
1117 ]
1118 );
1119
1120 $this->add_control( 'icon_color_active', [
1121 'label' => esc_html__( 'Color', 'uicore-elements' ),
1122 'type' => Controls_Manager::COLOR,
1123 'selectors' => [
1124 '{{WRAPPER}} .ui-e-tab-title[aria-selected="true"] .ui-e-tab-icon > i' => 'color: {{VALUE}}',
1125 '{{WRAPPER}} .ui-e-tab-title[aria-selected="true"] .ui-e-tab-icon > svg' => 'fill: {{VALUE}}',
1126 ],
1127 ] );
1128
1129 $this->add_control(
1130 'icon_background_color_active',
1131 [
1132 'label' => esc_html__( 'Background Color', 'uicore-elements' ),
1133 'type' => Controls_Manager::COLOR,
1134 'selectors' => [
1135 '{{WRAPPER}} .ui-e-tab-title[aria-selected="true"] .ui-e-tab-icon' => 'background-color: {{VALUE}}',
1136 ],
1137 ]
1138 );
1139
1140 $this->end_controls_tab();
1141
1142 $this->end_controls_tabs();
1143
1144 $this->end_controls_section();
1145
1146 $this->start_controls_section( 'section_box_style', [
1147 'label' => esc_html__( 'Content', 'uicore-elements' ),
1148 'tab' => Controls_Manager::TAB_STYLE,
1149 ] );
1150
1151 $this->add_group_control(
1152 Group_Control_Background::get_type(),
1153 [
1154 'name' => 'box_background_color',
1155 'types' => [ 'classic', 'gradient' ],
1156 'exclude' => [ 'image' ],
1157 'selector' => $content_selector,
1158 'fields_options' => [
1159 'color' => [
1160 'label' => esc_html__( 'Background Color', 'uicore-elements' ),
1161 ],
1162 ],
1163 ]
1164 );
1165
1166 $this->add_group_control(
1167 Group_Control_Border::get_type(),
1168 [
1169 'name' => 'box_border',
1170 'selector' => $content_selector,
1171 'fields_options' => [
1172 'color' => [
1173 'label' => esc_html__( 'Border Color', 'uicore-elements' ),
1174 ],
1175 'width' => [
1176 'label' => esc_html__( 'Border Width', 'uicore-elements' ),
1177 ],
1178 ],
1179 ]
1180 );
1181
1182 $this->add_responsive_control(
1183 'box_border_radius',
1184 [
1185 'label' => esc_html__( 'Border Radius', 'uicore-elements' ),
1186 'type' => Controls_Manager::DIMENSIONS,
1187 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
1188 'selectors' => [
1189 $content_selector => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1190 ],
1191 ]
1192 );
1193
1194 $this->add_group_control(
1195 Group_Control_Box_Shadow::get_type(),
1196 [
1197 'name' => 'box_shadow_box_shadow',
1198 'selector' => $content_selector,
1199 ]
1200 );
1201
1202 $this->add_responsive_control(
1203 'box_padding',
1204 [
1205 'label' => esc_html__( 'Padding', 'uicore-elements' ),
1206 'type' => Controls_Manager::DIMENSIONS,
1207 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1208 'selectors' => [
1209 $content_selector => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1210 ],
1211 ]
1212 );
1213
1214 $this->end_controls_section();
1215
1216 }
1217
1218 protected function maybe_render_tab_icons_html( $item_settings ): void {
1219 $icon_settings = $item_settings['item']['tab_icon'];
1220
1221 if ( empty( $icon_settings['value'] ) ) {
1222 return;
1223 }
1224
1225 $active_icon_settings = $this->is_active_icon_exist( $item_settings['item'] )
1226 ? $item_settings['item']['tab_icon_active']
1227 : $icon_settings;
1228 ?>
1229 <span <?php $this->print_render_attribute_string( 'tab-icon' ); ?>>
1230 <?php Icons_Manager::render_icon( $active_icon_settings, [ 'aria-hidden' => 'true' ] ); ?>
1231 <?php Icons_Manager::render_icon( $icon_settings, [ 'aria-hidden' => 'true' ] ); ?>
1232 </span>
1233 <?php
1234 }
1235
1236 protected function render_tab_titles_html( $item_settings ): string {
1237 // Data
1238 $setting_key = $this->get_repeater_setting_key( 'tab_title', 'tabs', $item_settings['index'] );
1239 $title = $item_settings['item']['tab_title'];
1240 $description = $item_settings['item']['tab_description'];
1241 // Classes
1242 $hover_animation = $item_settings['hover_animation'] ? 'elementor-animation-' . $item_settings['hover_animation'] : '';
1243 $toggle_description = $item_settings['show_description'] ? 'ui-e-toggle-description' : '';
1244
1245 $this->add_render_attribute( $setting_key, [
1246 'id' => $item_settings['tab_id'],
1247 'class' => [
1248 'ui-e-tab-title',
1249 $toggle_description,
1250 $hover_animation
1251 ],
1252 'aria-selected' => (1 === (int)$item_settings['tab_count'] ? 'true' : 'false'),
1253 'data-tab-index' => $item_settings['tab_count'],
1254 'role' => 'tab',
1255 'tabindex' => (1 === $item_settings['tab_count'] ? '0' : '-1'),
1256 'aria-controls' => $item_settings['container_id'],
1257 'style' => '--ui-e-tabs-order: ' . $item_settings['tab_count'] . ';',
1258 ] );
1259
1260 $render_attributes = $this->get_render_attribute_string( $setting_key );
1261 $text_class = $this->get_render_attribute_string( 'tab-texts' );
1262
1263 ob_start();
1264 ?>
1265 <button <?php echo $render_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
1266 <?php $this->maybe_render_tab_icons_html( $item_settings ); ?>
1267 <div <?php echo $text_class; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
1268
1269 <?php if( !empty( $title ) ) : ?>
1270 <span> <?php echo wp_kses_post( $title ); ?> </span>
1271 <?php endif; ?>
1272
1273 <?php if( !empty( $description ) ) : ?>
1274 <p> <?php echo wp_kses_post( $description ); ?> </p>
1275 <?php endif; ?>
1276
1277 </div>
1278 </button>
1279 <?php
1280 return ob_get_clean();
1281 }
1282
1283 protected function render_tab_containers_html( $item_settings ): string {
1284 ob_start();
1285 $this->print_child( $item_settings['index'], $item_settings );
1286 return ob_get_clean();
1287 }
1288
1289 private function is_active_icon_exist( $item ) {
1290 return array_key_exists( 'tab_icon_active', $item ) && ! empty( $item['tab_icon_active'] ) && ! empty( $item['tab_icon_active']['value'] );
1291 }
1292
1293 /**
1294 * Print the content area.
1295 *
1296 * @param int $index
1297 * @param array $item_settings
1298 */
1299 public function print_child( $index, $item_settings = [] ) {
1300 $children = $this->get_children();
1301 $child_ids = [];
1302 if( empty( $children )){
1303 return;
1304 }
1305 foreach ( $children as $child ) {
1306 $child_ids[] = $child->get_id();
1307 }
1308
1309 // Add data-tab-index attribute to the content area.
1310 $add_attribute_to_container = function ( $should_render, $container ) use ( $item_settings, $child_ids ) {
1311 if ( in_array( $container->get_id(), $child_ids ) ) {
1312 $this->add_attributes_to_container( $container, $item_settings );
1313 }
1314
1315 return $should_render;
1316 };
1317
1318 add_filter( 'elementor/frontend/container/should_render', $add_attribute_to_container, 10, 3 );
1319 $children[ $index ]->print_element();
1320 remove_filter( 'elementor/frontend/container/should_render', $add_attribute_to_container );
1321 }
1322
1323 protected function add_attributes_to_container( $container, $item_settings ) {
1324 $container->add_render_attribute( '_wrapper', [
1325 'id' => $item_settings['container_id'],
1326 'role' => 'tabpanel',
1327 'aria-labelledby' => $item_settings['tab_id'],
1328 'data-tab-index' => $item_settings['tab_count'],
1329 'style' => '--ui-e-tabs-order: ' . $item_settings['tab_count'] . ';',
1330 'class' => 0 === $item_settings['index'] ? 'e-active' : '',
1331 ] );
1332 }
1333
1334 protected function render() {
1335
1336 if( Plugin::$instance->experiments->is_feature_active('nested-elements') == false ){
1337 $this->nesting_fallback();
1338 return;
1339 }
1340
1341 $settings = $this->get_settings_for_display();
1342 $widget_number = substr( $this->get_id_int(), 0, 3 );
1343
1344 $this->add_render_attribute( 'elementor-tabs', [
1345 'class' => 'ui-e-tabs',
1346 'data-widget-number' => $widget_number,
1347 'aria-label' => esc_html__( 'Tabs. Open items with Enter or Space, close with Escape and navigate using the Arrow keys.', 'uicore-elements' ),
1348 ] );
1349
1350 $this->add_render_attribute( 'tab-texts', 'class', 'ui-e-tab-texts' );
1351 $this->add_render_attribute( 'tab-icon', 'class', 'ui-e-tab-icon' );
1352 $this->add_render_attribute( 'tab-icon-active', 'class', [ 'ui-e-tab-icon' ] );
1353
1354 $tab_titles_html = '';
1355 $tab_containers_html = '';
1356
1357 foreach ( $settings['tabs'] as $index => $item ) {
1358 $tab_count = $index + 1;
1359
1360 $tab_id = empty( $item['tab_id'] )
1361 ? 'ui-e-tab-title-' . $widget_number . $tab_count
1362 : $item['tab_id'];
1363
1364 $item_settings = [
1365 'index' => $index,
1366 'tab_count' => $tab_count,
1367 'tab_id' => $tab_id,
1368 'container_id' => 'ui-e-tab-content-' . $widget_number . $tab_count,
1369 'widget_number' => $widget_number,
1370 'hover_animation' => $settings['hover_animation'],
1371 'show_description' => $settings['show_description'],
1372 'item' => $item,
1373 'settings' => $settings,
1374 ];
1375
1376 $tab_titles_html .= $this->render_tab_titles_html( $item_settings );
1377 $tab_containers_html .= $this->render_tab_containers_html( $item_settings );
1378 }
1379 ?>
1380 <div <?php $this->print_render_attribute_string( 'elementor-tabs' ); ?>>
1381 <div class="ui-e-tabs-heading" role="tablist">
1382 <?php echo $tab_titles_html;// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1383 </div>
1384 <div class="ui-e-tabs-content">
1385 <?php echo $tab_containers_html;// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1386 </div>
1387 </div>
1388 <?php
1389 }
1390
1391 protected function get_initial_config(): array {
1392 if ( Plugin::$instance->experiments->is_feature_active( 'e_nested_atomic_repeaters' ) ) {
1393 return array_merge( parent::get_initial_config(), [
1394 'support_improved_repeaters' => true,
1395 'target_container' => [ '.ui-e-tabs-heading' ],
1396 'node' => 'button',
1397 ] );
1398 }
1399
1400 return parent::get_initial_config();
1401 }
1402 /*
1403 protected function content_template_single_repeater_item() {
1404 ?>
1405 <#
1406 const tabCount = view.collection.length + 1,
1407 elementUid = view.getIDInt().toString().substring( 0, 3 ) + tabCount,
1408 tabIcon = elementor.helpers.renderIcon( view, data.tab_icon, { 'aria-hidden': true }, 'i' , 'object' );
1409
1410 let tabActiveIcon = tabIcon,
1411 tabId = 'ui-e-tab-title-' + elementUid;
1412
1413 if ( '' !== data.tab_icon_active.value ) {
1414 tabActiveIcon = elementor.helpers.renderIcon( view, data.tab_icon_active, { 'aria-hidden': true }, 'i' , 'object' );
1415 }
1416
1417 const tabWrapperKey = {
1418 'id': 'ui-e-tab-title-' + elementUid,
1419 'class': [ 'ui-e-tab-title' ],
1420 'data-tab-index': tabCount,
1421 'role': 'tab',
1422 'aria-selected': 1 === tabCount ? 'true' : 'false',
1423 'tabindex': 1 === tabCount ? '0' : '-1',
1424 'aria-controls': 'ui-e-tab-content-' + elementUid,
1425 'style': '--ui-e-tabs-order: ' + tabCount + ';',
1426 };
1427
1428 const tabIconKey = {
1429 'class': [ 'ui-e-tab-icon' ],
1430 'data-binding-type': 'repeater-item',
1431 'data-binding-repeater-name': 'tabs',
1432 'data-binding-setting': [ data.tab_icon.value, data.tab_icon_active.value ],
1433 'data-binding-index': tabCount,
1434 };
1435
1436 const tabTitleKey = {
1437 'class': [ 'ui-e-tab-title-text' ],
1438 'data-binding-type': 'repeater-item',
1439 'data-binding-repeater-name': 'tabs',
1440 'data-binding-setting': [ 'tab_title' ],
1441 'data-binding-index': tabCount,
1442 };
1443
1444 view.addRenderAttribute( 'button-container', tabWrapperKey, null, true );
1445 view.addRenderAttribute( 'tab-title-container', tabTitleKey, null, true );
1446 view.addRenderAttribute( 'tab-icon-key-container', tabIconKey, null, true );
1447 #>
1448
1449 <button {{{ view.getRenderAttributeString( 'button-container' ) }}}>
1450 <# if ( tabIcon.value ) { #>
1451 <span {{{ view.getRenderAttributeString( 'tab-icon-key-container' ) }}}> {{{ tabIcon.value }}}{{{ tabActiveIcon.value }}} </span>
1452 <# } #>
1453 <span {{{ view.getRenderAttributeString( 'tab-title-container' ) }}}> {{{ data.tab_title }}} </span>
1454 </button>
1455 <?php
1456 }
1457 */
1458 /*
1459 protected function content_template_single_repeater_item() {
1460 ?>
1461 <#
1462 const tabIndex = view.collection.length,
1463 elementUid = view.getIDInt().toString(),
1464 item = data,
1465 hoverAnimationSetting = view?.container?.settings?.attributes?.hover_animation;
1466 hoverAnimationClass = hoverAnimationSetting
1467 ? `elementor-animation-${ hoverAnimationSetting }`
1468 : '';
1469 #>
1470 <?php $this->content_template_single_item( '{{ tabIndex }}', '{{ item }}', '{{ elementUid }}', '{{ hoverAnimationClass }}' );
1471 }
1472 */
1473 protected function content_template() {
1474
1475 if( Plugin::$instance->experiments->is_feature_active('nested-elements') == false ){
1476 return;
1477 }
1478
1479 ?>
1480 <# const elementUid = view.getIDInt().toString().substr( 0, 3 ); #>
1481 <div class="ui-e-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.', 'uicore-elements' ); ?>">
1482 <# if ( settings['tabs'] ) { #>
1483 <div class="ui-e-tabs-heading" role="tablist">
1484 <# _.each( settings['tabs'], function( item, index ) {
1485 const tabCount = index + 1,
1486 tabUid = elementUid + tabCount,
1487 tabWrapperKey = tabUid,
1488 tabTitleKey = 'tab-title-' + tabUid,
1489 tabIconKey = 'tab-icon-' + tabUid,
1490 tabIcon = elementor.helpers.renderIcon( view, item.tab_icon, { 'aria-hidden': true }, 'i' , 'object' ),
1491 hoverAnimationClass = settings['hover_animation'] ? `elementor-animation-${ settings['hover_animation'] }` : '',
1492 showDescription = settings['show_description'] ? 'ui-e-toggle-description' : '';
1493
1494 let tabActiveIcon = tabIcon,
1495 tabId = 'ui-e-tab-title-' + tabUid;
1496
1497 if ( '' !== item.tab_icon_active.value ) {
1498 tabActiveIcon = elementor.helpers.renderIcon( view, item.tab_icon_active, { 'aria-hidden': true }, 'i' , 'object' );
1499 }
1500
1501 if ( '' !== item.tab_id ) {
1502 tabId = item.tab_id;
1503 }
1504
1505 view.addRenderAttribute( tabWrapperKey, {
1506 'id': tabId,
1507 'class': [ 'ui-e-tab-title', hoverAnimationClass, showDescription ],
1508 'data-tab-index': tabCount,
1509 'role': 'tab',
1510 'aria-selected': 1 === tabCount ? 'true' : 'false',
1511 'tabindex': 1 === tabCount ? '0' : '-1',
1512 'aria-controls': 'ui-e-tab-content-' + tabUid,
1513 'style': '--ui-e-tabs-order: ' + tabCount + ';',
1514 } );
1515
1516 view.addRenderAttribute( tabTitleKey, {
1517 'class': [ 'ui-e-tab-texts' ],
1518 'data-binding-type': 'repeater-item',
1519 'data-binding-repeater-name': 'tabs',
1520 'data-binding-setting': [ 'tab_title' ],
1521 'data-binding-index': tabCount,
1522 } );
1523
1524 view.addRenderAttribute( tabIconKey, {
1525 'class': [ 'ui-e-tab-icon' ],
1526 'data-binding-type': 'repeater-item',
1527 'data-binding-repeater-name': 'tabs',
1528 'data-binding-setting': [ 'tab_icon.value', 'tab_icon_active.value' ],
1529 'data-binding-index': tabCount,
1530 } );
1531 #>
1532 <button {{{ view.getRenderAttributeString( tabWrapperKey ) }}}>
1533 <# if ( tabIcon.value ) { #>
1534 <span {{{ view.getRenderAttributeString( tabIconKey ) }}}>{{{ tabActiveIcon.value }}}{{{ tabIcon.value }}}</span>
1535 <# } #>
1536 <div {{{ view.getRenderAttributeString( tabTitleKey ) }}}>
1537 <# if ( item.tab_title ) { #>
1538 <span> {{{ item.tab_title }}} </span>
1539 <# } #>
1540 <# if ( item.tab_description ) { #>
1541 <p> {{{ item.tab_description }}} </p>
1542 <# } #>
1543 </div>
1544 </button>
1545 <# } ); #>
1546 </div>
1547 <div class="ui-e-tabs-content"></div>
1548 <# } #>
1549 </div>
1550 <?php
1551 }
1552 /*
1553 private function content_template_single_item( $tab_index, $item, $element_uid, $hover_animation_class ) {
1554 ?>
1555 <#
1556 const tabCount = tabIndex + 1,
1557 tabId = item.tab_id
1558 ? item.tab_id
1559 : 'ui-e-tab-title-' + elementUid + ( tabIndex + 1 ),
1560 tabUid = elementUid + tabCount,
1561 tabIcon = elementor.helpers.renderIcon( view, item.tab_icon, { 'aria-hidden': true }, 'i' , 'object' ),
1562 activeTabIcon = item.tab_icon_active.value
1563 ? elementor.helpers.renderIcon( view, item.tab_icon_active, { 'aria-hidden': true }, 'i' , 'object' )
1564 : tabIcon,
1565 escapedHoverAnimationClass = _.escape( hoverAnimationClass );
1566
1567 view.addRenderAttribute( 'tab-title', {
1568 'id': tabId,
1569 'class': [ 'ui-e-tab-title',escapedHoverAnimationClass ],
1570 'data-tab-index': tabCount,
1571 'role': 'tab',
1572 'aria-selected': 1 === tabCount ? 'true' : 'false',
1573 'tabindex': 1 === tabCount ? '0' : '-1',
1574 'aria-controls': 'ui-e-tab-content-' + tabUid,
1575 'style': '--ui-e-tabs-order: ' + tabCount + ';',
1576 }, null, true );
1577
1578 view.addRenderAttribute( 'tab-title-text', {
1579 'class': [ 'ui-e-tab-title-text' ],
1580 'data-binding-type': 'repeater-item',
1581 'data-binding-repeater-name': 'tabs',
1582 'data-binding-setting': [ 'tab_title' ],
1583 'data-binding-index': tabCount,
1584 'data-binding-dynamic': 'true',
1585 }, null, true );
1586
1587 view.addRenderAttribute( 'tab-icon', {
1588 'class': [ 'ui-e-tab-icon' ],
1589 'data-binding-type': 'repeater-item',
1590 'data-binding-repeater-name': 'tabs',
1591 'data-binding-setting': [ 'tab_icon', 'tab_icon_active' ],
1592 'data-binding-index': tabCount,
1593 }, null, true );
1594 #>
1595
1596 <button {{{ view.getRenderAttributeString( 'tab-title' ) }}}>
1597 <# if ( !! item.tab_icon.value ) { #>
1598 <span {{{ view.getRenderAttributeString( 'tab-icon' ) }}}>{{{ tabIcon.value }}}{{{ activeTabIcon.value }}}</span>
1599 <# } #>
1600
1601 <span {{{ view.getRenderAttributeString( 'tab-title-text' ) }}}>{{{ item.tab_title }}}</span>
1602 </button>
1603 <?php
1604 }
1605 */
1606 }
1607 \Elementor\Plugin::instance()->widgets_manager->register(new Tabs());