athlefi-ui 0.1.7 → 0.1.9

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.
@@ -0,0 +1,215 @@
1
+ ---
2
+ /**
3
+ * Copyright (c) 2025 Grupo DedSec S.A. de C.V.
4
+ * Este código fuente es propiedad exclusiva de Grupo DedSec S.A. de C.V.
5
+ * Se prohíbe su uso, reproducción, distribución o modificación, total o parcial, sin autorización expresa por escrito.
6
+ * No se permite el uso comercial ni la redistribución pública del mismo.
7
+ * Para licenciamiento, contactar a: admin@dedsec.com.mx
8
+ */
9
+
10
+ /**
11
+ * Átomo: TimelineStep
12
+ * @description Paso individual de una línea de tiempo con ícono, título y descripción
13
+ */
14
+
15
+ import shieldIcon from '../../icons/shield-checkmark-outline.svg?raw';
16
+ import searchIcon from '../../icons/search-outline.svg?raw';
17
+ import cardIcon from '../../icons/card-outline.svg?raw';
18
+ import chartIcon from '../../icons/bar-chart-outline.svg?raw';
19
+ import trophyIcon from '../../icons/trophy-outline.svg?raw';
20
+ import userIcon from '../../icons/person-outline.svg?raw';
21
+ import documentIcon from '../../icons/document-text-outline.svg?raw';
22
+ import laptopIcon from '../../icons/laptop-outline.svg?raw';
23
+ import cashIcon from '../../icons/cash-outline.svg?raw';
24
+ import pieIcon from '../../icons/pie-chart-outline.svg?raw';
25
+
26
+ export interface Props {
27
+ icon: string;
28
+ title: string;
29
+ description: string;
30
+ stepNumber: number;
31
+ isVertical?: boolean;
32
+ animationDelay?: number;
33
+ class?: string;
34
+ }
35
+
36
+ const {
37
+ icon,
38
+ title,
39
+ description,
40
+ stepNumber,
41
+ isVertical = false,
42
+ animationDelay = 0,
43
+ class: className = ""
44
+ } = Astro.props;
45
+
46
+ // Mapeo de iconos disponibles
47
+ const iconMap: Record<string, string> = {
48
+ shield: shieldIcon,
49
+ search: searchIcon,
50
+ card: cardIcon,
51
+ chart: chartIcon,
52
+ trophy: trophyIcon,
53
+ user: userIcon,
54
+ 'document-text': documentIcon,
55
+ laptop: laptopIcon,
56
+ cash: cashIcon,
57
+ pie: pieIcon
58
+ };
59
+
60
+ const iconSvg = iconMap[icon] || iconMap.shield;
61
+ const iconSize = isVertical ? '20' : '24';
62
+ ---
63
+
64
+ <div class={`timeline-step ${isVertical ? 'timeline-step--vertical' : 'timeline-step--horizontal'} ${className}`}>
65
+ <div class="timeline-step__icon-container">
66
+ <!-- Ícono principal -->
67
+ <div class="timeline-step__icon">
68
+ <Fragment set:html={iconSvg.replace('<svg', `<svg width="${iconSize}" height="${iconSize}" class="timeline-step__svg"`)} />
69
+ </div>
70
+
71
+ <!-- Efecto pulse animado -->
72
+ <div
73
+ class="timeline-step__pulse"
74
+ style={`animation-delay: ${animationDelay}s;`}
75
+ ></div>
76
+
77
+ <!-- Conector vertical (solo para timeline vertical) -->
78
+ {isVertical && stepNumber < 5 && (
79
+ <div class="timeline-step__connector"></div>
80
+ )}
81
+ </div>
82
+
83
+ <!-- Contenido del paso -->
84
+ <div class={`timeline-step__content ${isVertical ? 'timeline-step__content--vertical' : 'timeline-step__content--horizontal'}`}>
85
+ <h3 class={`timeline-step__title ${isVertical ? '' : 'timeline-step__title--horizontal'}`}>
86
+ {stepNumber}. {title}
87
+ </h3>
88
+ <p class={`timeline-step__description ${!isVertical ? 'timeline-step__description--horizontal' : ''}`}>
89
+ {description}
90
+ </p>
91
+ </div>
92
+ </div>
93
+
94
+ <style>
95
+ /* Base styles */
96
+ .timeline-step {
97
+ position: relative;
98
+ }
99
+
100
+ /* Horizontal layout */
101
+ .timeline-step--horizontal {
102
+ display: flex;
103
+ flex-direction: column;
104
+ align-items: center;
105
+ width: 20%;
106
+ }
107
+
108
+ /* Vertical layout */
109
+ .timeline-step--vertical {
110
+ display: flex;
111
+ align-items: flex-start;
112
+ }
113
+
114
+ /* Icon container */
115
+ .timeline-step__icon-container {
116
+ position: relative;
117
+ }
118
+
119
+ .timeline-step--vertical .timeline-step__icon-container {
120
+ flex-shrink: 0;
121
+ }
122
+
123
+ /* Icon */
124
+ .timeline-step__icon {
125
+ position: relative;
126
+ z-index: 10;
127
+ width: 48px;
128
+ height: 48px;
129
+ background-color: var(--color-primary-60);
130
+ border-radius: 50%;
131
+ display: flex;
132
+ align-items: center;
133
+ justify-content: center;
134
+ margin-bottom: 16px;
135
+ }
136
+
137
+ .timeline-step__icon :global(.timeline-step__svg) {
138
+ color: var(--color-primary-90);
139
+ fill: var(--color-primary-90);
140
+ }
141
+
142
+ /* Pulse effect */
143
+ .timeline-step__pulse {
144
+ position: absolute;
145
+ top: -8px;
146
+ left: -8px;
147
+ width: 64px;
148
+ height: 64px;
149
+ border: 2px solid rgba(1, 234, 199, 0.3);
150
+ border-radius: 50%;
151
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
152
+ }
153
+
154
+ @keyframes pulse {
155
+ 0%, 100% {
156
+ opacity: 0.3;
157
+ transform: scale(1);
158
+ }
159
+ 50% {
160
+ opacity: 0.1;
161
+ transform: scale(1.05);
162
+ }
163
+ }
164
+
165
+ /* Connector for vertical timeline */
166
+ .timeline-step__connector {
167
+ position: absolute;
168
+ top: 48px;
169
+ left: 50%;
170
+ transform: translateX(-50%);
171
+ width: 2px;
172
+ height: 64px;
173
+ background-color: rgba(1, 234, 199, 0.3);
174
+ }
175
+
176
+ /* Content */
177
+ .timeline-step__content--horizontal {
178
+ text-align: center;
179
+ }
180
+
181
+ .timeline-step__content--vertical {
182
+ flex: 1;
183
+ margin-left: 16px;
184
+ }
185
+
186
+ /* Title */
187
+ .timeline-step__title {
188
+ font-family: var(--font-family-manrope);
189
+ font-size: var(--font-size-subtitle-m);
190
+ font-weight: var(--font-weight-subtitle-m);
191
+ line-height: var(--line-height-subtitle-m);
192
+ letter-spacing: var(--letter-spacing-subtitle-m);
193
+ color: var(--color-white);
194
+ }
195
+
196
+ .timeline-step__title--horizontal {
197
+ margin-top: 16px;
198
+ margin-bottom: 8px;
199
+ }
200
+
201
+ /* Description */
202
+ .timeline-step__description {
203
+ font-family: var(--font-family-manrope);
204
+ font-size: var(--font-size-body-s);
205
+ font-weight: var(--font-weight-body-s);
206
+ line-height: var(--line-height-body-s);
207
+ letter-spacing: var(--letter-spacing-body-s);
208
+ color: rgb(209, 213, 219);
209
+ }
210
+
211
+ .timeline-step__description--horizontal {
212
+ max-width: 192px;
213
+ }
214
+ </style>
215
+
@@ -1,41 +1,41 @@
1
1
  ---
