Skip to content

Commit eb09b6d

Browse files
committed
🔧 Refactor component imports and add language selection feature
1 parent c6a35e8 commit eb09b6d

File tree

7 files changed

+273
-16
lines changed

7 files changed

+273
-16
lines changed

src/components/App.astro

+17-9
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
11
---
2-
import About from '@components/About.astro';
32
import ButtonTop from '@components/buttons/button-top.svelte';
4-
import Contact from '@components/Contact.astro';
53
import Header from '@components/Header.astro';
6-
import Hero from '@components/Hero.astro';
74
import Navigation from '@components/Navigation.svelte';
8-
import Portfolio from '@components/Portfolio.astro';
9-
import Skills from '@components/Skills.astro';
105
import { getI18n } from '@i18n/index';
116
import Layout from '@layouts/Layout.astro';
127
8+
import About from './About.astro';
9+
import Contact from './Contact.astro';
10+
import Hero from './Hero.astro';
11+
import Portfolio from './Portfolio.astro';
12+
import Skills from './Skills.astro';
13+
1314
const { currentLocale } = Astro;
1415
1516
const i18n = getI18n({ currentLocale });
1617
---
1718

18-
<Layout title={i18n.SEO_TITLE} description={i18n.SEO_DESCRIPTION} language={i18n.LANGUAGE}>
19+
<Layout
20+
title={i18n.SEO_TITLE}
21+
description={i18n.SEO_DESCRIPTION}
22+
language={i18n.LANGUAGE}
23+
>
1924
<div class="wrapper">
2025
<Header />
21-
<Navigation client:load/>
26+
<Navigation client:load />
2227
<div class="content">
2328
<div class="blur bottom"></div>
2429
<div class="blur top"></div>
@@ -29,14 +34,17 @@ const i18n = getI18n({ currentLocale });
2934
<Contact />
3035
</div>
3136
</div>
32-
<ButtonTop client:idle/>
37+
<ButtonTop client:idle />
3338
</Layout>
3439

3540
<style>
3641
.wrapper {
3742
opacity: 1;
3843
visibility: visible;
39-
transition: opacity 2.2s ease-in-out, visibility 2.2s ease-in-out, height 2.2s ease-in-out;
44+
transition:
45+
opacity 2.2s ease-in-out,
46+
visibility 2.2s ease-in-out,
47+
height 2.2s ease-in-out;
4048
overflow: hidden;
4149
max-width: 1200px;
4250
min-width: 380px;

src/components/Header.astro

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
import GithubIcon from '@components/icons/github-icon.astro';
33
import LinkedinIcon from '@components/icons/linkedin-icon.astro';
4+
import LanguageSelect from '@components/selects/language.astro';
45
import { GITHUB_URL, LINKEDIN_URL } from '@constants/urls.ts';
56
---
67

@@ -10,12 +11,14 @@ import { GITHUB_URL, LINKEDIN_URL } from '@constants/urls.ts';
1011
</p>
1112
<div class="social-icons">
1213
<a target="_blank" href={GITHUB_URL} class="icon" aria-label="Github">
13-
<GithubIcon height={45} width={45} />
14+
<GithubIcon height={35} width={35} />
1415
</a>
1516
<a target="_blank" href={LINKEDIN_URL} class="icon" aria-label="Linkedin">
16-
<LinkedinIcon height={45} width={45} />
17+
<LinkedinIcon height={35} width={35} />
1718
</a>
19+
<LanguageSelect />
1820
</div>
21+
</header>
1922

2023
<style>
2124
header {
@@ -31,7 +34,7 @@ import { GITHUB_URL, LINKEDIN_URL } from '@constants/urls.ts';
3134
}
3235

3336
header p.logo-header {
34-
font-family: "Yellowtail", cursive;
37+
font-family: 'Yellowtail', cursive;
3538
font-size: 52px;
3639
color: var(--primary-color);
3740
}

src/components/Hero.astro

+11-4
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,27 @@ const i18n = getI18n({ currentLocale });
2626
class="btn"
2727
href="pdf/cv.pdf"
2828
download="cv - marco cruz.pdf"
29-
aria-label={i18n.HERO_SECTION.CV.ARIA_LABEL}>
29+
aria-label={i18n.HERO_SECTION.CV.ARIA_LABEL}
30+
>
3031
{i18n.HERO_SECTION.CV.BTN_TEXT}
3132
</a>
3233
<div class="social">
3334
<a target="_blank" href={GITHUB_URL} class="icon" aria-label="Github">
3435
<GithubIcon height={40} width={40} />
3536
</a>
36-
<a target="_blank" href={LINKEDIN_URL} class="icon" aria-label="Linkedin">
37+
<a
38+
target="_blank"
39+
href={LINKEDIN_URL}
40+
class="icon"
41+
aria-label="Linkedin"
42+
>
3743
<LinkedinIcon height={40} width={40} />
3844
</a>
3945
</div>
4046
</div>
4147
</div>
4248

43-
<img src="/me.webp" alt={i18n.HERO_SECTION.IMAGE.ALT} class="profile">
49+
<img src="/me.webp" alt={i18n.HERO_SECTION.IMAGE.ALT} class="profile" />
4450
</section>
4551

4652
<style>
@@ -87,7 +93,8 @@ const i18n = getI18n({ currentLocale });
8793
color: var(--primary-color);
8894
}
8995

