Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/collaborators/europython_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/collaborators/pyes_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/collaborators/python_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/collaborators/ub_white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/components/Button.astro
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ const variants = {
primary: 'bg-orange-500 text-white hover:bg-orange-600',
secondary: 'bg-amber-400 text-stone-900 hover:bg-amber-500',
outline: 'outline outline-2 outline-offset-[-2px] outline-orange-500 text-orange-500 hover:bg-orange-50',
ghost: 'text-stone-900 dark:text-white hover:bg-gray-100 dark:hover:bg-gray-800',
}
ghost: 'text-stone-900 text-white hover:bg-gray-100 hover:bg-gray-800'
};

// Map sizes based on exact Figma sizes
const sizes = {
Expand Down
27 changes: 0 additions & 27 deletions src/components/Nav.astro

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/home/SectionMain.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
import { texts } from '../../i18n/home'
import { texts } from '@/i18n/home'
import CenteredPanel from '../CenteredPanel.astro'

interface Props {
Expand Down
2 changes: 1 addition & 1 deletion src/components/index.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
import Layout from '../layouts/Layout.astro'
import Layout from '@/layouts/Layout.astro'
import SectionMain from './home/SectionMain.astro'
import SectionSponsors from './home/SectionSponsors.astro'

Expand Down
1 change: 1 addition & 0 deletions src/pages/constants.ts → src/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const SPONSORS_EMAIL = 'sponsors@2026.es.pycon.org'
export const CONTACT_EMAIL = 'contacto@2026.es.pycon.org'
10 changes: 10 additions & 0 deletions src/i18n/components/footer/ca.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const ca = {
copyright: 'Copyright © Python España & PyConES 2026 Org',
links: [{ label: 'Codi de conducta', href: '/ca/code-of-conduct' }],
social: {
title: 'Segueix-nos',
},
collaborators: {
title: 'Col·laboren',
},
} as const
10 changes: 10 additions & 0 deletions src/i18n/components/footer/en.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const en = {
copyright: 'Copyright © Python España & PyConES 2026 Org',
links: [{ label: 'Code of Conduct', href: '/en/code-of-conduct' }],
social: {
title: 'Follow us',
},
collaborators: {
title: 'Collaborators',
},
} as const
10 changes: 10 additions & 0 deletions src/i18n/components/footer/es.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const es = {
copyright: 'Copyright © Python España & PyConES 2026 Org',
links: [{ label: 'Código de conducta', href: '/es/code-of-conduct' }],
social: {
title: 'Síguenos en redes',
},
collaborators: {
title: 'Colaboran',
},
} as const
9 changes: 9 additions & 0 deletions src/i18n/components/footer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { es } from './es'
import { en } from './en'
import { ca } from './ca'

export const footerTexts = {
es,
en,
ca,
} as const
10 changes: 0 additions & 10 deletions src/i18n/sponsors/ca.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,16 +409,6 @@ export const ca = {
},
],
},
socialLinks: {
title: 'Segueix-nos a les xarxes',
items: [
{ icon: '🦋', label: 'Bluesky', url: 'https://bsky.app/profile/es.pycon.org' },
{ icon: '🐙', label: 'GitHub', url: 'https://github.com/python-spain' },
{ icon: '𝕏', label: '', url: 'https://x.com/PyConES' },
{ icon: '💼', label: 'LinkedIn', url: 'https://www.linkedin.com/company/pycones' },
{ icon: '📸', label: 'Instagram', url: 'https://www.instagram.com/pycon_es' },
],
},
contact: {
title: 'T’hi apuntes?',
body: 'T’ho posem fàcil. Escriu-nos explicant-nos quin nivell de patrocini t’interessa o quin pressupost teniu al cap. Nosaltres et guiarem en el procés, resoldrem els teus dubtes i veurem com encaixar la teva marca de la millor forma possible.',
Expand Down
11 changes: 1 addition & 10 deletions src/i18n/sponsors/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,16 +409,7 @@ export const en = {
},
],
},
socialLinks: {
title: 'Follow us',
items: [
{ icon: '🦋', label: 'Bluesky', url: 'https://bsky.app/profile/es.pycon.org' },
{ icon: '🐙', label: 'GitHub', url: 'https://github.com/python-spain' },
{ icon: '𝕏', label: '', url: 'https://x.com/PyConES' },
{ icon: '💼', label: 'LinkedIn', url: 'https://www.linkedin.com/company/pycones' },
{ icon: '📸', label: 'Instagram', url: 'https://www.instagram.com/pycon_es' },
],
},

