mirror of
https://github.com/symfony/ai.git
synced 2026-03-23 23:42:18 +01:00
Overhaul the landing page with a modern, section-based layout: - Hero slider with 3 rotating slides (Agent, Symfony, MCP) and progress bar - Component Architecture section with layered SVG diagram - Features section with 10 tabbed code examples - Third-party integration bridges logo grid - Demos section with setup steps and demo cards - MCP SDK and Symfony Mate sections - Sticky navbar with glassmorphism effect and Bootstrap tooltips - Redesigned "Get Involved & Get Support" CTA section - Full light/dark theme support with CSS variables - Stimulus controllers for hero slider, feature tabs, and clipboard - AOS scroll animations - Subtle gradient backgrounds for secondary sections
76 lines
2.3 KiB
JavaScript
76 lines
2.3 KiB
JavaScript
import './stimulus_bootstrap.js';
|
|
import { Tooltip } from 'bootstrap';
|
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
|
import './styles/app.css';
|
|
import AOS from 'aos';
|
|
import 'aos/dist/aos.css';
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
new App();
|
|
AOS.init({
|
|
duration: 700,
|
|
once: true,
|
|
});
|
|
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => new Tooltip(el));
|
|
});
|
|
|
|
class App {
|
|
constructor() {
|
|
this.#initializeThemeSwitcher();
|
|
}
|
|
|
|
#initializeThemeSwitcher() {
|
|
const themeToggle = document.getElementById('themeToggle');
|
|
const themeIcon = document.getElementById('themeIcon');
|
|
const html = document.documentElement;
|
|
|
|
const icons = {
|
|
auto: document.getElementById('icon-theme-auto').content,
|
|
light: document.getElementById('icon-theme-light').content,
|
|
dark: document.getElementById('icon-theme-dark').content,
|
|
};
|
|
|
|
const getStoredTheme = () => localStorage.getItem('theme') || 'auto';
|
|
const setStoredTheme = (theme) => localStorage.setItem('theme', theme);
|
|
|
|
const setTheme = (theme) => {
|
|
const themeToApply = 'auto' === theme
|
|
? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
|
: theme;
|
|
html.setAttribute('data-bs-theme', themeToApply);
|
|
};
|
|
|
|
const updateIcon = (theme) => {
|
|
themeIcon.replaceChildren(icons[theme].firstElementChild.cloneNode(true));
|
|
};
|
|
|
|
const cycleTheme = () => {
|
|
const currentTheme = getStoredTheme();
|
|
let nextTheme;
|
|
|
|
if ('auto' === currentTheme) {
|
|
nextTheme = 'light';
|
|
} else if ('light' === currentTheme) {
|
|
nextTheme = 'dark';
|
|
} else {
|
|
nextTheme = 'auto';
|
|
}
|
|
|
|
setStoredTheme(nextTheme);
|
|
setTheme(nextTheme);
|
|
updateIcon(nextTheme);
|
|
};
|
|
|
|
const storedTheme = getStoredTheme();
|
|
updateIcon(storedTheme);
|
|
|
|
themeToggle.addEventListener('click', cycleTheme);
|
|
|
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
|
if ('auto' === getStoredTheme()) {
|
|
setTheme('auto');
|
|
}
|
|
});
|
|
}
|
|
}
|