2
+ import NavLink from "../atoms/NavLink.astro";
3
+
2
4
  export interface Props {
3
- icon: "phone" | "mail" | "location";
4
- title: string;
5
- text: string;
6
5
  class?: string;
6
+ isMobile?: boolean;
7
7
  }
8
8
 
9
- const { icon, title, text, class: className = "" } = Astro.props;
10
-
11
- // Mapeo de íconos a archivos SVG
12
- const iconMap = {
13
- phone: "/src/assets/phone-portrait-outline.svg",
14
- mail: "/src/assets/mail-outline.svg",
15
- location: "/src/assets/location-outline.svg",
16
- };
9
+ const { class: className = "", isMobile = false } = Astro.props;
17
10
 
18
- const iconSrc = iconMap[icon];
11
+ const navigationItems = [
12
+ { href: "#atleta", label: "Atleta" },
13
+ { href: "/us", label: "Nosotros" },
14
+ { href: "/how-work", label: "Cómo trabajamos" },
15
+ { href: "/contact", label: "Contacto" },
16
+ ];
19
17
  ---
20
18
 
21
- <div class={`flex flex-col items-center text-center ${className}`}>
22
- <!-- Ícono SVG -->
23
- <div class="mb-4 flex h-12 w-12 items-center justify-center">
24
- <img
25
- src={iconSrc}
26
- alt={`${title} icon`}
27
- class="h-12 w-12 text-primary-60 fill-primary-60"
28
- aria-hidden="true"
29
- />
30
- </div>
31
-
32
- <!-- Título -->
33
- <h4 class="h4-style text-primary-60 font-bold mb-2">
34
- {title}
35
- </h4>
19
+ <nav class={`${className}`} aria-label="Navegación principal">
20
+ <ul
21
+ class={`
22
+ ${
23
+ isMobile
24
+ ? "flex flex-col space-y-4 py-4"
25
+ : "hidden lg:flex lg:items-center lg:space-x-8"
26
+ }
27
+ `}
28
+ role="menubar"
29
+ >
30
+ {
31
+ navigationItems.map((item) => (
32
+ <li role="none">
33
+ <NavLink href={item.href} class={isMobile ? "w-full text-left" : ""}>
34
+ {item.label}
35
+ </NavLink>
36
+ </li>
37
+ ))
38
+ }
39
+ </ul>
40
+ </nav>
36
41
 