contact: {
title: 'Interested?',
body: 'We make it easy. Write to us mentioning which sponsorship level interests you or what budget you have in mind. We will guide you through the process and help your brand fit in the best possible way.',
Expand Down
22 changes: 12 additions & 10 deletions src/i18n/sponsors/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ export const es = {
sunday: 'Domingo',
sundayBody: 'Más charlas, "charlas relámpago" y la despedida final.',
},
socialLinks: {
title: 'Síguenos en redes',
items: [
{ icon: '🦋', label: 'Bluesky', url: 'https://bsky.app/profile/es.pycon.org' },
{ icon: '🐙', label: 'GitHub', url: 'https://github.com/python-spain' },
{ icon: '🐘', label: 'Mastodon', url: 'https://fosstodon.org/@pycones' },
{ icon: '𝕏', label: '', url: 'https://x.com/PyConES' },
{ icon: '💼', label: 'LinkedIn', url: 'https://www.linkedin.com/company/pycones' },
{ icon: '📸', label: 'Instagram', url: 'https://www.instagram.com/pycon_es' },
],
},
stats: {
title: 'La PyConES en números',
items: [
Expand Down Expand Up @@ -409,16 +420,7 @@ export const es = {
},
],
},
socialLinks: {
title: 'Síguenos en redes',
items: [
{ icon: '🦋', label: 'Bluesky', url: 'https://bsky.app/profile/es.pycon.org' },
{ icon: '🐙', label: 'GitHub', url: 'https://github.com/python-spain' },
{ icon: '𝕏', label: '', url: 'https://x.com/PyConES' },
{ icon: '💼', label: 'LinkedIn', url: 'https://www.linkedin.com/company/pycones' },
{ icon: '📸', label: 'Instagram', url: 'https://www.instagram.com/pycon_es' },
],
},

contact: {
title: '¿Te apuntas?',
body: 'Te lo ponemos fácil. Escríbenos contándonos qué nivel de patrocinio te interesa o qué presupuesto tenéis en mente. Nosotros te guiaremos en el proceso, resolveremos tus dudas y veremos cómo encajar tu marca de la mejor forma posible.',
Expand Down
33 changes: 26 additions & 7 deletions src/layouts/Layout.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
import Nav from '../components/Nav.astro'
import '../style/global.css'
import Header from './components/Header/Header.astro'
import Footer from './components/Footer.astro'
import '@/style/global.css'
import '@fontsource-variable/jetbrains-mono'
import '@fontsource-variable/outfit'
import { ClientRouter } from 'astro:transitions'
Expand Down Expand Up @@ -114,22 +115,40 @@ const alternates = [
<ClientRouter />

<script is:inline>
document.documentElement.classList.add('dark')
const getThemePreference = () => {
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme')
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
const isDark = getThemePreference() === 'dark'
document.documentElement.classList[isDark ? 'add' : 'remove']('dark')
document.documentElement.classList[!isDark ? 'add' : 'remove']('light')

if (typeof localStorage !== 'undefined') {
const observer = new MutationObserver(() => {
const isDark = document.documentElement.classList.contains('dark')
localStorage.setItem('theme', isDark ? 'dark' : 'light')
})
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })
}
</script>
</head>

<body
class="bg-pycon-black font-outfit text-pycon-white antialiased h-screen relative transition-colors duration-300"
class="bg-pycon-black font-outfit text-pycon-white antialiased min-h-screen relative flex flex-col transition-colors duration-300"
>
<div
class="fixed inset-0 bg-[url('/images/symbol-black-dark.svg')] bg-size-[80vh] bg-position-[140%_120%] bg-no-repeat opacity-5 pointer-events-none blur transition-colors duration-300"
class="fixed inset-0 bg-no-repeat bg-size-[80vh] bg-position-[140%_120%] opacity-5 pointer-events-none blur transition-all duration-300"
style="background-image: var(--bg-symbol);"
>
</div>
<Nav lang={lang as string} />
<Header lang={lang as string} />

<main class="relative z-10 flex flex-col justify-center container mx-auto p-4 md:p-8">
<main class="relative grow z-10 flex flex-col justify-center container mx-auto p-4 md:p-8 pt-20">
<slot />
</main>
<Footer lang={lang as string} />
</body>
</html>

Expand Down
136 changes: 136 additions & 0 deletions src/layouts/components/Footer.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
import { getRelativeLocaleUrl } from 'astro:i18n'
import { footerTexts } from '@/i18n/components/footer'

interface Props {
lang?: string
}

const { lang: propLang } = Astro.props

// Get current language from URL if prop not provided
const urlLang = Astro.url.pathname.split('/')[1] || 'es'
const rawLang = propLang || urlLang
const validLangs = ['es', 'en', 'ca'] as const
type Lang = (typeof validLangs)[number]
const currentLang: Lang = validLangs.includes(rawLang as Lang) ? (rawLang as Lang) : 'es'

const t = footerTexts[currentLang]

const socialLinks = [
{ icon: '🦋', label: 'Bluesky', url: 'https://bsky.app/profile/es.pycon.org' },
{ icon: '🐙', label: 'GitHub', url: 'https://github.com/python-spain' },
{ icon: '𝕏', label: 'X (Twitter)', url: 'https://x.com/PyConES' },
{ icon: '💼', label: 'LinkedIn', url: 'https://www.linkedin.com/company/pycones' },
{ icon: '📸', label: 'Instagram', url: 'https://www.instagram.com/pycon_es' },
]

const collaborators = [
{
name: 'Python España',
logo: '/collaborators/pyes_logo.png',
url: 'https://es.python.org/',
},
// {
// name: 'Python Software Foundation',
// logo: '/collaborators/psf.png',
// url: 'https://www.python.org/psf/',
// },
{
name: 'EuroPython Society',
logo: '/collaborators/europython_logo.png',
url: 'https://www.europython-society.org/',
},
{
name: 'Universitat de Barcelona',
logo: '/collaborators/ub.png',
url: 'https://www.ub.edu/',
},
]
---

<footer
class="w-full bg-gray-50 bg-pycon-black py-8 border-t border-pycon-gray-100/10 border-pycon-gray-100/20 text-pycon-black text-pycon-white transition-colors duration-300"
>
<div class="container mx-auto px-4">
<!-- Top Row: Brand, Nav, and Social -->
<div class="flex flex-col lg:flex-row justify-between items-center gap-8 pb-8">
<!-- Brand & Copyright -->
<div class="flex flex-col items-center lg:items-start gap-2">
<a
href={getRelativeLocaleUrl(currentLang, '/')}
class="text-2xl font-bold font-outfit tracking-tighter text-pycon-black text-pycon-white hover:text-pycon-yellow transition-colors outline-none focus-visible:text-pycon-yellow"
>
PyCon<span class="text-pycon-yellow">ES</span>
</a>
<p class="text-[10px] font-mono text-pycon-black/50 text-pycon-black-50 uppercase tracking-widest text-center lg:text-left">
{t.copyright}
</p>
</div>

<!-- Navigation & Policies -->
<nav class="flex flex-wrap justify-center items-center gap-x-8 gap-y-2 text-sm font-medium">
{
t.links.map((link) => (
<a
href={link.href}
class="text-pycon-black/80 text-pycon-white/80 hover:text-pycon-red hover:text-pycon-red transition-colors relative group outline-none focus-visible:text-pycon-red"
>
{link.label}
<span class="absolute -bottom-1 left-0 w-0 h-0.5 bg-pycon-red transition-all group-hover:w-full group-focus-visible:w-full" />
</a>
))
}
</nav>

<!-- Social Links -->
<div class="flex flex-col items-center lg:items-end gap-2 text-pycon-black/50 text-pycon-black-50 uppercase tracking-[0.2em] font-bold">
<span class="text-[9px]">
{t.social.title}
</span>
<div class="flex gap-2">
{
socialLinks.map((link) => (
<a
href={link.url}
target="_blank"
rel="noopener noreferrer"
class="group flex h-9 w-9 items-center justify-center rounded-lg bg-pycon-gray-100/10 bg-pycon-gray-100/20 border border-pycon-gray-100/10 text-pycon-black text-pycon-white transition-all hover:bg-pycon-yellow hover:text-pycon-black hover:scale-110 outline-none focus-visible:bg-pycon-yellow focus-visible:text-pycon-black"
aria-label={link.label}
title={link.label}
>
<span class="text-lg">{link.icon}</span>
</a>
))
}
</div>
</div>
</div>

<!-- Bottom Row: Collaborators -->
<div class="pt-6 border-t border-pycon-gray-100/10 flex flex-col md:flex-row items-center justify-center gap-6 text-pycon-black/50 text-pycon-black-50 uppercase tracking-[0.2em] font-bold">
<span class="text-[9px] shrink-0">
{t.collaborators.title}
</span>
<div class="flex flex-wrap justify-center items-center gap-x-10 gap-y-4">
{
collaborators.map((collab) => (
<a
href={collab.url}
target="_blank"
rel="noopener noreferrer"
class="group transition-all hover:scale-105 outline-none focus-visible:ring-1 focus-visible:ring-pycon-orange rounded-md p-1"
title={collab.name}
>
<img
src={collab.logo}
alt={collab.name}
class="h-7 md:h-8 w-auto filter grayscale opacity-80 group-hover:grayscale-0 group-hover:opacity-100 transition-all duration-300"
/>
</a>
))
}
</div>
</div>
</div>
</footer>
13 changes: 13 additions & 0 deletions src/layouts/components/Header/Header.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
import Navigation from './components/Navigation.astro'

interface Props {
lang?: string
}

const { lang } = Astro.props
---

<header class="w-full z-50">
<Navigation lang={lang} />
</header>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
import { i18n } from 'astro:config/client'
import { texts } from '../i18n/components/LanguagePicker'
import { texts } from '@/i18n/components/LanguagePicker'

// Idiomas disponibles
const languages = i18n.locales as string[]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
---
import ResponsiveToggle from './ResponsiveToggle.astro'
import LanguagePicker from './LanguagePicker.astro'
import { getRelativeLocaleUrl } from 'astro:i18n'
import { menuTexts } from '../i18n/menu'
import { getRelativeLocaleUrl } from 'astro:i18n'
import { menuTexts } from '@/i18n/menu'

interface MenuItem {
label: string
href: string
Expand Down
Loading
Loading