✨ feat(app.scss): Ajoute style pour fond semi-transparent avec flou.
✨ feat(base.twig): Ajoute panier latéral et icônes sur l'en-tête.
This commit is contained in:
@@ -1,2 +1,6 @@
|
||||
@import "tailwindcss";
|
||||
@import url('https://fonts.googleapis.com/css2?family=Intel+One+Mono:ital,wght@0,300..700;1,300..700&display=swap');
|
||||
.bg-op {
|
||||
background: rgba(0,0,0,0.5);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
</div>
|
||||
|
||||
{# LIENS DE NAVIGATION (Desktop) #}
|
||||
<div class="hidden md:flex md:space-x-4">
|
||||
<div class="hidden md:flex md:space-x-4 items-center">
|
||||
<div class="hidden md:flex md:space-x-1">
|
||||
{% for link in links %}
|
||||
{% set is_active = (app.request.get('_route') == link.route) %}
|
||||
@@ -126,11 +126,35 @@
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{# BOUTON PANIER (Desktop) #}
|
||||
<button id="openCartDesktop" type="button" class="relative p-2 text-gray-700 hover:text-red-600 rounded-full transition duration-150 ease-in-out">
|
||||
<span class="sr-only">Ouvrir le panier</span>
|
||||
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
{# Compteur Panier - Initialisé à 0 #}
|
||||
<span id="cartCountDesktop" class="absolute top-0 right-0 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-white transform translate-x-1/2 -translate-y-1/2 bg-red-600 rounded-full">
|
||||
0
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{# BOUTON MOBILE (Burger Icon) - Couleur adaptée #}
|
||||
<div class="md:hidden">
|
||||
<button type="button" class="text-red-500 hover:text-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 p-2 rounded-md" aria-controls="mobile-menu" aria-expanded="false">
|
||||
{# BOUTONS MOBILE (Burger Icon et Panier) #}
|
||||
<div class="md:hidden flex items-center space-x-2">
|
||||
{# BOUTON PANIER (Mobile) #}
|
||||
<button id="openCartMobile" type="button" class="relative p-2 text-gray-700 hover:text-red-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 rounded-md">
|
||||
<span class="sr-only">Ouvrir le panier</span>
|
||||
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
{# Compteur Panier - Initialisé à 0 #}
|
||||
<span id="cartCountMobile" class="absolute top-0 right-0 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-white transform translate-x-1/2 -translate-y-1/2 bg-red-600 rounded-full">
|
||||
0
|
||||
</span>
|
||||
</button>
|
||||
|
||||
{# BOUTON MOBILE (Burger Icon) #}
|
||||
<button id="mobileMenuButton" type="button" class="text-red-500 hover:text-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 p-2 rounded-md" aria-controls="mobile-menu" aria-expanded="false">
|
||||
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
@@ -141,13 +165,13 @@
|
||||
</nav>
|
||||
|
||||
{# MENU MOBILE (Contenu caché) #}
|
||||
<div class="md:hidden" id="mobile-menu">
|
||||
<div class="md:hidden hidden" id="mobile-menu">
|
||||
<div class="px-2 pt-2 pb-3 space-y-1 sm:px-3">
|
||||
{% for link in links %}
|
||||
{% set is_active = (app.request.get('_route') == link.route) %}
|
||||
|
||||
<a href="{{ path(link.route) }}"
|
||||
class="{% if is_active %}bg-gray-100 text-red-600{% else %}text-gray-700 hover:bg-gray-100 hover:text-red-600{% endif %} px-3 py-2 rounded-md text-sm font-medium">
|
||||
class="block {% if is_active %}bg-gray-100 text-red-600{% else %}text-gray-700 hover:bg-gray-100 hover:text-red-600{% endif %} px-3 py-2 rounded-md text-base font-medium">
|
||||
{{ link.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
@@ -161,6 +185,64 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{# ========================================================== #}
|
||||
{# PANIER LATÉRAL (OFF-CANVAS CART) #}
|
||||
{# Utilise Tailwind pour les transitions et l'accessibilité #}
|
||||
{# Le panier sera masqué par défaut (translate-x-full) #}
|
||||
<div id="cartSidebar" class="fixed top-0 right-0 w-full md:w-96 h-full bg-white shadow-xl transform translate-x-full transition-transform duration-300 ease-in-out z-50 flex flex-col">
|
||||
|
||||
{# Entête du panier #}
|
||||
<div class="p-4 border-b border-gray-200 flex justify-between items-center">
|
||||
<h2 class="text-xl font-bold text-gray-900">Votre Panier</h2>
|
||||
<button id="closeCartButton" type="button" class="text-gray-400 hover:text-gray-600 p-2 rounded-full transition duration-150 ease-in-out">
|
||||
<span class="sr-only">Fermer le panier</span>
|
||||
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{# Contenu du Panier (Défilement) #}
|
||||
<div id="cartItemsContainer" class="flex-grow overflow-y-auto p-4 space-y-4">
|
||||
{# Espace pour les articles du panier - Contenu mocké pour l'exemple #}
|
||||
<div class="text-center text-gray-500 py-12">
|
||||
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
<p class="mt-1">Votre panier est vide.</p>
|
||||
</div>
|
||||
|
||||
{# Exemple d'article (Commenter ou supprimer en production) #}
|
||||
{#
|
||||
<div class="flex items-center space-x-4 border-b pb-4">
|
||||
<img class="h-16 w-16 object-cover rounded" src="placeholder-image-url.jpg" alt="Produit">
|
||||
<div class="flex-grow">
|
||||
<p class="font-semibold text-gray-800">T-Shirt E-Cosplay</p>
|
||||
<p class="text-sm text-gray-600">1 x 19.99 €</p>
|
||||
</div>
|
||||
<button class="text-red-500 hover:text-red-700 text-sm">Supprimer</button>
|
||||
</div>
|
||||
#}
|
||||
</div>
|
||||
|
||||
{# Pied de page du panier (Total et Paiement) #}
|
||||
<div class="p-4 border-t border-gray-200">
|
||||
<div class="flex justify-between font-bold text-lg mb-4">
|
||||
<span>Sous-total:</span>
|
||||
<span id="cartSubtotal">0.00 €</span>
|
||||
</div>
|
||||
<a href="" class="w-full block text-center bg-red-600 text-white py-3 rounded-md hover:bg-red-700 transition duration-150 ease-in-out font-semibold">
|
||||
Passer à la Caisse
|
||||
</a>
|
||||
<p class="text-xs text-gray-500 text-center mt-2">Les frais de livraison seront calculés à l'étape suivante.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# FONDU NOIR (Backdrop) - S'affiche lorsque le panier est ouvert #}
|
||||
<div id="cartBackdrop" class="fixed inset-0 bg-op z-40 hidden transition-opacity duration-300 ease-in-out" aria-hidden="true"></div>
|
||||
{# ========================================================== #}
|
||||
|
||||
|
||||
<footer class="bg-[#FABF04] text-gray-900 border-t border-red-600">
|
||||
<div class="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
|
||||
|
||||
@@ -235,7 +317,81 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{% block javascripts %}{% endblock %}
|
||||
{% block javascripts %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// --- 1. Gestion du Menu Mobile (Burger) ---
|
||||
const mobileMenuButton = document.getElementById('mobileMenuButton');
|
||||
const mobileMenu = document.getElementById('mobile-menu');
|
||||
|
||||
mobileMenuButton.addEventListener('click', () => {
|
||||
const isExpanded = mobileMenuButton.getAttribute('aria-expanded') === 'true' || false;
|
||||
mobileMenuButton.setAttribute('aria-expanded', !isExpanded);
|
||||
mobileMenu.classList.toggle('hidden');
|
||||
});
|
||||
|
||||
|
||||
// --- 2. Gestion du Panier Latéral (Off-Canvas) ---
|
||||
const cartSidebar = document.getElementById('cartSidebar');
|
||||
const cartBackdrop = document.getElementById('cartBackdrop');
|
||||
const openCartButtons = [
|
||||
document.getElementById('openCartDesktop'),
|
||||
document.getElementById('openCartMobile')
|
||||
].filter(e => e !== null);
|
||||
const closeCartButton = document.getElementById('closeCartButton');
|
||||
|
||||
function openCart() {
|
||||
// Empêche le scroll du body lorsque le panier est ouvert
|
||||
document.body.style.overflow = 'hidden';
|
||||
cartBackdrop.classList.remove('hidden');
|
||||
cartSidebar.classList.remove('translate-x-full');
|
||||
cartSidebar.classList.add('translate-x-0');
|
||||
}
|
||||
|
||||
function closeCart() {
|
||||
// Rétablit le scroll du body
|
||||
document.body.style.overflow = '';
|
||||
cartSidebar.classList.remove('translate-x-0');
|
||||
cartSidebar.classList.add('translate-x-full');
|
||||
// Cache le backdrop après la transition (pour une meilleure expérience)
|
||||
setTimeout(() => {
|
||||
cartBackdrop.classList.add('hidden');
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// Événements pour ouvrir le panier
|
||||
openCartButtons.forEach(button => {
|
||||
button.addEventListener('click', openCart);
|
||||
});
|
||||
|
||||
// Événements pour fermer le panier
|
||||
closeCartButton.addEventListener('click', closeCart);
|
||||
cartBackdrop.addEventListener('click', closeCart); // Fermer en cliquant sur le fond
|
||||
|
||||
// Fermer avec la touche ESC
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Escape' && !cartSidebar.classList.contains('translate-x-full')) {
|
||||
closeCart();
|
||||
}
|
||||
});
|
||||
|
||||
// --- 3. Logique Panier Mock (Affichage du compteur) ---
|
||||
// Cette fonction serait remplacée par la logique réelle de gestion du panier (Firestore/API)
|
||||
function updateCartDisplay(count) {
|
||||
document.getElementById('cartCountDesktop').textContent = count;
|
||||
document.getElementById('cartCountMobile').textContent = count;
|
||||
// Exemple : Afficher un faux article si le panier n'est pas vide (à supprimer en production)
|
||||
const container = document.getElementById('cartItemsContainer');
|
||||
if (count > 0) {
|
||||
// Remplace le contenu par un message de test si besoin, sinon afficherait les vrais articles
|
||||
}
|
||||
}
|
||||
|
||||
// Simuler un panier non-vide au chargement (Mettre 0 pour un panier vide réel)
|
||||
updateCartDisplay(0);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user