feat: implement a contact modal with form submission functionality and minor style adjustments to card tags.
This commit is contained in:
parent
801342a0bd
commit
338efc548e
130
public/style.css
130
public/style.css
@ -787,15 +787,15 @@ hr { border: none; border-top: var(--border); margin: 0; }
|
||||
|
||||
.card-coord-tag {
|
||||
position: absolute;
|
||||
bottom: 6px; left: 8px;
|
||||
bottom: 8px; left: 10px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.45rem;
|
||||
color: rgba(232,168,0,0.6);
|
||||
font-size: 0.58rem;
|
||||
color: rgba(232,168,0,0.9);
|
||||
letter-spacing: 0.05em;
|
||||
z-index: 5;
|
||||
pointer-events: none;
|
||||
background: rgba(0,0,0,0.35);
|
||||
padding: 1px 5px;
|
||||
background: #111;
|
||||
padding: 2px 7px;
|
||||
}
|
||||
|
||||
/* Construction line under collection header */
|
||||
@ -861,6 +861,126 @@ hr { border: none; border-top: var(--border); margin: 0; }
|
||||
100% { height: 10px; }
|
||||
}
|
||||
|
||||
/* ---- CONTACT MODAL ---- */
|
||||
.contact-modal {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1001;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
.contact-modal.is-open {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.contact-modal-backdrop {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0,0,0,0.6);
|
||||
}
|
||||
.contact-modal-content {
|
||||
position: relative;
|
||||
background: var(--clr-bg);
|
||||
border: 2px solid var(--clr-black);
|
||||
width: 90%;
|
||||
max-width: 480px;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
padding: 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.2rem;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.contact-modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.contact-modal-close {
|
||||
background: none;
|
||||
border: 1px solid var(--clr-black);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.85rem;
|
||||
width: 32px; height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: none;
|
||||
pointer-events: auto;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
.contact-modal-close:hover {
|
||||
background: var(--clr-black);
|
||||
color: var(--clr-white);
|
||||
}
|
||||
.contact-modal-title {
|
||||
font-size: clamp(1.6rem, 3vw, 2.2rem);
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
.contact-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
.contact-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.3rem;
|
||||
padding: 0.8rem 0;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.12);
|
||||
}
|
||||
.contact-field label {
|
||||
font-size: 0.68rem;
|
||||
font-weight: 700;
|
||||
color: #555;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
.contact-field input,
|
||||
.contact-field textarea {
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.82rem;
|
||||
outline: none;
|
||||
cursor: none;
|
||||
padding: 0;
|
||||
color: var(--clr-black);
|
||||
pointer-events: auto;
|
||||
resize: vertical;
|
||||
}
|
||||
.contact-field input::placeholder,
|
||||
.contact-field textarea::placeholder { color: #aaa; }
|
||||
.contact-submit {
|
||||
margin-top: 1rem;
|
||||
background: var(--clr-black);
|
||||
color: #e8a800;
|
||||
border: none;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
padding: 1.1rem 1.5rem;
|
||||
cursor: none;
|
||||
text-align: center;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.contact-submit:hover {
|
||||
background: #e8a800;
|
||||
color: var(--clr-black);
|
||||
}
|
||||
.contact-note {
|
||||
margin-top: 0.6rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ---- RESPONSIVE ---- */
|
||||
@media (max-width: 900px) {
|
||||
.hero, .newsletter { grid-template-columns: 1fr; }
|
||||
|
||||
@ -166,7 +166,7 @@ const schemaBreadcrumb = {
|
||||
<a href="/" class="logo-text" aria-label="REBOURS — Accueil">REBOURS</a>
|
||||
<nav class="header-nav" aria-label="Navigation principale">
|
||||
<a href="/#collection">COLLECTION_001</a>
|
||||
<a href="/#contact">CONTACT</a>
|
||||
<a href="#" class="contact-trigger">CONTACT</a>
|
||||
<span class="wip-tag"><span class="blink">■</span> W.I.P</span>
|
||||
</nav>
|
||||
</header>
|
||||
@ -255,12 +255,47 @@ const schemaBreadcrumb = {
|
||||
<nav aria-label="Liens secondaires">
|
||||
<a href="https://instagram.com/rebour.studio" rel="noopener" target="_blank">INSTAGRAM</a>
|
||||
/
|
||||
<a href="mailto:contact@rebour.studio">CONTACT</a>
|
||||
<a href="#" class="contact-trigger">CONTACT</a>
|
||||
</nav>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- CONTACT MODAL -->
|
||||
<div id="contact-modal" class="contact-modal" aria-hidden="true">
|
||||
<div class="contact-modal-backdrop"></div>
|
||||
<div class="contact-modal-content">
|
||||
<div class="contact-modal-header">
|
||||
<p class="label">// CONTACT</p>
|
||||
<button class="contact-modal-close" aria-label="Fermer">✕</button>
|
||||
</div>
|
||||
<hr>
|
||||
<h2 class="contact-modal-title">ENVOYER<br>UN MESSAGE</h2>
|
||||
<form id="contact-form" class="contact-form">
|
||||
<div class="contact-field">
|
||||
<label for="contact-name">NOM *</label>
|
||||
<input type="text" id="contact-name" name="name" placeholder="Votre nom" required autocomplete="name">
|
||||
</div>
|
||||
<div class="contact-field">
|
||||
<label for="contact-email">EMAIL *</label>
|
||||
<input type="email" id="contact-email" name="email" placeholder="votre@email.com" required autocomplete="email">
|
||||
</div>
|
||||
<div class="contact-field">
|
||||
<label for="contact-subject">OBJET</label>
|
||||
<input type="text" id="contact-subject" name="subject" placeholder="Objet du message" autocomplete="off">
|
||||
</div>
|
||||
<div class="contact-field">
|
||||
<label for="contact-message">MESSAGE *</label>
|
||||
<textarea id="contact-message" name="message" rows="5" placeholder="Votre message..." required></textarea>
|
||||
</div>
|
||||
<button type="submit" class="contact-submit">
|
||||
ENVOYER LE MESSAGE →
|
||||
</button>
|
||||
<p class="mono-sm contact-note"><span class="blink">■</span> REDIRECTION VERS VOTRE CLIENT MAIL</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cursor-dot"></div>
|
||||
<div class="cursor-outline"></div>
|
||||
</Base>
|
||||
|
||||
@ -130,7 +130,7 @@ const schemaOrg = {
|
||||
<a href="/" class="logo-text" aria-label="REBOURS — Accueil">REBOURS</a>
|
||||
<nav class="header-nav" aria-label="Navigation principale">
|
||||
<a href="#collection">COLLECTION_001</a>
|
||||
<a href="#contact">CONTACT</a>
|
||||
<a href="#" class="contact-trigger">CONTACT</a>
|
||||
<span class="wip-tag"><span class="blink">■</span> W.I.P</span>
|
||||
</nav>
|
||||
</header>
|
||||
@ -222,12 +222,47 @@ const schemaOrg = {
|
||||
<nav aria-label="Liens secondaires">
|
||||
<a href="https://instagram.com/rebour.studio" rel="noopener" target="_blank">INSTAGRAM</a>
|
||||
/
|
||||
<a href="mailto:contact@rebour.studio">CONTACT</a>
|
||||
<a href="#" class="contact-trigger">CONTACT</a>
|
||||
</nav>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- CONTACT MODAL -->
|
||||
<div id="contact-modal" class="contact-modal" aria-hidden="true">
|
||||
<div class="contact-modal-backdrop"></div>
|
||||
<div class="contact-modal-content">
|
||||
<div class="contact-modal-header">
|
||||
<p class="label">// CONTACT</p>
|
||||
<button class="contact-modal-close" aria-label="Fermer">✕</button>
|
||||
</div>
|
||||
<hr>
|
||||
<h2 class="contact-modal-title">ENVOYER<br>UN MESSAGE</h2>
|
||||
<form id="contact-form" class="contact-form">
|
||||
<div class="contact-field">
|
||||
<label for="contact-name">NOM *</label>
|
||||
<input type="text" id="contact-name" name="name" placeholder="Votre nom" required autocomplete="name">
|
||||
</div>
|
||||
<div class="contact-field">
|
||||
<label for="contact-email">EMAIL *</label>
|
||||
<input type="email" id="contact-email" name="email" placeholder="votre@email.com" required autocomplete="email">
|
||||
</div>
|
||||
<div class="contact-field">
|
||||
<label for="contact-subject">OBJET</label>
|
||||
<input type="text" id="contact-subject" name="subject" placeholder="Objet du message" autocomplete="off">
|
||||
</div>
|
||||
<div class="contact-field">
|
||||
<label for="contact-message">MESSAGE *</label>
|
||||
<textarea id="contact-message" name="message" rows="5" placeholder="Votre message..." required></textarea>
|
||||
</div>
|
||||
<button type="submit" class="contact-submit">
|
||||
ENVOYER LE MESSAGE →
|
||||
</button>
|
||||
<p class="mono-sm contact-note"><span class="blink">■</span> REDIRECTION VERS VOTRE CLIENT MAIL</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cursor-dot"></div>
|
||||
<div class="cursor-outline"></div>
|
||||
</Base>
|
||||
|
||||
@ -660,4 +660,66 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// 7. CONTACT MODAL
|
||||
// ==========================================================
|
||||
|
||||
const contactModal = document.getElementById('contact-modal');
|
||||
const contactForm = document.getElementById('contact-form');
|
||||
|
||||
function openContactModal() {
|
||||
if (!contactModal) return;
|
||||
contactModal.classList.add('is-open');
|
||||
contactModal.setAttribute('aria-hidden', 'false');
|
||||
document.body.style.overflow = 'hidden';
|
||||
attachCursorHover(contactModal.querySelectorAll('button, input, textarea'));
|
||||
}
|
||||
|
||||
function closeContactModal() {
|
||||
if (!contactModal) return;
|
||||
contactModal.classList.remove('is-open');
|
||||
contactModal.setAttribute('aria-hidden', 'true');
|
||||
if (!panel.classList.contains('is-open')) {
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger links
|
||||
document.querySelectorAll('.contact-trigger').forEach(link => {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
openContactModal();
|
||||
});
|
||||
});
|
||||
|
||||
// Close button
|
||||
const contactCloseBtn = contactModal?.querySelector('.contact-modal-close');
|
||||
if (contactCloseBtn) contactCloseBtn.addEventListener('click', closeContactModal);
|
||||
|
||||
// Backdrop click
|
||||
const contactBackdrop = contactModal?.querySelector('.contact-modal-backdrop');
|
||||
if (contactBackdrop) contactBackdrop.addEventListener('click', closeContactModal);
|
||||
|
||||
// Escape key
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && contactModal?.classList.contains('is-open')) {
|
||||
closeContactModal();
|
||||
}
|
||||
});
|
||||
|
||||
// Form → mailto
|
||||
if (contactForm) {
|
||||
contactForm.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
const name = document.getElementById('contact-name').value.trim();
|
||||
const email = document.getElementById('contact-email').value.trim();
|
||||
const subject = document.getElementById('contact-subject').value.trim() || 'Contact depuis rebours.studio';
|
||||
const message = document.getElementById('contact-message').value.trim();
|
||||
|
||||
const body = `${message}\n\n— ${name}\n${email}`;
|
||||
const mailto = `mailto:contact@rebours.fr?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
||||
window.location.href = mailto;
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user