90-
h1.title, h2.title {
96+
h1.title,
97+
h2.title {
9198
font-weight: bold;
9299
font-size: 64px;
93100
cursor: default;
+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
interface Props {
3+
height?: number;
4+
width?: number;
5+
}
6+
7+
const { height = 40, width = 40 }: Props = Astro.props;
8+
---
9+
10+
<svg
11+
xmlns="http://www.w3.org/2000/svg"
12+
viewBox="0 0 512 512"
13+
id="united-states-of-america"
14+
width={width}
15+
height={height}
16+
>
17+
<path fill="#f0f0f0" d="M0 85.331h512v341.337H0z"></path>
18+
<path
19+
fill="#d80027"
20+
d="M0 127.994h512v42.663H0zM0
21+
213.331h512v42.663H0zM0 298.657h512v42.663H0zM0 383.994h512v42.663H0z"
22+
></path>
23+
<path fill="#2e52b2" d="M0 85.331h256v183.797H0z"></path>
24+
<path
25+
fill="#f0f0f0"
26+
d="m99.822 160.624-4.123 12.684H82.363l10.791
27+
7.835-4.123 12.683 10.791-7.835 10.784
28+
7.835-4.122-12.683 10.791-7.835h-13.337zM103.938
29+
219.08l-4.116-12.683-4.123 12.683H82.363l10.791
30+
7.836-4.123 12.683 10.791-7.836 10.784
31+
7.836-4.122-12.683 10.791-7.836zM47.577
32+
219.08l-4.117-12.683-4.123 12.683H26.001l10.791
33+
7.836-4.123 12.683 10.791-7.836 10.785 7.836-4.122-12.683
34+
10.789-7.836zM43.46 160.624l-4.123 12.684H26.001l10.791
35+
7.835-4.123 12.683 10.791-7.835 10.785 7.835-4.122-12.683
36+
10.789-7.835H47.577zM99.822 114.85l-4.123 12.685H82.363l10.791
37+
7.836-4.123 12.683 10.791-7.836 10.784 7.836-4.122-12.683
38+
10.791-7.836h-13.337zM43.46 114.85l-4.123 12.685H26.001l10.791
39+
7.836-4.123 12.683 10.791-7.836 10.785 7.836-4.122-12.683
40+
10.789-7.836H47.577zM156.183 160.624l-4.122 12.684h-13.336l10.79
41+
7.835-4.121 12.683 10.789-7.835 10.786 7.835-4.123-12.683
42+
10.791-7.835h-13.336zM160.301 219.08l-4.118-12.683-4.122
43+
12.683h-13.336l10.79 7.836-4.121 12.683 10.789-7.836
44+
10.786 7.836-4.123-12.683 10.791-7.836zM216.663
45+
219.08l-4.117-12.683-4.123 12.683h-13.335l10.789 7.836-4.122
46+
12.683 10.791-7.836 10.785 7.836-4.123-12.683
47+
10.791-7.836zM212.546 160.624l-4.123 12.684h-13.335l10.789
48+
7.835-4.122 12.683 10.791-7.835 10.785
49+
7.835-4.123-12.683 10.791-7.835h-13.336zM156.183
50+
114.85l-4.122 12.685h-13.336l10.79 7.836-4.121 12.683
51+
10.789-7.836 10.786 7.836-4.123-12.683 10.791-7.836h-13.336zM212.546
52+
114.85l-4.123 12.685h-13.335l10.789 7.836-4.122 12.683 10.791-7.836
53+
10.785 7.836-4.123-12.683 10.791-7.836h-13.336z"
54+
></path>
55+
</svg>
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
interface Props {
3+
height?: number;
4+
width?: number;
5+
}
6+
7+
const { height = 40, width = 40 }: Props = Astro.props;
8+
---
9+
10+
<svg
11+
xmlns="http://www.w3.org/2000/svg"
12+
viewBox="0 0 47.5 47.5"
13+
id="spain"
14+
width={width}
15+
height={height}
16+
>
17+
<defs>
18+
<clipPath id="a">
19+
<path d="M0 38h38V0H0v38Z"></path>
20+
</clipPath>
21+
</defs>
22+
<g clip-path="url(#a)" transform="matrix(1.25 0 0 -1.25 0 47.5)">
23+
<path
24+
fill="#dd2e44"
25+
d="M37 10a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v18a4 4 0 0 0 4 4h28a4 4 0 0 0 4-4V10Z"
26+
></path>
27+
<path fill="#ffcc4d" d="M37 13H1v12h36V13Z"></path>
28+
<path fill="#ea596e" d="M10 20v-3a3 3 0 1 1 6 0v3h-6Z"></path>
29+
<path fill="#f4a2b2" d="M13 18h3v3h-3v-3z"></path>
30+
<path fill="#dd2e44" d="M13 18h-3v3h3v-3z"></path>
31+
<path
32+
fill="#ea596e"
33+
d="M16 22.5c0-.829-1.343-1.5-3-1.5s-3 .671-3 1.5 1.343 1.5 3 1.5 3-.671 3-1.5"
34+
></path>
35+
<path
36+
fill="#ffac33"
37+
d="M16 23.25c0 .414-1.343.75-3 .75s-3-.336-3-.75 1.343-.75 3-.75 3 .336 3 .75"
38+
></path>
39+
<path fill="#99aab5" d="M8 14h1v7H8v-7zm10 0h-1v7h1v-7z"></path>
40+
<path
41+
fill="#66757f"
42+
d="M10 14H7v1h3v-1zm9 0h-3v1h3v-1zM9 21H8v1h1v-1zm9 0h-1v1h1v-1z"></path>
43+
</g>
44+
</svg>

src/components/selects/language.astro

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
import EnglishFlag from '@components/icons/flags/english.astro';
3+
import SpanishFlag from '@components/icons/flags/spanish.astro';
4+
5+
const LANGUAGES_SUPPORTED = [
6+
{
7+
id: 'es',
8+
name: 'Español',
9+
flag: SpanishFlag,
10+
},
11+
{
12+
id: 'en',
13+
name: 'English',
14+
flag: EnglishFlag,
15+
},
16+
];
17+
18+
const path = Astro.url.pathname;
19+
const currentLocale = LANGUAGES_SUPPORTED.find(({ id }) => path.startsWith(`/${id}`))
20+
|| LANGUAGES_SUPPORTED[0];
21+
const LANGUAGES_FILTERED = LANGUAGES_SUPPORTED.filter(
22+
({ id }) => id !== currentLocale.id,
23+
);
24+
---
25+
26+
<div class="custom-select">
27+
<div class="select-selected">
28+
<currentLocale.flag height={30} width={30} />
29+
</div>
30+
<div class="select-items">
31+
{
32+
LANGUAGES_FILTERED.map((lang) => (
33+
<div class="language-option" data-lang-id={lang.id}>
34+
<lang.flag height={20} width={20} />
35+
{lang.name}
36+
</div>
37+
))
38+
}
39+
</div>
40+
</div>
41+
42+
<style>
43+
.custom-select {
44+
position: relative;
45+
display: inline-block;
46+
width: fit-content;
47+
}
48+
49+
.select-selected {
50+
padding: 10px;
51+
cursor: pointer;
52+
display: flex;
53+
align-items: center;
54+
transition: 0.3s ease;
55+
border-radius: 1rem;
56+
gap: 0.5rem;
57+
}
58+
59+
.select-selected:hover {
60+
background-color: var(--bg-color-button-hover);
61+
}
62+
63+
.select-items {
64+
display: none;
65+
position: absolute;
66+
z-index: 1;
67+
width: 100%;
68+
min-width: 10rem;
69+
right: 0;
70+
}
71+
72+
.select-items div {
73+
padding: 10px;
74+
cursor: pointer;
75+
display: flex;
76+
align-items: center;
77+
gap: 0.5rem;
78+
}
79+
80+
.select-items div:nth-child(1) {
81+
border-radius: 1rem 1rem 0 0;
82+
}
83+
84+
.select-items div:last-child {
85+
border-radius: 0 0 1rem 1rem;
86+
}
87+
.select-items div:hover {
88+
background-color: var(--bg-color-button-hover);
89+
}
90+
91+
.select-items:has(div:only-child) div {
92+
border-radius: 1rem;
93+
}
94+
95+
.custom-select.active .select-items {
96+
display: block;
97+
border-radius: 1rem;
98+
border: 1px solid var(--border-color-nav);
99+
margin-top: 5px;
100+
}
101+
</style>
102+
103+
<script>
104+
function changeLanguage(langId: string) {
105+
const currentPath = window.location.pathname;
106+
const hasLangPrefix = /^\/[a-z]{2}(\/|$)/.test(currentPath);
107+
108+
let newPath;
109+
if (hasLangPrefix) {
110+
newPath = currentPath.replace(/^\/[a-z]{2}/, `/${langId}`);
111+
} else {
112+
newPath = `/${langId}${currentPath}`;
113+
}
114+
115+
window.location.pathname = newPath;
116+
}
117+
118+
document.addEventListener('DOMContentLoaded', () => {
119+
const selectSelected = document.querySelector('.select-selected');
120+
const languageOptions = document.querySelectorAll('.language-option');
121+
122+
languageOptions.forEach((option) => {
123+
option.addEventListener('click', () => {
124+
const langId = option.getAttribute('data-lang-id');
125+
langId && changeLanguage(langId);
126+
});
127+
});
128+
129+
if (selectSelected) {
130+
selectSelected.addEventListener('click', () => {
131+
selectSelected.parentElement?.classList.toggle('active');
132+
});
133+
}
134+
});
135+
</script>

src/pages/es/index.astro

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
import App from '@/components/App.astro';
3+
---
4+
5+
<App />

0 commit comments

Comments
 (0)