Images: Miniatures avec modal d'agrandissement

Les images dans les notes sont maintenant des miniatures qui s'agrandissent
dans un modal en plein écran au clic.

CSS - Miniatures:
- .note-card-image: 140px hauteur (cartes pliées)
- .note-image: 200px max-height (notes expandues, réduit de 300px)
- Cursor pointer + hover effect (scale 1.02, opacity 0.9)
- Indication visuelle qu'on peut cliquer

Modal Image:
- Fond noir semi-transparent (rgba(0,0,0,0.9))
- Image centrée, max 90vw x 90vh
- Bouton fermeture (top-right, backdrop-filter)
- z-index 400 (au-dessus de tout)
- Animation fadeIn 0.2s

Interactions:
- Clic sur miniature → Modal avec image en taille réelle
- Clic sur fond noir → Ferme le modal
- Bouton X → Ferme le modal
- Touche Escape → Ferme le modal
- Délégation d'événements pour gérer les images après re-render
- Désactive scroll pendant que modal ouvert

JavaScript:
- openImageModal(src): Ouvre modal + désactive scroll
- closeImageModal(): Ferme modal + réactive scroll
- Event listeners: click, escape, backdrop

Bénéfices utilisateur:
✓ Notes plus compactes (images miniatures)
✓ Images consultables en haute qualité (modal)
✓ Navigation intuitive (clic pour agrandir)
✓ Fermeture rapide (X, Escape, backdrop)
✓ Pas de scroll accidentel pendant consultation

Files:
- public/css/components.css: Miniatures + hover effects
- public/css/skeleton.css: Styles modal image
- public/index.html: HTML modal image
- public/js/complete-app.js: Gestion modal + event listeners
This commit is contained in:
Claude committed 2025-11-11 19:41:17 +00:00
1 parent 7354818d3e
commit 6599348878
4 files changed
+151 -1

No files matched your search

+15 -1
View File
@@ -84,6 +84,13 @@
object-fit: cover;
border-radius: var(--radius-md);
margin-bottom: var(--spacing-md);
cursor: pointer;
transition: all var(--transition-fast);
}
.note-card-image:hover {
opacity: 0.9;
transform: scale(1.02);
}
.note-todos-preview {
@@ -840,9 +847,16 @@
.note-image {
width: 100%;
max-height: 300px;
max-height: 200px;
object-fit: cover;
border-radius: var(--radius-lg);
cursor: pointer;
transition: all var(--transition-fast);
}
.note-image:hover {
opacity: 0.9;
transform: scale(1.02);
}
.btn-remove-image {
+65
View File
@@ -293,3 +293,68 @@
transform: translateX(400px);
}
}
/* Modal pour agrandir les images */
.image-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.9);
z-index: 400;
display: none;
align-items: center;
justify-content: center;
padding: 40px;
cursor: pointer;
animation: fadeIn 0.2s ease-in;
}
.image-modal.active {
display: flex;
}
.image-modal-content {
position: relative;
max-width: 90vw;
max-height: 90vh;
cursor: default;
}
.image-modal-img {
max-width: 100%;
max-height: 90vh;
object-fit: contain;
border-radius: var(--radius-md);
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}
.image-modal-close {
position: fixed;
top: 20px;
right: 20px;
width: 48px;
height: 48px;
border: none;
background: rgba(255, 255, 255, 0.1);
color: white;
font-size: 32px;
cursor: pointer;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: all var(--transition-fast);
backdrop-filter: blur(10px);
}
.image-modal-close:hover {
background: rgba(255, 255, 255, 0.2);
transform: scale(1.1);
}
.image-modal-close svg {
width: 24px;
height: 24px;
}
+13
View File
@@ -305,6 +305,19 @@
<!-- Conteneur de notifications -->
<div class="notifications-container" id="notificationsContainer"></div>
<!-- Modal pour agrandir les images -->
<div class="image-modal" id="imageModal">
<div class="image-modal-content">
<img src="" alt="" class="image-modal-img" id="imageModalImg">
</div>
<button class="image-modal-close" id="imageModalClose">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<!-- JavaScript -->
<script src="/js/complete-app.js"></script>
</body>
+58
View File
@@ -534,6 +534,27 @@ function closeNotification(notification) {
}, 300);
}
// ==================== MODAL IMAGE ====================
function openImageModal(imageSrc) {
const modal = document.getElementById('imageModal');
const img = document.getElementById('imageModalImg');
if (modal && img) {
img.src = imageSrc;
modal.classList.add('active');
document.body.style.overflow = 'hidden'; // Désactiver le scroll
}
}
function closeImageModal() {
const modal = document.getElementById('imageModal');
if (modal) {
modal.classList.remove('active');
document.body.style.overflow = ''; // Réactiver le scroll
}
}
// ==================== INLINE NOTE EXPANSION ====================
function expandNote(noteId) {
state.expandedNoteId = noteId;
@@ -2263,6 +2284,43 @@ async function init() {
if (saveOpenRouterBtn) {
saveOpenRouterBtn.addEventListener('click', saveOpenRouterSettings);
}
// ==================== MODAL IMAGE ====================
// Fermer le modal avec le bouton X
const imageModalClose = document.getElementById('imageModalClose');
if (imageModalClose) {
imageModalClose.addEventListener('click', closeImageModal);
}
// Fermer le modal en cliquant sur le fond
const imageModal = document.getElementById('imageModal');
if (imageModal) {
imageModal.addEventListener('click', (e) => {
if (e.target === imageModal) {
closeImageModal();
}
});
}
// Fermer le modal avec la touche Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeImageModal();
}
});
// Délégation d'événements pour les clics sur les images
// Cela permettra de gérer les images même après un re-render
document.addEventListener('click', (e) => {
const target = e.target;
// Si on clique sur une image de note (miniature)
if (target.classList.contains('note-card-image') || target.classList.contains('note-image')) {
e.preventDefault();
e.stopPropagation();
openImageModal(target.src);
}
});
}
// Démarrer l'application