PluginProbe
UiCore Elements – Free widgets and templates for Elementor / 1.0.9
UiCore Elements – Free widgets and templates for Elementor v1.0.9
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.9, at includes/widgets/tabs.php

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