Skip to content
Open
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
3 changes: 3 additions & 0 deletions .jules/palette.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2025-05-15 - Accessible Custom Interactive Elements
**Learning:** For custom interactive elements (e.g., `div` as a product item), adding `role="button"` and `tabindex="0"` is only half the battle. To ensure full keyboard operability, explicit listeners for both 'Enter' and 'Space' must be implemented in JavaScript to mirror native button behavior.
**Action:** Always pair `tabindex="0"` on non-interactive elements with a `keydown` handler that triggers the primary action on 'Enter' and 'Space'.
6 changes: 3 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ <h2 style="margin-bottom: 1rem;">Divineo Studio</h2>
<div class="product-selector">
<h3>Catálogo Shopify</h3>
<div class="product-grid">
<div class="product-item selected" onclick="selectProduct('BALMAIN_SS26_SLIM')" style="border-color: #C5A46D;">
<div class="product-item selected" data-product-id="BALMAIN_SS26_SLIM" style="border-color: #C5A46D;" tabindex="0" role="button" aria-label="Select Balmain Slim Jeans">
<div class="product-placeholder">BALMAIN SLIM</div>
<p style="font-size: 0.8rem; text-align: center; color: #C5A46D;">1.290 €</p>
</div>
<div class="product-item" onclick="selectProduct('LEVIS_510_STRETCH')">
<div class="product-item" data-product-id="LEVIS_510_STRETCH" tabindex="0" role="button" aria-label="Select Levis 510 Jeans">
<div class="product-placeholder">LEVIS 510</div>
<p style="font-size: 0.8rem; text-align: center; color: #C5A46D;">110 €</p>
</div>
Expand All @@ -123,7 +123,7 @@ <h3>Catálogo Shopify</h3>
<div class="modal-content" style="background:#141619; border:1px solid #C5A46D; padding:3rem; max-width:500px; text-align:center;">
<h3 style="color:#C5A46D; margin-bottom:1.5rem;">PASE PRIVADO SOLICITADO</h3>
<p style="color:#F5EFE6; opacity:0.7; margin-bottom:2rem;">Contenido restringido para Curadores del Búnker. Por favor, introduce tu credencial de acceso.</p>
<input type="password" id="private-pass-input" placeholder="Credential ID" style="width:100%; padding:1rem; background:#0d0e10; border:1px solid rgba(255,255,255,0.1); color:#F5EFE6; margin-bottom:2rem;">
<input type="password" id="private-pass-input" placeholder="Credential ID" aria-label="Staff Credential ID" style="width:100%; padding:1rem; background:#0d0e10; border:1px solid rgba(255,255,255,0.1); color:#F5EFE6; margin-bottom:2rem;">
<div style="display:flex; gap:1rem; justify-content:center;">
<button class="cta-button" onclick="verifyPrivatePass()" style="padding:10px 20px; font-size:0.8rem;">ACCEDER</button>
<button class="cta-button" onclick="closePrivatePass()" style="padding:10px 20px; font-size:0.8rem; background:transparent; border:1px solid #C5A46D; color:#C5A46D;">CERRAR</button>
Expand Down
11 changes: 9 additions & 2 deletions js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,20 @@ class TryOnYouBunker {

// Product Selection
document.querySelectorAll('.product-item').forEach(item => {
const productId = item.getAttribute('onclick')?.match(/'([^']+)'/)?.[1];
const productId = item.dataset.productId;
if (productId) {
item.addEventListener('click', (e) => {
e.preventDefault();
this.selectGarment(productId, item);
});
item.removeAttribute('onclick');

// Keyboard accessibility for product selection
item.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
item.click();
}
});
Comment on lines +89 to +94
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better code clarity and to avoid dispatching a synthetic event, it's better to call the this.selectGarment() method directly instead of programmatically triggering a click. This makes the code's intent clearer, avoids the overhead of the event system, and removes the dependency on the click event handler.

Suggested change
item.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
item.click();
}
});
item.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
this.selectGarment(productId, item);
}
});

}
});
}
Expand Down
20 changes: 20 additions & 0 deletions styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ body {
color: var(--accent-gold);
}

.nav-menu a:focus-visible {
outline: 2px solid var(--accent-gold);
outline-offset: 4px;
}
Comment on lines +85 to +88
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve maintainability and reduce code duplication, consider grouping all the new :focus-visible styles into a single rule set. The styles for .nav-menu a:focus-visible, .cta-button:focus-visible, .camera-btn:focus-visible, and .product-item:focus-visible are identical.

You could define a single rule like this in a shared/global styles section and remove the other individual declarations:

.nav-menu a:focus-visible,
.cta-button:focus-visible,
.camera-btn:focus-visible,
.product-item:focus-visible {
    outline: 2px solid var(--accent-gold);
    outline-offset: 4px;
}

This makes it easier to update the focus style consistently across the application in the future.


/* Hero Section */
.hero {
height: 100vh;
Expand Down Expand Up @@ -131,6 +136,11 @@ body {
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
}

.cta-button:focus-visible {
outline: 2px solid var(--accent-gold);
outline-offset: 4px;
}

/* Features Section */
.features {
padding: 120px 0;
Expand Down Expand Up @@ -247,6 +257,11 @@ body {
color: var(--bg-dark);
}

.camera-btn:focus-visible {
outline: 2px solid var(--accent-gold);
outline-offset: 4px;
}

.product-selector h3 {
margin-bottom: 2rem;
color: var(--accent-gold);
Expand All @@ -273,6 +288,11 @@ body {
border-color: var(--accent-gold);
}

.product-item:focus-visible {
outline: 2px solid var(--accent-gold);
outline-offset: 4px;
}

.product-placeholder {
height: 180px;
display: flex;
Expand Down