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
16 changes: 10 additions & 6 deletions src/components/LanguagePicker.astro
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const getPathForLang = (targetLang: string) => {
{
variant === 'desktop' ? (
<div
class="lang-picker flex items-center gap-1 border-l border-white/20 pl-6 ml-2 text-pycon-orange-100 text-lg font-outfit"
class="lang-picker flex items-center gap-1 border-l border-pycon-black/20 dark:border-white/20 pl-6 ml-2 text-pycon-orange-100 text-lg font-outfit"
role="group"
aria-label={t['alttext']}
>
Expand All @@ -50,15 +50,19 @@ const getPathForLang = (targetLang: string) => {
'px-2 py-1 text-sm font-outfit rounded transition-colors outline-none',
lang === currentLang
? 'text-pycon-red-100 font-bold underline'
: 'text-pycon-orange-500 hover:text-white focus-visible:text-pycon-red-500',
: 'text-pycon-orange hover:text-pycon-black dark:hover:text-white focus-visible:text-pycon-red-75',
]}
>
{t.label[lang as keyof typeof t.label]}
</a>
))}
</div>
) : (
<div class="lang-picker-mobile border-t border-white/10 pt-4 mt-2" role="group" aria-label={t['alttext']}>
<div
class="lang-picker-mobile border-t border-pycon-black/10 dark:border-white/10 pt-4 mt-2"
role="group"
aria-label={t['alttext']}
>
<span class="text-slate-500 text-sm font-medium mb-2 block">Idioma</span>
<div class="flex gap-2">
{languages.map((lang) => (
Expand All @@ -67,12 +71,12 @@ const getPathForLang = (targetLang: string) => {
hreflang={lang}
lang={lang}
aria-current={lang === currentLang ? 'page' : undefined}
aria-label={`${t['labelariadesc']} ${t.label[lang as keyof typeof t.label]}`}
aria-label={t['labelariadesc'][lang as keyof typeof t.labelariadesc]}
class:list={[
'px-3 py-2 text-sm font-outfit rounded transition-colors outline-none',
lang === currentLang
? 'bg-blue-600 text-white font-bold'
: 'bg-white/5 text-slate-300 hover:bg-white/10 focus-visible:bg-blue-600 focus-visible:text-white',
? 'bg-pycon-orange text-white font-bold'
: 'bg-pycon-black/5 dark:bg-white/5 text-slate-600 dark:text-slate-300 hover:bg-pycon-black/10 dark:hover:bg-white/10 focus-visible:bg-pycon-orange focus-visible:text-white',
]}
>
{t.label[lang as keyof typeof t.label]}
Expand Down
44 changes: 24 additions & 20 deletions src/components/Navigation.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
import ResponsiveToggle from './ResponsiveToggle.astro'
import LanguagePicker from './LanguagePicker.astro'
import ThemeToggle from './ThemeToggle.astro'
import { getRelativeLocaleUrl } from 'astro:i18n'
import { menuTexts } from '../i18n/menu'

Expand Down Expand Up @@ -55,13 +56,13 @@ const { items } = menuTexts[currentLang]

<div
id="main-navigation"
class="fixed top-0 w-full z-50 bg-slate-900/90 backdrop-blur-md border-b border-white/10"
class="fixed top-0 w-full z-50 bg-pycon-white/90 dark:bg-slate-900/90 backdrop-blur-md border-b border-pycon-black/10 dark:border-white/10 transition-colors duration-300"
>
<div class="container mx-auto px-4 h-20 flex items-center justify-between">
<!-- Logo -->
<a
href={getRelativeLocaleUrl(currentLang, '/')}
class="text-2xl font-bold font-outfit tracking-tighter text-white rounded px-2 py-1 outline-none transition-all focus-visible:bg-white/10 focus-visible:text-pycon-orange"
class="text-2xl font-bold font-outfit tracking-tighter text-pycon-black dark:text-white rounded px-2 py-1 outline-none transition-all focus-visible:bg-pycon-black/10 dark:focus-visible:bg-white/10 focus-visible:text-pycon-orange"
>
PyCon<span class="text-pycon-orange">ES</span>
</a>
Expand All @@ -77,7 +78,7 @@ const { items } = menuTexts[currentLang]
<>
<button
id={`dropdown-btn-${index}`}
class="dropdown-trigger flex items-center gap-1 text-white hover:text-pycon-orange font-medium transition-colors rounded outline-none focus-visible:text-pycon-orange focus-visible:underline decoration-2 underline-offset-4"
class="dropdown-trigger flex items-center gap-1 text-pycon-black dark:text-white hover:text-pycon-orange font-medium transition-colors rounded outline-none focus-visible:text-pycon-orange focus-visible:underline decoration-2 underline-offset-4"
aria-expanded="false"
aria-haspopup="true"
aria-controls={`dropdown-menu-${index}`}
Expand All @@ -100,14 +101,14 @@ const { items } = menuTexts[currentLang]
</button>
<ul
id={`dropdown-menu-${index}`}
class="submenu lg:absolute lg:top-full lg:left-0 lg:w-64 bg-slate-800 rounded-lg p-2 mt-2 lg:mt-4 shadow-2xl z-50"
class="submenu lg:absolute lg:top-full lg:left-0 lg:w-64 bg-pycon-white dark:bg-slate-800 rounded-lg p-2 mt-2 lg:mt-4 shadow-2xl z-50 border border-pycon-black/5 dark:border-white/5"
role="menu"
>
{item.children.map((child) => (
<li role="none">
<a
href={getLocalizedUrl(currentLang, child.href)}
class="submenu-item block px-4 py-3 rounded-md text-white font-medium transition-colors outline-none hover:text-pycon-orange hover:bg-white/5 focus-visible:bg-pycon-orange focus-visible:text-white"
class="submenu-item block px-4 py-3 rounded-md text-pycon-black dark:text-white font-medium transition-colors outline-none hover:text-pycon-orange hover:bg-pycon-black/5 dark:hover:bg-white/5 focus-visible:bg-pycon-orange focus-visible:text-white"
role="menuitem"
{...(isExternal(child.href)
? { target: '_blank', rel: 'noopener noreferrer' }
Expand All @@ -122,7 +123,7 @@ const { items } = menuTexts[currentLang]
) : (
<a
href={getLocalizedUrl(currentLang, item.href)}
class="block text-white hover:text-pycon-orange font-medium transition-colors rounded outline-none focus-visible:text-pycon-orange focus-visible:underline decoration-2 underline-offset-4"
class="block text-pycon-black dark:text-white hover:text-pycon-orange font-medium transition-colors rounded outline-none focus-visible:text-pycon-orange focus-visible:underline decoration-2 underline-offset-4"
{...(isExternal(item.href) ? { target: '_blank', rel: 'noopener noreferrer' } : {})}
>
{item.label}
Expand All @@ -131,21 +132,23 @@ const { items } = menuTexts[currentLang]
</li>
))
}

<!-- Language Picker (Desktop) -->
<li class="menu-item">
<LanguagePicker variant="desktop" lang={currentLang} />
</li>
</ul>
</nav>

<!-- Desktop utility controls (outside nav for proper semantics) -->
<div class="hidden lg:flex items-center gap-2">
<LanguagePicker variant="desktop" lang={currentLang} />
<div class="h-6 w-px bg-pycon-black/20 dark:bg-white/20" aria-hidden="true"></div>
<ThemeToggle />
</div>

<!-- Mobile Toggle -->
<ResponsiveToggle />
</div>

<!-- Mobile Navigation -->
<nav
class="mobile-menu absolute top-20 left-0 w-full bg-slate-900 p-4 border-b border-white/10 shadow-xl lg:hidden"
class="mobile-menu absolute top-20 left-0 w-full bg-pycon-white dark:bg-slate-900 p-4 border-b border-pycon-black/10 dark:border-white/10 shadow-xl lg:hidden transition-colors duration-300"
aria-label="Navegación principal móvil"
>
<ul class="menu flex flex-col gap-2">
Expand All @@ -154,7 +157,7 @@ const { items } = menuTexts[currentLang]
<li class="menu-item">
{item.children ? (
<details class="mobile-details">
<summary class="flex items-center justify-between gap-1 w-full text-white hover:text-pycon-orange font-medium py-2 transition-colors rounded outline-none focus-visible:text-pycon-orange focus-visible:underline decoration-2 underline-offset-4 cursor-pointer list-none">
<summary class="flex items-center justify-between gap-1 w-full text-pycon-black dark:text-white hover:text-pycon-orange font-medium py-2 transition-colors rounded outline-none focus-visible:text-pycon-orange focus-visible:underline decoration-2 underline-offset-4 cursor-pointer list-none">
{item.label}
<svg
class="w-4 h-4 transition-transform duration-200 chevron-icon"
Expand All @@ -176,7 +179,7 @@ const { items } = menuTexts[currentLang]
<li>
<a
href={getLocalizedUrl(currentLang, child.href)}
class="block px-4 py-3 rounded-md text-white font-medium transition-colors outline-none hover:text-pycon-orange hover:bg-white/5 focus-visible:bg-pycon-orange focus-visible:text-white"
class="block px-4 py-3 rounded-md text-pycon-black dark:text-white font-medium transition-colors outline-none hover:text-pycon-orange hover:bg-pycon-black/5 dark:hover:bg-white/5 focus-visible:bg-pycon-orange focus-visible:text-white"
{...(isExternal(child.href)
? { target: '_blank', rel: 'noopener noreferrer' }
: {})}
Expand All @@ -190,7 +193,7 @@ const { items } = menuTexts[currentLang]
) : (
<a
href={getLocalizedUrl(currentLang, item.href)}
class="block text-white hover:text-pycon-orange font-medium py-2 transition-colors rounded outline-none focus-visible:text-pycon-orange focus-visible:underline decoration-2 underline-offset-4"
class="block text-pycon-black dark:text-white hover:text-pycon-orange font-medium py-2 transition-colors rounded outline-none focus-visible:text-pycon-orange focus-visible:underline decoration-2 underline-offset-4"
{...(isExternal(item.href) ? { target: '_blank', rel: 'noopener noreferrer' } : {})}
>
{item.label}
Expand All @@ -199,12 +202,13 @@ const { items } = menuTexts[currentLang]
</li>
))
}

<!-- Language Picker (Mobile) -->
<li class="menu-item">
<LanguagePicker variant="mobile" lang={currentLang} />
</li>
</ul>

<!-- Mobile utility controls (outside nav for proper semantics) -->
<div class="flex items-center justify-between py-2 border-t border-pycon-black/10 dark:border-white/10 mt-2">
<LanguagePicker variant="mobile" lang={currentLang} />
<ThemeToggle />
</div>
</nav>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/ResponsiveToggle.astro
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const { class: className } = Astro.props
<button
class:list={[
className,
'responsive-toggle lg:hidden text-white p-2 rounded outline-none transition-colors focus-visible:bg-white/15 focus-visible:text-blue-300',
'responsive-toggle lg:hidden text-pycon-black dark:text-white p-2 rounded outline-none transition-colors focus-visible:bg-pycon-black/15 dark:focus-visible:bg-white/15 focus-visible:text-pycon-orange',
]}
aria-expanded="false"
aria-label="Abrir menú de navegación"
Expand Down
63 changes: 63 additions & 0 deletions src/components/ThemeToggle.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<button
class="theme-toggle-btn cursor-pointer relative p-2 text-pycon-black dark:text-white rounded-md outline-none transition-colors hover:bg-pycon-black/5 dark:hover:bg-white/5 focus-visible:bg-pycon-orange focus-visible:text-white"
role="switch"
aria-checked="false"
aria-label="Modo oscuro"
>
<svg
aria-hidden="true"
class="w-5 h-5 hidden dark:block"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
></path>
</svg>
<svg
aria-hidden="true"
class="w-5 h-5 block dark:hidden"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path>
</svg>
</button>

<script>
document.addEventListener('astro:page-load', () => {
const toggleBtns = document.querySelectorAll('.theme-toggle-btn')

const updateButtonState = (isDark) => {
toggleBtns.forEach((btn) => {
btn.setAttribute('aria-checked', isDark ? 'true' : 'false')
})
}

const handleToggleClick = () => {
const element = document.documentElement
element.classList.toggle('dark')

const isDark = element.classList.contains('dark')
localStorage.setItem('theme', isDark ? 'dark' : 'light')
updateButtonState(isDark)
}

const isDarkInitial = document.documentElement.classList.contains('dark')
updateButtonState(isDarkInitial)

toggleBtns.forEach((btn) => {
btn.removeEventListener('click', handleToggleClick)
btn.addEventListener('click', handleToggleClick)
})
})
</script>
36 changes: 31 additions & 5 deletions src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,36 @@ const { title, description = 'PyconES 2026' } = Astro.props
<title>{title}</title>

<ClientRouter />

<script is:inline>
const theme = (() => {
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme')
}
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark'
}
return 'light'
})()

if (theme === 'dark') {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
</script>
</head>

<body class="bg-pycon-black font-outfit text-pycon-white antialiased h-screen relative">
<body
class="bg-pycon-white dark:bg-pycon-black font-outfit text-pycon-black dark:text-pycon-white antialiased h-screen relative 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-30 pointer-events-none blur-xs"
class="fixed inset-0 bg-[url('/images/symbol-black-light.svg')] dark:bg-[url('/images/symbol-black-dark.svg')] bg-size-[80vh] bg-position-[140%_120%] bg-no-repeat opacity-30 pointer-events-none blur-xs transition-colors duration-300"
>
</div>
<Nav lang={lang as string} />

<main class="relative z-10 flex flex-col justify-center text-white container mx-auto p-4 md:p-8">
<main class="relative z-10 flex flex-col justify-center container mx-auto p-4 md:p-8">
<slot />
</main>
</body>
Expand All @@ -56,12 +76,18 @@ const { title, description = 'PyconES 2026' } = Astro.props
width: 10px;
}
::-webkit-scrollbar-track {
background: #1d1d1b;
background: var(--bg-color);
}
::-webkit-scrollbar-thumb {
background: #555554;
background: #c6c6c6;
border-radius: 5px;
}
.dark ::-webkit-scrollbar-thumb {
background: #555554;
}
.dark ::-webkit-scrollbar-thumb:hover {
background: #8e8e8d;
}
::-webkit-scrollbar-thumb:hover {
background: #8e8e8d;
}
Expand Down
2 changes: 1 addition & 1 deletion src/pages/[lang]/sponsors.astro
Original file line number Diff line number Diff line change
Expand Up @@ -547,4 +547,4 @@ const {
</section>
</div>
</div>
</Layout>
</Layout>
43 changes: 43 additions & 0 deletions src/style/global.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
@import 'tailwindcss';

@custom-variant dark (&:where(.dark, .dark *));

html {
scroll-behavior: smooth;
scroll-padding-top: 6rem; /* Adjust based on your header height */
Expand Down Expand Up @@ -53,9 +55,50 @@ html {
--color-pycon-red-50: #fca09c;
--color-pycon-red-25: #fdcfcd;

--color-pycon-mute: #cc6600;
--color-pycon-mute-100: #cc6600;

--color-pycon-gray: #4a4a48;
--color-pycon-gray-100: #4a4a48;

--color-pycon-black: #1d1d1b;
--color-pycon-black-100: #1d1d1b;
--color-pycon-black-75: #555554;
--color-pycon-black-50: #8e8e8d;
--color-pycon-black-25: #c6c6c6;

--color-pycon-white: #ffffff;

/*DS colors*/
--color-pantone-151c: --color-pycon-orange-100;
--color-pantone-123c: --color-pycon-yellow-100;
--color-pantone-warm-red: --color-pycon-red-100;
--color-pantone-black-c: --color-pycon-black-100;
--color-pantone-yellow-100: --color-pycon-yellow;
--color-pantone-yellow-75: --color-pycon-yellow-75;
--color-pantone-yellow-50: --color-pycon-yellow-50;
--color-pantone-yellow-25: --color-pycon-yellow-25;
--color-pantone-warm-red-100: --color-pycon-red;
--color-pantone-warm-red-75: --color-pycon-red-75;
--color-pantone-warm-red-50: --color-pycon-red-50;
--color-pantone-warm-red-25: --color-pycon-red-25;

--color-tier-main: --color-pycon-yellow;
--color-tier-platinum: --color-pycon-orange;
--color-tier-gold: --color-pycon-red;
--color-tier-silver: --color-pycon-mute;
--color-tier-bronze: --color-pycon-gray;
}

@layer base {
:root {
--bg-color: #ffffff;
--text-color: #1d1d1b;
--bg-symbol: url('/images/symbol-black-dark.svg');
color-scheme: light dark;
}
.dark {
--bg-color: #1d1d1b;
--text-color: #ffffff;
}
}
1 change: 1 addition & 0 deletions tailwind.config.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/** @type {import('tailwindcss').Config} */
export default {
darkMode: 'class',
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
plugins: [],
}