@shohojdhara/atomix 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/README.md +3 -3
- package/dist/atomix.css +77 -9
- package/dist/atomix.min.css +1 -1
- package/dist/index.d.ts +202 -10
- package/dist/index.esm.js +599 -170
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +608 -170
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/themes/applemix.css +77 -9
- package/dist/themes/applemix.min.css +1 -1
- package/dist/themes/boomdevs.css +77 -9
- package/dist/themes/boomdevs.min.css +1 -1
- package/dist/themes/esrar.css +77 -9
- package/dist/themes/esrar.min.css +1 -1
- package/dist/themes/flashtrade.css +77 -9
- package/dist/themes/flashtrade.min.css +1 -1
- package/dist/themes/mashroom.css +77 -9
- package/dist/themes/mashroom.min.css +1 -1
- package/dist/themes/shaj-default.css +77 -9
- package/dist/themes/shaj-default.min.css +1 -1
- package/package.json +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +0 -2
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +0 -1
- package/src/components/Button/Button.stories.tsx +25 -0
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +121 -11
- package/src/components/ColorModeToggle/ColorModeToggle.tsx +146 -45
- package/src/components/ColorModeToggle/index.ts +1 -1
- package/src/components/Hero/Hero.stories.tsx +297 -0
- package/src/components/Hero/Hero.tsx +79 -0
- package/src/components/{Tab/Tab.stories.tsx → Tabs/Tabs.stories.tsx} +9 -9
- package/src/components/{Tab/Tab.tsx → Tabs/Tabs.tsx} +7 -7
- package/src/components/Tabs/index.ts +2 -0
- package/src/components/index.ts +12 -2
- package/src/lib/composables/useHero.ts +33 -4
- package/src/lib/composables/useHeroBackgroundSlider.ts +228 -0
- package/src/lib/constants/components.ts +7 -1
- package/src/lib/types/components.ts +98 -0
- package/src/styles/06-components/_components.atomix-glass.scss +4 -3
- package/src/styles/06-components/_components.color-mode-toggle.scss +43 -6
- package/src/styles/06-components/_components.hero.scss +51 -1
- package/src/components/Tab/index.ts +0 -2
|
@@ -100,6 +100,10 @@ const meta = {
|
|
|
100
100
|
control: 'object',
|
|
101
101
|
description: 'Video background options',
|
|
102
102
|
},
|
|
103
|
+
backgroundSlider: {
|
|
104
|
+
control: 'object',
|
|
105
|
+
description: 'Background slider configuration with multiple images/videos',
|
|
106
|
+
},
|
|
103
107
|
},
|
|
104
108
|
} satisfies Meta<typeof Hero>;
|
|
105
109
|
|
|
@@ -345,3 +349,296 @@ export const VideoBackgroundWithImage: Story = {
|
|
|
345
349
|
imageAlt: 'Product showcase',
|
|
346
350
|
},
|
|
347
351
|
};
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Hero with background image slider (fade transition)
|
|
355
|
+
*/
|
|
356
|
+
export const WithBackgroundSlider: Story = {
|
|
357
|
+
args: {
|
|
358
|
+
title: 'Dynamic Background Slider',
|
|
359
|
+
subtitle: 'Multiple Images with Fade Transition',
|
|
360
|
+
text: 'This hero features a background slider with multiple images that automatically transition using a smooth fade effect. Perfect for showcasing multiple products or features.',
|
|
361
|
+
alignment: 'center',
|
|
362
|
+
showOverlay: true,
|
|
363
|
+
actions: showcaseActionButtons,
|
|
364
|
+
contentWidth: '800px',
|
|
365
|
+
backgroundSlider: {
|
|
366
|
+
slides: [
|
|
367
|
+
{
|
|
368
|
+
type: 'image',
|
|
369
|
+
src: 'https://picsum.photos/id/1015/1920/1080',
|
|
370
|
+
alt: 'Mountain landscape',
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
type: 'image',
|
|
374
|
+
src: 'https://picsum.photos/id/1018/1920/1080',
|
|
375
|
+
alt: 'Forest scene',
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
type: 'image',
|
|
379
|
+
src: 'https://picsum.photos/id/1025/1920/1080',
|
|
380
|
+
alt: 'Ocean view',
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
type: 'image',
|
|
384
|
+
src: 'https://picsum.photos/id/1035/1920/1080',
|
|
385
|
+
alt: 'City skyline',
|
|
386
|
+
},
|
|
387
|
+
],
|
|
388
|
+
autoplay: {
|
|
389
|
+
delay: 3000,
|
|
390
|
+
pauseOnHover: false,
|
|
391
|
+
},
|
|
392
|
+
loop: true,
|
|
393
|
+
transition: 'fade',
|
|
394
|
+
transitionDuration: 1000,
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Hero with background slider (mixed images and videos)
|
|
401
|
+
*/
|
|
402
|
+
export const WithMixedMediaSlider: Story = {
|
|
403
|
+
args: {
|
|
404
|
+
title: 'Mixed Media Background Slider',
|
|
405
|
+
subtitle: 'Images & Videos Combined',
|
|
406
|
+
text: 'This hero demonstrates a background slider that seamlessly transitions between images and videos, creating a rich, dynamic visual experience.',
|
|
407
|
+
alignment: 'center',
|
|
408
|
+
showOverlay: true,
|
|
409
|
+
actions: showcaseActionButtons,
|
|
410
|
+
contentWidth: '800px',
|
|
411
|
+
backgroundSlider: {
|
|
412
|
+
slides: [
|
|
413
|
+
{
|
|
414
|
+
type: 'image',
|
|
415
|
+
src: 'https://picsum.photos/id/1015/1920/1080',
|
|
416
|
+
alt: 'Mountain landscape',
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
type: 'video',
|
|
420
|
+
src: 'https://cdn.pixabay.com/video/2021/02/20/65772-515379427_large.mp4',
|
|
421
|
+
videoOptions: {
|
|
422
|
+
autoplay: true,
|
|
423
|
+
loop: true,
|
|
424
|
+
muted: true,
|
|
425
|
+
posterUrl: 'https://picsum.photos/id/1018/1920/1080',
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
type: 'image',
|
|
430
|
+
src: 'https://picsum.photos/id/1025/1920/1080',
|
|
431
|
+
alt: 'Ocean view',
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
type: 'video',
|
|
435
|
+
src: 'https://cdn.pixabay.com/video/2023/11/18/189639-886016299_large.mp4',
|
|
436
|
+
videoOptions: {
|
|
437
|
+
autoplay: true,
|
|
438
|
+
loop: true,
|
|
439
|
+
muted: true,
|
|
440
|
+
posterUrl: 'https://picsum.photos/id/1035/1920/1080',
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
],
|
|
444
|
+
autoplay: {
|
|
445
|
+
delay: 4000,
|
|
446
|
+
pauseOnHover: false,
|
|
447
|
+
},
|
|
448
|
+
loop: true,
|
|
449
|
+
transition: 'fade',
|
|
450
|
+
transitionDuration: 1500,
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Hero with background slider (fast transitions)
|
|
457
|
+
*/
|
|
458
|
+
export const WithFastSlider: Story = {
|
|
459
|
+
args: {
|
|
460
|
+
title: 'Fast-Paced Background Slider',
|
|
461
|
+
subtitle: 'Quick Transitions',
|
|
462
|
+
text: 'This slider uses faster transition times and shorter delays for a more dynamic, energetic feel.',
|
|
463
|
+
alignment: 'center',
|
|
464
|
+
showOverlay: true,
|
|
465
|
+
actions: primaryActionButtons,
|
|
466
|
+
contentWidth: '800px',
|
|
467
|
+
backgroundSlider: {
|
|
468
|
+
slides: [
|
|
469
|
+
{
|
|
470
|
+
type: 'image',
|
|
471
|
+
src: 'https://picsum.photos/id/106/1920/1080',
|
|
472
|
+
alt: 'Abstract art',
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
type: 'image',
|
|
476
|
+
src: 'https://picsum.photos/id/107/1920/1080',
|
|
477
|
+
alt: 'Nature scene',
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
type: 'image',
|
|
481
|
+
src: 'https://picsum.photos/id/108/1920/1080',
|
|
482
|
+
alt: 'Urban landscape',
|
|
483
|
+
},
|
|
484
|
+
],
|
|
485
|
+
autoplay: {
|
|
486
|
+
delay: 2000,
|
|
487
|
+
pauseOnHover: false,
|
|
488
|
+
},
|
|
489
|
+
loop: true,
|
|
490
|
+
transition: 'fade',
|
|
491
|
+
transitionDuration: 500,
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Hero with background slider (pause on hover)
|
|
498
|
+
*/
|
|
499
|
+
export const WithPauseOnHoverSlider: Story = {
|
|
500
|
+
args: {
|
|
501
|
+
title: 'Interactive Background Slider',
|
|
502
|
+
subtitle: 'Pause on Hover',
|
|
503
|
+
text: 'Hover over this hero to pause the slider. Move your mouse away to resume. Perfect for giving users control over the experience.',
|
|
504
|
+
alignment: 'center',
|
|
505
|
+
showOverlay: true,
|
|
506
|
+
actions: showcaseActionButtons,
|
|
507
|
+
contentWidth: '800px',
|
|
508
|
+
backgroundSlider: {
|
|
509
|
+
slides: [
|
|
510
|
+
{
|
|
511
|
+
type: 'image',
|
|
512
|
+
src: 'https://picsum.photos/id/1015/1920/1080',
|
|
513
|
+
alt: 'Mountain landscape',
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
type: 'image',
|
|
517
|
+
src: 'https://picsum.photos/id/1018/1920/1080',
|
|
518
|
+
alt: 'Forest scene',
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
type: 'image',
|
|
522
|
+
src: 'https://picsum.photos/id/1025/1920/1080',
|
|
523
|
+
alt: 'Ocean view',
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
type: 'image',
|
|
527
|
+
src: 'https://picsum.photos/id/1035/1920/1080',
|
|
528
|
+
alt: 'City skyline',
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
type: 'image',
|
|
532
|
+
src: 'https://picsum.photos/id/1041/1920/1080',
|
|
533
|
+
alt: 'Desert landscape',
|
|
534
|
+
},
|
|
535
|
+
],
|
|
536
|
+
autoplay: {
|
|
537
|
+
delay: 3000,
|
|
538
|
+
pauseOnHover: true,
|
|
539
|
+
},
|
|
540
|
+
loop: true,
|
|
541
|
+
transition: 'fade',
|
|
542
|
+
transitionDuration: 1000,
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Hero with background slider and glass effect
|
|
549
|
+
*/
|
|
550
|
+
export const SliderWithGlassEffect: Story = {
|
|
551
|
+
args: {
|
|
552
|
+
title: 'Slider with Glass Effect',
|
|
553
|
+
subtitle: 'Best of Both Worlds',
|
|
554
|
+
text: 'Combine the dynamic background slider with the elegant glass effect for a truly modern, sophisticated hero section.',
|
|
555
|
+
alignment: 'center',
|
|
556
|
+
showOverlay: true,
|
|
557
|
+
glass: true,
|
|
558
|
+
actions: showcaseActionButtons,
|
|
559
|
+
contentWidth: '800px',
|
|
560
|
+
backgroundSlider: {
|
|
561
|
+
slides: [
|
|
562
|
+
{
|
|
563
|
+
type: 'video',
|
|
564
|
+
src: 'https://cdn.pixabay.com/video/2021/02/20/65772-515379427_large.mp4',
|
|
565
|
+
videoOptions: {
|
|
566
|
+
autoplay: true,
|
|
567
|
+
loop: true,
|
|
568
|
+
muted: true,
|
|
569
|
+
posterUrl: 'https://picsum.photos/id/1018/1920/1080',
|
|
570
|
+
},
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
type: 'video',
|
|
574
|
+
src: 'https://cdn.pixabay.com/video/2020/11/09/56026-478239201_large.mp4',
|
|
575
|
+
videoOptions: {
|
|
576
|
+
autoplay: true,
|
|
577
|
+
loop: true,
|
|
578
|
+
muted: true,
|
|
579
|
+
posterUrl: 'https://picsum.photos/id/1018/1920/1080',
|
|
580
|
+
},
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
type: 'video',
|
|
584
|
+
src: 'https://cdn.pixabay.com/video/2023/11/18/189639-886016299_large.mp4',
|
|
585
|
+
videoOptions: {
|
|
586
|
+
autoplay: true,
|
|
587
|
+
loop: true,
|
|
588
|
+
muted: true,
|
|
589
|
+
posterUrl: 'https://picsum.photos/id/1018/1920/1080',
|
|
590
|
+
},
|
|
591
|
+
},
|
|
592
|
+
],
|
|
593
|
+
autoplay: {
|
|
594
|
+
delay: 30000,
|
|
595
|
+
pauseOnHover: false,
|
|
596
|
+
},
|
|
597
|
+
loop: true,
|
|
598
|
+
transition: 'fade',
|
|
599
|
+
transitionDuration: 1200,
|
|
600
|
+
},
|
|
601
|
+
},
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Hero with background slider (full viewport height)
|
|
606
|
+
*/
|
|
607
|
+
export const FullHeightSlider: Story = {
|
|
608
|
+
args: {
|
|
609
|
+
title: 'Full Height Background Slider',
|
|
610
|
+
subtitle: 'Immersive Experience',
|
|
611
|
+
text: 'This hero takes the full viewport height and features a background slider, creating an immersive, full-screen experience.',
|
|
612
|
+
alignment: 'center',
|
|
613
|
+
showOverlay: true,
|
|
614
|
+
fullViewportHeight: true,
|
|
615
|
+
actions: showcaseActionButtons,
|
|
616
|
+
contentWidth: '800px',
|
|
617
|
+
backgroundSlider: {
|
|
618
|
+
slides: [
|
|
619
|
+
{
|
|
620
|
+
type: 'image',
|
|
621
|
+
src: 'https://picsum.photos/id/1015/1920/1080',
|
|
622
|
+
alt: 'Mountain landscape',
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
type: 'image',
|
|
626
|
+
src: 'https://picsum.photos/id/1018/1920/1080',
|
|
627
|
+
alt: 'Forest scene',
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
type: 'image',
|
|
631
|
+
src: 'https://picsum.photos/id/1025/1920/1080',
|
|
632
|
+
alt: 'Ocean view',
|
|
633
|
+
},
|
|
634
|
+
],
|
|
635
|
+
autoplay: {
|
|
636
|
+
delay: 4000,
|
|
637
|
+
pauseOnHover: false,
|
|
638
|
+
},
|
|
639
|
+
loop: true,
|
|
640
|
+
transition: 'fade',
|
|
641
|
+
transitionDuration: 1500,
|
|
642
|
+
},
|
|
643
|
+
},
|
|
644
|
+
};
|
|
@@ -30,6 +30,7 @@ export const Hero: React.FC<HeroProps> = ({
|
|
|
30
30
|
loop: true,
|
|
31
31
|
muted: true,
|
|
32
32
|
},
|
|
33
|
+
backgroundSlider,
|
|
33
34
|
}) => {
|
|
34
35
|
const {
|
|
35
36
|
generateHeroClassNames,
|
|
@@ -40,6 +41,8 @@ export const Hero: React.FC<HeroProps> = ({
|
|
|
40
41
|
useGridLayout,
|
|
41
42
|
heroRef,
|
|
42
43
|
videoRef,
|
|
44
|
+
backgroundSlider: sliderHook,
|
|
45
|
+
hasBackgroundSlider,
|
|
43
46
|
} = useHero({
|
|
44
47
|
alignment,
|
|
45
48
|
imageColSize,
|
|
@@ -52,6 +55,7 @@ export const Hero: React.FC<HeroProps> = ({
|
|
|
52
55
|
parallax,
|
|
53
56
|
parallaxIntensity,
|
|
54
57
|
videoBackground,
|
|
58
|
+
backgroundSlider,
|
|
55
59
|
});
|
|
56
60
|
|
|
57
61
|
// Create custom style for hero element with content width if provided
|
|
@@ -82,6 +86,81 @@ export const Hero: React.FC<HeroProps> = ({
|
|
|
82
86
|
};
|
|
83
87
|
|
|
84
88
|
const renderBackground = () => {
|
|
89
|
+
// Render background slider if configured
|
|
90
|
+
if (hasBackgroundSlider && backgroundSlider && sliderHook) {
|
|
91
|
+
const { slides, transition = 'fade', transitionDuration = 1000 } = backgroundSlider;
|
|
92
|
+
const { currentIndex, slideRefs, videoRefs } = sliderHook;
|
|
93
|
+
|
|
94
|
+
// Determine transition class
|
|
95
|
+
let transitionClass = HERO.CLASSES.SLIDER_FADE;
|
|
96
|
+
if (transition === 'slide') {
|
|
97
|
+
transitionClass = HERO.CLASSES.SLIDER_SLIDE;
|
|
98
|
+
} else if (transition === 'custom') {
|
|
99
|
+
transitionClass = HERO.CLASSES.SLIDER_CUSTOM;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<div
|
|
104
|
+
className={`${HERO.SELECTORS.SLIDER.replace('.', '')} ${transitionClass}`}
|
|
105
|
+
style={{
|
|
106
|
+
'--slider-transition-duration': `${transitionDuration}ms`,
|
|
107
|
+
} as React.CSSProperties}
|
|
108
|
+
onMouseEnter={() => {
|
|
109
|
+
if (backgroundSlider.autoplay?.pauseOnHover) {
|
|
110
|
+
sliderHook.pauseAutoplay();
|
|
111
|
+
}
|
|
112
|
+
}}
|
|
113
|
+
onMouseLeave={() => {
|
|
114
|
+
if (backgroundSlider.autoplay?.pauseOnHover) {
|
|
115
|
+
sliderHook.resumeAutoplay();
|
|
116
|
+
}
|
|
117
|
+
}}
|
|
118
|
+
>
|
|
119
|
+
{slides.map((slide, index) => {
|
|
120
|
+
const isActive = index === currentIndex;
|
|
121
|
+
const slideRef = slideRefs[index];
|
|
122
|
+
const videoRef = videoRefs[index];
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<div
|
|
126
|
+
key={index}
|
|
127
|
+
ref={slideRef}
|
|
128
|
+
className={`${HERO.SELECTORS.SLIDER_ITEM.replace('.', '')} ${
|
|
129
|
+
isActive ? HERO.CLASSES.SLIDER_ITEM_ACTIVE : ''
|
|
130
|
+
}`}
|
|
131
|
+
>
|
|
132
|
+
{slide.type === 'image' ? (
|
|
133
|
+
<img
|
|
134
|
+
src={slide.src}
|
|
135
|
+
alt={slide.alt || 'Background slide'}
|
|
136
|
+
className={HERO.SELECTORS.BG_IMAGE.replace('.', '')}
|
|
137
|
+
/>
|
|
138
|
+
) : (
|
|
139
|
+
<video
|
|
140
|
+
ref={videoRef as React.LegacyRef<HTMLVideoElement>}
|
|
141
|
+
className="c-hero__video"
|
|
142
|
+
autoPlay={slide.videoOptions?.autoplay !== false}
|
|
143
|
+
loop={slide.videoOptions?.loop !== false}
|
|
144
|
+
muted={slide.videoOptions?.muted !== false}
|
|
145
|
+
playsInline
|
|
146
|
+
poster={slide.videoOptions?.posterUrl}
|
|
147
|
+
>
|
|
148
|
+
<source
|
|
149
|
+
src={slide.src}
|
|
150
|
+
type={`video/${slide.src.split('.').pop() || 'mp4'}`}
|
|
151
|
+
/>
|
|
152
|
+
Your browser does not support the video tag.
|
|
153
|
+
</video>
|
|
154
|
+
)}
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
157
|
+
})}
|
|
158
|
+
{showOverlay && <div className={HERO.SELECTORS.OVERLAY.replace('.', '')}></div>}
|
|
159
|
+
</div>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Fall back to single background image/video
|
|
85
164
|
if (!hasBackgroundImage && !videoBackground) return null;
|
|
86
165
|
|
|
87
166
|
return (
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { StoryFn, Meta } from '@storybook/react';
|
|
3
3
|
import { fn } from '@storybook/test';
|
|
4
|
-
import {
|
|
4
|
+
import { Tabs } from './Tabs';
|
|
5
5
|
|
|
6
6
|
export default {
|
|
7
|
-
title: 'Components/
|
|
8
|
-
component:
|
|
7
|
+
title: 'Components/Tabs',
|
|
8
|
+
component: Tabs,
|
|
9
9
|
argTypes: {
|
|
10
10
|
activeIndex: {
|
|
11
11
|
control: { type: 'number' },
|
|
@@ -16,11 +16,11 @@ export default {
|
|
|
16
16
|
description: 'Enable glass morphism effect',
|
|
17
17
|
},
|
|
18
18
|
},
|
|
19
|
-
} as Meta<typeof
|
|
19
|
+
} as Meta<typeof Tabs>;
|
|
20
20
|
|
|
21
|
-
const Template: StoryFn<typeof
|
|
21
|
+
const Template: StoryFn<typeof Tabs> = args => (
|
|
22
22
|
<div style={{ maxWidth: '600px', margin: '0 auto', padding: '30px' }}>
|
|
23
|
-
<
|
|
23
|
+
<Tabs {...args} />
|
|
24
24
|
</div>
|
|
25
25
|
);
|
|
26
26
|
|
|
@@ -164,7 +164,7 @@ export const Glass = {
|
|
|
164
164
|
}}
|
|
165
165
|
>
|
|
166
166
|
<div style={{ width: '100%', maxWidth: '600px' }}>
|
|
167
|
-
<
|
|
167
|
+
<Tabs {...args} />
|
|
168
168
|
</div>
|
|
169
169
|
</div>
|
|
170
170
|
),
|
|
@@ -211,8 +211,8 @@ export const GlassCustom = {
|
|
|
211
211
|
}}
|
|
212
212
|
>
|
|
213
213
|
<div style={{ width: '100%', maxWidth: '600px' }}>
|
|
214
|
-
<
|
|
214
|
+
<Tabs {...args} />
|
|
215
215
|
</div>
|
|
216
216
|
</div>
|
|
217
217
|
),
|
|
218
|
-
};
|
|
218
|
+
};
|
|
@@ -3,7 +3,7 @@ import { TAB } from '../../lib/constants/components';
|
|
|
3
3
|
import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
|
|
4
4
|
import { AtomixGlassProps } from '../../lib/types/components';
|
|
5
5
|
|
|
6
|
-
export interface
|
|
6
|
+
export interface TabsItemProps {
|
|
7
7
|
/**
|
|
8
8
|
* Label for the tab
|
|
9
9
|
*/
|
|
@@ -25,11 +25,11 @@ export interface TabItemProps {
|
|
|
25
25
|
className?: string;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export interface
|
|
28
|
+
export interface TabsProps {
|
|
29
29
|
/**
|
|
30
30
|
* Array of tab items
|
|
31
31
|
*/
|
|
32
|
-
items:
|
|
32
|
+
items: TabsItemProps[];
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* Initial active tab index
|
|
@@ -59,9 +59,9 @@ export interface TabProps {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
62
|
+
* Tabs component for switching between different content panels
|
|
63
63
|
*/
|
|
64
|
-
export const
|
|
64
|
+
export const Tabs: React.FC<TabsProps> = ({
|
|
65
65
|
items,
|
|
66
66
|
activeIndex = TAB.DEFAULTS.ACTIVE_INDEX,
|
|
67
67
|
onTabChange,
|
|
@@ -139,6 +139,6 @@ export const Tab: React.FC<TabProps> = ({
|
|
|
139
139
|
return tabContent;
|
|
140
140
|
};
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
Tabs.displayName = 'Tabs';
|
|
143
143
|
|
|
144
|
-
export default
|
|
144
|
+
export default Tabs;
|
package/src/components/index.ts
CHANGED
|
@@ -10,6 +10,8 @@ export { default as Breadcrumb, type BreadcrumbProps } from './Breadcrumb/Breadc
|
|
|
10
10
|
export { default as Button, type ButtonProps } from './Button/Button';
|
|
11
11
|
export { default as Callout, type CalloutProps } from './Callout/Callout';
|
|
12
12
|
export { default as Card, type CardProps } from './Card/Card';
|
|
13
|
+
// Card sub-components
|
|
14
|
+
export { default as ElevationCard, type ElevationCardProps } from './Card/ElevationCard';
|
|
13
15
|
export {
|
|
14
16
|
AnimatedChart,
|
|
15
17
|
AreaChart,
|
|
@@ -29,7 +31,6 @@ export {
|
|
|
29
31
|
ScatterChart,
|
|
30
32
|
TreemapChart,
|
|
31
33
|
WaterfallChart,
|
|
32
|
-
type AnimatedChartProps,
|
|
33
34
|
type AreaChartProps,
|
|
34
35
|
type BarChartProps,
|
|
35
36
|
type BubbleChartProps,
|
|
@@ -87,6 +88,9 @@ export { default as Textarea, type TextareaProps } from './Form/Textarea';
|
|
|
87
88
|
export { default as Hero, type HeroProps } from './Hero/Hero';
|
|
88
89
|
export { default as Icon, type IconProps } from './Icon/Icon';
|
|
89
90
|
export { default as List, type ListProps } from './List/List';
|
|
91
|
+
// List sub-components
|
|
92
|
+
export { ListGroup } from './List/ListGroup';
|
|
93
|
+
export type { ListGroupProps } from '../lib/types/components';
|
|
90
94
|
export { default as Messages, type MessagesProps } from './Messages/Messages';
|
|
91
95
|
export { default as Modal, type ModalProps } from './Modal/Modal';
|
|
92
96
|
export { default as Nav, type NavProps } from './Navigation/Nav/Nav';
|
|
@@ -101,6 +105,12 @@ export {
|
|
|
101
105
|
default as SideMenuList,
|
|
102
106
|
type SideMenuListProps,
|
|
103
107
|
} from './Navigation/SideMenu/SideMenuList';
|
|
108
|
+
// Menu components
|
|
109
|
+
export { Menu, MenuItem, MenuDivider, type MenuProps, type MenuItemProps, type MenuDividerProps } from './Navigation/Menu/Menu';
|
|
110
|
+
export { MegaMenu, MegaMenuColumn, MegaMenuLink } from './Navigation/Menu/MegaMenu';
|
|
111
|
+
export type { MegaMenuProps, MegaMenuColumnProps, MegaMenuLinkProps } from '../lib/types/components';
|
|
112
|
+
// Navigation sub-components
|
|
113
|
+
export { NavDropdown, type NavDropdownProps } from './Navigation/Nav/NavDropdown';
|
|
104
114
|
export { default as Pagination, type PaginationProps } from './Pagination/Pagination';
|
|
105
115
|
export { default as PhotoViewer, type PhotoViewerProps } from './PhotoViewer/PhotoViewer';
|
|
106
116
|
export { default as Popover, type PopoverProps } from './Popover/Popover';
|
|
@@ -112,7 +122,7 @@ export { default as SectionIntro, type SectionIntroProps } from './SectionIntro/
|
|
|
112
122
|
export { Slider } from './Slider/Slider';
|
|
113
123
|
export { default as Spinner, type SpinnerProps } from './Spinner/Spinner';
|
|
114
124
|
export { default as Steps, type StepsProps } from './Steps/Steps';
|
|
115
|
-
export { default as
|
|
125
|
+
export { default as Tabs, type TabsProps } from './Tabs/Tabs';
|
|
116
126
|
export { default as Testimonial, type TestimonialProps } from './Testimonial/Testimonial';
|
|
117
127
|
export { default as Todo, type TodoProps } from './Todo/Todo';
|
|
118
128
|
export { default as Toggle, type ToggleProps } from './Toggle/Toggle';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect, useRef } from 'react';
|
|
2
2
|
import { HeroProps, HeroAlignment } from '../types/components';
|
|
3
3
|
import { HERO } from '../constants/components';
|
|
4
|
+
import { useHeroBackgroundSlider, UseHeroBackgroundSliderResult } from './useHeroBackgroundSlider';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Hero hook result interface
|
|
@@ -55,6 +56,16 @@ interface UseHeroResult {
|
|
|
55
56
|
* Remove parallax effect
|
|
56
57
|
*/
|
|
57
58
|
removeParallaxEffect: (element: HTMLElement) => void;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Background slider hook result (if slider is enabled)
|
|
62
|
+
*/
|
|
63
|
+
backgroundSlider?: UseHeroBackgroundSliderResult;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Whether background slider is enabled
|
|
67
|
+
*/
|
|
68
|
+
hasBackgroundSlider: boolean;
|
|
58
69
|
}
|
|
59
70
|
|
|
60
71
|
/**
|
|
@@ -80,10 +91,25 @@ export function useHero(initialProps?: Partial<HeroProps>): UseHeroResult {
|
|
|
80
91
|
...initialProps,
|
|
81
92
|
};
|
|
82
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Check if background slider is enabled
|
|
96
|
+
*/
|
|
97
|
+
const hasBackgroundSlider = !!defaultProps.backgroundSlider;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Initialize background slider hook if enabled
|
|
101
|
+
*/
|
|
102
|
+
const backgroundSlider = hasBackgroundSlider && defaultProps.backgroundSlider
|
|
103
|
+
? useHeroBackgroundSlider(defaultProps.backgroundSlider)
|
|
104
|
+
: undefined;
|
|
105
|
+
|
|
83
106
|
/**
|
|
84
107
|
* Check if the hero has a background image
|
|
108
|
+
* Slider takes precedence over single background image
|
|
85
109
|
*/
|
|
86
|
-
const hasBackgroundImage =
|
|
110
|
+
const hasBackgroundImage = hasBackgroundSlider
|
|
111
|
+
? true
|
|
112
|
+
: !!defaultProps.backgroundImageSrc || !!defaultProps.videoBackground;
|
|
87
113
|
|
|
88
114
|
/**
|
|
89
115
|
* Check if the hero has a foreground image
|
|
@@ -151,11 +177,12 @@ export function useHero(initialProps?: Partial<HeroProps>): UseHeroResult {
|
|
|
151
177
|
}
|
|
152
178
|
};
|
|
153
179
|
|
|
154
|
-
// Apply parallax effect if enabled
|
|
180
|
+
// Apply parallax effect if enabled (disabled when slider is active)
|
|
155
181
|
useEffect(() => {
|
|
156
182
|
const heroElement = heroRef.current;
|
|
157
183
|
|
|
158
|
-
|
|
184
|
+
// Disable parallax when slider is active (conflicts with transitions)
|
|
185
|
+
if (heroElement && defaultProps.parallax && hasBackgroundImage && !hasBackgroundSlider) {
|
|
159
186
|
applyParallaxEffect(heroElement, defaultProps.parallaxIntensity);
|
|
160
187
|
}
|
|
161
188
|
|
|
@@ -164,7 +191,7 @@ export function useHero(initialProps?: Partial<HeroProps>): UseHeroResult {
|
|
|
164
191
|
removeParallaxEffect(heroElement);
|
|
165
192
|
}
|
|
166
193
|
};
|
|
167
|
-
}, [defaultProps.parallax, defaultProps.parallaxIntensity, hasBackgroundImage]);
|
|
194
|
+
}, [defaultProps.parallax, defaultProps.parallaxIntensity, hasBackgroundImage, hasBackgroundSlider]);
|
|
168
195
|
|
|
169
196
|
/**
|
|
170
197
|
* Generate hero class names based on props
|
|
@@ -246,5 +273,7 @@ export function useHero(initialProps?: Partial<HeroProps>): UseHeroResult {
|
|
|
246
273
|
videoRef,
|
|
247
274
|
applyParallaxEffect,
|
|
248
275
|
removeParallaxEffect,
|
|
276
|
+
backgroundSlider,
|
|
277
|
+
hasBackgroundSlider,
|
|
249
278
|
};
|
|
250
279
|
}
|