37
- <!-- Texto descriptivo -->
38
- <p class="body-m-style text-white leading-relaxed">
39
- {text}
40
- </p>
41
- </div>
@@ -0,0 +1,70 @@
1
+ ---
2
+ import FooterLink from "../atoms/FooterLink.astro";
3
+
4
+ export interface Props {
5
+ title: string;
6
+ links: Array<{
7
+ href: string;
8
+ label: string;
9
+ external?: boolean;
10
+ ariaLabel?: string;
11
+ }>;
12
+ class?: string;
13
+ }
14
+
15
+ const { title, links, class: className = "" } = Astro.props;
16
+ ---
17
+
18
+ <div class={`link-group ${className}`}>
19
+ <h3 class="link-group__title">
20
+ {title}
21
+ </h3>
22
+
23
+ <nav aria-label={`${title} navigation`}>
24
+ <ul class="link-group__list" role="list">
25
+ {
26
+ links.map((link) => (
27
+ <li class="link-group__item">
28
+ <FooterLink
29
+ href={link.href}
30
+ external={link.external || false}
31
+ ariaLabel={link.ariaLabel}
32
+ >
33
+ {link.label}
34
+ </FooterLink>
35
+ </li>
36
+ ))
37
+ }
38
+ </ul>
39
+ </nav>
40
+ </div>
41
+
42
+ <style>
43
+ .link-group {
44
+ /* Base styles */
45
+ }
46
+
47
+ .link-group__title {
48
+ font-family: var(--font-family-manrope);
49
+ font-size: var(--font-size-h6);
50
+ font-weight: var(--font-weight-h6);
51
+ line-height: var(--line-height-h6);
52
+ letter-spacing: var(--letter-spacing-h6);
53
+ color: var(--color-white);
54
+ margin-bottom: 16px;
55
+ }
56
+
57
+ .link-group__list {
58
+ list-style: none;
59
+ margin: 0;
60
+ padding: 0;
61
+ display: flex;
62
+ flex-direction: column;
63
+ gap: 12px;
64
+ }
65
+
66
+ .link-group__item {
67
+ /* Item styles */
68
+ }
69
+ </style>
70
+
@@ -0,0 +1,79 @@
1
+ ---
2
+ import NavLink from "../atoms/NavLink.astro";
3
+
4
+ export interface Props {
5
+ class?: string;
6
+ isMobile?: boolean;
7
+ }
8
+
9
+ const { class: className = "", isMobile = false } = Astro.props;
10
+
11
+ const navigationItems = [
12
+ { href: "#atleta", label: "Atleta" },
13
+ { href: "/us", label: "Nosotros" },
14
+ { href: "/how-work", label: "Cómo trabajamos" },
15
+ { href: "/contact", label: "Contacto" },
16
+ ];
17
+ ---
18
+
19
+ <nav class={`nav-menu ${className}`} aria-label="Navegación principal">
20
+ <ul
21
+ class={`nav-menu__list ${isMobile ? 'nav-menu__list--mobile' : 'nav-menu__list--desktop'}`}
22
+ role="menubar"
23
+ >
24
+ {
25
+ navigationItems.map((item) => (
26
+ <li role="none" class="nav-menu__item">
27
+ <NavLink href={item.href} class={isMobile ? "nav-menu__link--mobile" : ""}>
28
+ {item.label}
29
+ </NavLink>
30
+ </li>
31
+ ))
32
+ }
33
+ </ul>
34
+ </nav>
35
+
36
+ <style>
37
+ .nav-menu {
38
+ /* Base styles */
39
+ }
40
+
41
+ .nav-menu__list {
42
+ list-style: none;
43
+ margin: 0;
44
+ padding: 0;
45
+ }
46
+
47
+ /* Desktop menu */
48
+ .nav-menu__list--desktop {
49
+ display: none;
50
+ }
51
+
52
+ @media (min-width: 1024px) {
53
+ .nav-menu__list--desktop {
54
+ display: flex;
55
+ align-items: center;
56
+ gap: 32px;
57
+ }
58
+ }
59
+
60
+ /* Mobile menu */
61
+ .nav-menu__list--mobile {
62
+ display: flex;
63
+ flex-direction: column;
64
+ gap: 16px;
65
+ padding: 16px 0;
66
+ }
67
+
68
+ .nav-menu__item {
69
+ /* Item styles */
70
+ }
71
+
72
+ /* Mobile link full width */
73
+ .nav-menu__list--mobile :global(.nav-menu__link--mobile) {
74
+ display: block;
75
+ width: 100%;
76
+ text-align: left;
77
+ }
78
+ </style>
79
+
@@ -0,0 +1,64 @@
1
+ ---
2
+ import SocialIcon from "../atoms/SocialIcon.astro";
3
+
4
+ export interface Props {
5
+ title: string;
6
+ socialLinks: Array<{
7
+ platform: "youtube" | "facebook" | "twitter" | "instagram";
8
+ href: string;
9
+ }>;
10
+ class?: string;
11
+ }
12
+
13
+ const { title, socialLinks, class: className = "" } = Astro.props;
14
+ ---
15
+
16
+ <div class={`social-group ${className}`}>
17
+ <h3 class="social-group__title">
18
+ {title}
19
+ </h3>
20
+
21
+ <nav aria-label="Redes sociales">
22
+ <ul class="social-group__list" role="list">
23
+ {
24
+ socialLinks.map((social) => (
25
+ <li class="social-group__item">
26
+ <SocialIcon platform={social.platform} href={social.href} />
27
+ </li>
28
+ ))
29
+ }
30
+ </ul>
31
+ </nav>
32
+ </div>
33
+
34
+ <style>
35
+ .social-group {
36
+ /* Base styles */
37
+ }
38
+
39
+ .social-group__title {
40
+ font-family: var(--font-family-manrope);
41
+ font-size: var(--font-size-h6);
42
+ font-weight: var(--font-weight-h6);
43
+ line-height: var(--line-height-h6);
44
+ letter-spacing: var(--letter-spacing-h6);
45
+ color: var(--color-white);
46
+ text-align: center;
47
+ margin-bottom: 16px;
48
+ }
49
+
50
+ .social-group__list {
51
+ list-style: none;
52
+ margin: 0;
53
+ padding: 0;
54
+ display: flex;
55
+ justify-content: center;
56
+ align-items: center;
57
+ gap: 16px;
58
+ }
59
+
60
+ .social-group__item {
61
+ /* Item styles */
62
+ }
63
+ </style>
64
+
@@ -0,0 +1,214 @@
1
+ ---
2
+ import Logo from "../atoms/Logo.astro";
3
+ import LinkGroup from "../molecules/LinkGroup.astro";
4
+ import SocialGroup from "../molecules/SocialGroup.astro";
5
+
6
+ export interface Props {
7
+ class?: string;
8
+ }
9
+
10
+ const { class: className = "" } = Astro.props;
11
+
12
+ // Configuración de enlaces del sitio
13
+ const siteMapLinks = [
14
+ { href: "#atletas", label: "Atletas" },
15
+ { href: "#nosotros", label: "Nosotros" },
16
+ { href: "#como-trabajamos", label: "Cómo trabajamos" },
17
+ { href: "#contacto", label: "Contacto" },
18
+ { href: "#ayuda", label: "Ayuda" },
19
+ { href: "#faq", label: "FAQ" },
20
+ ];
21
+
22
+ // Configuración de enlaces legales
23
+ const legalLinks = [
24
+ { href: "/privacy-policy", label: "Políticas de Privacidad" },
25
+ { href: "/terms-conditions", label: "Términos y Condiciones" },
26
+ { href: "/cookie-policy", label: "Políticas de Cookies" },
27
+ ];
28
+
29
+ // Configuración de redes sociales
30
+ const socialLinks = [
31
+ { platform: "youtube" as const, href: "https://youtube.com/@athlefi" },
32
+ { platform: "facebook" as const, href: "https://facebook.com/athlefi" },
33
+ { platform: "twitter" as const, href: "https://twitter.com/athlefi" },
34
+ { platform: "instagram" as const, href: "https://instagram.com/athlefi" },
35
+ ];
36
+
37
+ const currentYear = new Date().getFullYear();
38
+ ---
39
+
40
+ <footer
41
+ class={`footer ${className}`}
42
+ role="contentinfo"
43
+ aria-label="Información del sitio y enlaces adicionales"
44
+ >
45
+ <div class="footer__container">
46
+ <!-- Secciones principales del footer -->
47
+ <div class="footer__grid">
48
+ <!-- Logo -->
49
+ <div class="footer__logo">
50
+ <div class="footer__logo-wrapper">
51
+ <Logo size="lg" class="footer__logo-image" />
52
+ </div>
53
+ </div>
54
+
55
+ <!-- Separador mobile -->
56
+ <div class="footer__separator footer__separator--mobile"></div>
57
+
58
+ <!-- Mapa del sitio -->
59
+ <div class="footer__sitemap">
60
+ <LinkGroup title="Mapa del sitio" links={siteMapLinks} />
61
+ </div>
62
+
63
+ <!-- Legales -->
64
+ <div class="footer__legal">
65
+ <LinkGroup title="Legales" links={legalLinks} />
66
+ </div>
67
+
68
+ <!-- Redes sociales -->
69
+ <div class="footer__social">
70
+ <SocialGroup title="Síguenos" socialLinks={socialLinks} />
71
+ </div>
72
+ </div>
73
+
74
+ <!-- Separador -->
75
+ <div class="footer__separator"></div>
76
+
77
+ <!-- Sección inferior con copyright -->
78
+ <div class="footer__copyright">
79
+ <div class="footer__copyright-content">
80
+ <p class="footer__copyright-text">
81
+ © {currentYear} Athlefi. Todos los derechos reservados.
82
+ </p>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ </footer>
87
+
88
+ <style>
89
+ .footer {
90
+ background-color: var(--color-primary-90);
91
+ border-top: 1px solid rgb(31, 41, 55);
92
+ }
93
+
94
+ .footer__container {
95
+ max-width: 1280px;
96
+ margin: 0 auto;
97
+ padding: 0 1rem;
98
+ }
99
+
100
+ @media (min-width: 640px) {
101
+ .footer__container {
102
+ padding: 0 1.5rem;
103
+ }
104
+ }
105
+
106
+ @media (min-width: 1024px) {
107
+ .footer__container {
108
+ padding: 0 2rem;
109
+ }
110
+ }
111
+
112
+ /* Grid Layout */
113
+ .footer__grid {
114
+ display: grid;
115
+ grid-template-columns: 1fr;
116
+ gap: 2rem;
117
+ padding: 3rem 0;
118
+ }
119
+
120
+ @media (min-width: 1024px) {
121
+ .footer__grid {
122
+ grid-template-columns: repeat(16, 1fr);
123
+ gap: 1.5rem;
124
+ }
125
+ }
126
+
127
+ /* Logo Section */
128
+ .footer__logo {
129
+ grid-column: 1;
130
+ }
131
+
132
+ @media (min-width: 1024px) {
133
+ .footer__logo {
134
+ grid-column: 1 / span 4;
135
+ }
136
+ }
137
+
138
+ .footer__logo-wrapper {
139
+ display: flex;
140
+ flex-direction: column;
141
+ align-items: flex-start;
142
+ }
143
+
144
+ .footer__logo-image {
145
+ margin-bottom: 1rem;
146
+ }
147
+
148
+ /* Sitemap Section */
149
+ .footer__sitemap {
150
+ grid-column: 1;
151
+ }
152
+
153
+ @media (min-width: 1024px) {
154
+ .footer__sitemap {
155
+ grid-column: 5 / span 4;
156
+ }
157
+ }
158
+
159
+ /* Legal Section */
160
+ .footer__legal {
161
+ grid-column: 1;
162
+ }
163
+
164
+ @media (min-width: 1024px) {
165
+ .footer__legal {
166
+ grid-column: 9 / span 4;
167
+ }
168
+ }
169
+
170
+ /* Social Section */
171
+ .footer__social {
172
+ grid-column: 1;
173
+ }
174
+
175
+ @media (min-width: 1024px) {
176
+ .footer__social {
177
+ grid-column: 13 / span 4;
178
+ }
179
+ }
180
+
181
+ /* Separators */
182
+ .footer__separator {
183
+ border-top: 1px solid var(--color-gray-medium);
184
+ }
185
+
186
+ .footer__separator--mobile {
187
+ display: block;
188
+ }
189
+
190
+ @media (min-width: 1024px) {
191
+ .footer__separator--mobile {
192
+ display: none;
193
+ }
194
+ }
195
+
196
+ /* Copyright Section */
197
+ .footer__copyright {
198
+ padding: 1.5rem 0;
199
+ }
200
+
201
+ .footer__copyright-content {
202
+ text-align: center;
203
+ }
204
+
205
+ .footer__copyright-text {
206
+ font-family: var(--font-family-manrope);
207
+ font-size: var(--font-size-body-s);
208
+ font-weight: var(--font-weight-body-s);
209
+ line-height: var(--line-height-body-s);
210
+ letter-spacing: var(--letter-spacing-body-s);
211
+ color: rgb(156, 163, 175);
212
+ }
213
+ </style>
214
+