Liveweave: Generative AI Web Editor & HTML/CSS/JS Playground
Initializing
Liveweave
Web
expand_more
home
Home
data_object
CSS Explorer
arrow_outward
Palette
Color Explorer
arrow_outward
Polyline
Graphics Editor
arrow_outward
data_array
Python Editor
New
arrow_outward
build
Tools
expand_more
restart_alt
Load "Hello Weaver!"
post_add
Generate Lorem ipsum...
code
Format HTML
code_blocks
Format CSS
data_object
Format JavaScript
library_add
Library
expand_more
A
Algolia JS
Animate CSS
Apex Charts JS
B
Bulma CSS
Bootstrap
C
Chart JS
Chartist
Create JS
D
D3
Dojo
F
Foundation
Fullpage JS
G
Granim JS
Google Charts
H
Halfmoon
J
jQuery
M
Materialize
Moment JS
Masonry JS
Milligram CSS
P
Pure CSS
Primer CSS
Popper JS
Pattern CSS
Picnic CSS
R
React JS
Raphael JS
Raisin CSS
S
Semantic UI
Skeleton CSS
Spectre CSS
Tachyons CSS
T
Tailwind
Three JS
U
UI Kit
Vis JS
W
Water CSS
download
Download
expand_more
developer_mode
Download as HTML
folder_zip
Download as .ZIP
cloud_upload
Save
account_circle
Login
settings
Settings
expand_more
14
px
Live mode
Night mode
Line number
Mini map
Word wrap
sync_alt
Reset Settings
smart_display
Run
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>BadgeOverlay Add‑on Preview</title> <style> /* ====== XenForo‑like theme variables (hardcoded for demo) ====== */ :root { --xf-contentBg: #ffffff; --xf-contentAltBg: #f5f5f5; --xf-borderColor: #e0e0e0; --xf-borderColorFeature: #b0b0b0; --xf-borderRadiusSmall: 4px; --xf-paddingMedium: 16px; --xf-paddingSmall: 8px; --xf-fontWeightHeavy: 700; --xf-fontSizeSmall: 13px; --xf-fontSizeSmaller: 12px; --xf-textColor: #141414; --xf-textColorMuted: #8c8c8c; --xf-textColorDimmed: #b3b3b3; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background: #f0f2f5; margin: 0; padding: 40px; display: flex; justify-content: center; align-items: center; min-height: 100vh; } .message-cell { max-width: 220px; background: var(--xf-contentBg); border-radius: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); padding: 15px; text-align: center; } .message-avatar { margin-bottom: 10px; } .avatar { display: inline-block; width: 96px; height: 96px; border-radius: 50%; background: #e0e0e0; line-height: 96px; text-align: center; font-size: 2em; color: #666; text-decoration: none; } .message-name { font-size: 1.1em; margin: 0 0 5px; display: flex; align-items: center; justify-content: center; gap: 4px; } .userTitle { color: #888; font-size: 0.85em; margin: 0 0 10px; } /* ====== Featured badges row ====== */ .featuredBadges { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; padding: 5px 0; } .featuredBadge { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; background: #fff; border: 1px solid var(--xf-borderColor); transition: transform 0.15s; text-decoration: none; position: relative; } .featuredBadge:hover { transform: scale(1.1); border-color: var(--xf-borderColorFeature); } .badgeIcon { width: 22px; height: 22px; object-fit: contain; } /* +N badge */ .featuredBadge--overflow { background: var(--xf-contentAltBg); cursor: pointer; } .overflow-text { font-size: 10px; font-weight: var(--xf-fontWeightHeavy); color: var(--xf-textColorDimmed); line-height: 1; } /* Tooltip */ .tooltip-element { display: none; position: absolute; background: rgba(0,0,0,0.85); color: #fff; padding: 4px 8px; border-radius: var(--xf-borderRadiusSmall); font-size: 12px; white-space: nowrap; bottom: 120%; left: 50%; transform: translateX(-50%); pointer-events: none; z-index: 10; } .featuredBadge--overflow:hover .tooltip-element { display: block; } /* Mobile touch target (media query) */ @media (max-width: 480px) { .featuredBadge--overflow { width: 44px; height: 44px; } .overflow-text { font-size: 14px; } } /* ====== Overlay / Modal ====== */ .badge-modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; } .badge-modal-overlay.active { display: flex; } .badge-modal { background: var(--xf-contentBg); border-radius: 8px; max-width: 500px; width: 90%; max-height: 80vh; overflow-y: auto; padding: 20px; position: relative; } .badge-modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .badge-modal-header h3 { margin: 0; font-size: 1.2em; } .badge-modal-close { background: none; border: none; font-size: 1.5em; cursor: pointer; color: #666; } .badge-modal-close:hover { color: #000; } /* Badge grid */ .badge-overlay-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100px, 30vw), 1fr)); gap: var(--xf-paddingMedium); padding: var(--xf-paddingMedium) 0; } .badge-tile { text-align: center; padding: var(--xf-paddingSmall); border: 1px solid var(--xf-borderColor); border-radius: var(--xf-borderRadiusSmall); background: var(--xf-contentBg); } .badge-tile-icon img { width: 36px; height: 36px; object-fit: contain; margin-bottom: 4px; } .badge-tile-name { font-weight: var(--xf-fontWeightHeavy); font-size: var(--xf-fontSizeSmall); color: var(--xf-textColor); line-height: 1.3; } .badge-tile-desc { font-size: var(--xf-fontSizeSmaller); color: var(--xf-textColorMuted); margin-top: 2px; } .badge-tile-noicon { display: inline-block; width: 36px; height: 36px; line-height: 36px; background: var(--xf-contentAltBg); border: 1px dashed var(--xf-borderColor); font-size: 10px; color: var(--xf-textColorDimmed); } /* Mobile typography */ @media (max-width: 480px) { .badge-tile-name { font-size: 14px; } .badge-tile-desc { font-size: 12px; } .badge-tile-noicon { font-size: 12px; } } </style> </head> <body> <!-- Simulated postbit user info --> <div class="message-cell"> <div class="message-avatar"> <a href="#" class="avatar" aria-label="User avatar">B</a> </div> <div class="message-userDetails"> <h4 class="message-name">beenz</h4> <h5 class="userTitle">Well-known member</h5> <div class="featuredBadges featuredBadges--message" id="featuredBadgesContainer"> <!-- Badges 1-4 (visible inline) --> <a href="#" class="featuredBadge featuredBadge--1" title="Bulls Nation"> <img class="badgeIcon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='45' fill='%23CE1141'/%3E%3Ctext x='50' y='65' text-anchor='middle' fill='white' font-size='40'%3E?%3C/text%3E%3C/svg%3E" alt="Bulls Nation"> </a> <a href="#" class="featuredBadge featuredBadge--2" title="Cubs Nation"> <img class="badgeIcon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='45' fill='%230E3386'/%3E%3Ctext x='50' y='65' text-anchor='middle' fill='white' font-size='40'%3E?%3C/text%3E%3C/svg%3E" alt="Cubs Nation"> </a> <a href="#" class="featuredBadge featuredBadge--3" title="Bear Down"> <img class="badgeIcon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='45' fill='%230B162A'/%3E%3Ctext x='50' y='65' text-anchor='middle' fill='white' font-size='40'%3E?%3C/text%3E%3C/svg%3E" alt="Bear Down"> </a> <a href="#" class="featuredBadge featuredBadge--4" title="Day One"> <img class="badgeIcon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='45' fill='%23FDB927'/%3E%3Ctext x='50' y='65' text-anchor='middle' fill='white' font-size='40'%3E1%3C/text%3E%3C/svg%3E" alt="Day One"> </a> <!-- +N badge will be inserted here via JS (simulating template modification) --> </div> </div> </div> <!-- Modal structure --> <div class="badge-modal-overlay" id="badgeModal" role="dialog" aria-modal="true" aria-labelledby="modalTitle"> <div class="badge-modal"> <div class="badge-modal-header"> <h3 id="modalTitle">All Badges (6)</h3> <button class="badge-modal-close" id="modalClose" aria-label="Close modal">×</button> </div> <div class="badge-overlay-grid" id="badgeGrid"> <!-- Filled dynamically --> </div> </div> </div> <script> // All 6 badges data (simulating OzzModz data) const allBadges = [ { id: 1, name: "Bulls Nation", icon: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='45' fill='%23CE1141'/%3E%3Ctext x='50' y='65' text-anchor='middle' fill='white' font-size='40'%3E?%3C/text%3E%3C/svg%3E", desc: "Fan of the Chicago Bulls" }, { id: 2, name: "Cubs Nation", icon: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='45' fill='%230E3386'/%3E%3Ctext x='50' y='65' text-anchor='middle' fill='white' font-size='40'%3E?%3C/text%3E%3C/svg%3E", desc: "This user is a fan of the Chicago Cubs." }, { id: 3, name: "Bear Down", icon: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='45' fill='%230B162A'/%3E%3Ctext x='50' y='65' text-anchor='middle' fill='white' font-size='40'%3E?%3C/text%3E%3C/svg%3E", desc: "Representing the Chicago Bears." }, { id: 4, name: "Day One", icon: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='45' fill='%23FDB927'/%3E%3Ctext x='50' y='65' text-anchor='middle' fill='white' font-size='40'%3E1%3C/text%3E%3C/svg%3E", desc: "Joined on the first day." }, { id: 5, name: "Dapset", icon: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='45' fill='%2356A8E0'/%3E%3Ctext x='50' y='65' text-anchor='middle' fill='white' font-size='40'%3E?%3C/text%3E%3C/svg%3E", desc: "True member of the community." }, { id: 6, name: "Badge Collector Lv1", icon: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='45' fill='%23FFD700'/%3E%3Ctext x='50' y='65' text-anchor='middle' fill='white' font-size='40'%3E⭐%3C/text%3E%3C/svg%3E", desc: "Collected at least 1 badge." } ]; const MAX_VISIBLE = 4; const container = document.getElementById('featuredBadgesContainer'); const overflowCount = allBadges.length - MAX_VISIBLE; if (overflowCount > 0) { // Create +N badge const plusBadge = document.createElement('a'); plusBadge.className = 'featuredBadge featuredBadge--overflow'; plusBadge.href = '#'; plusBadge.setAttribute('role', 'button'); plusBadge.setAttribute('aria-label', `Show all ${allBadges.length} badges`); plusBadge.innerHTML = `<span class="overflow-text">+${overflowCount}</span> <span class="tooltip-element">Show all ${allBadges.length} badges</span>`; plusBadge.addEventListener('click', (e) => { e.preventDefault(); openModal(); }); plusBadge.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); openModal(); } }); container.appendChild(plusBadge); } // Modal logic const modalOverlay = document.getElementById('badgeModal'); const modalClose = document.getElementById('modalClose'); const badgeGrid = document.getElementById('badgeGrid'); function openModal() { badgeGrid.innerHTML = allBadges.map(b => ` <div class="badge-tile"> <div class="badge-tile-icon"> <img src="${b.icon}" alt="${b.name}" loading="lazy" /> </div> <div class="badge-tile-name">${b.name}</div> ${b.desc ? `<div class="badge-tile-desc">${b.desc}</div>` : ''} </div> `).join(''); modalOverlay.classList.add('active'); modalClose.focus(); // Trap focus inside modal document.addEventListener('keydown', trapFocus); } function closeModal() { modalOverlay.classList.remove('active'); document.removeEventListener('keydown', trapFocus); // Return focus to the +N badge const plus = document.querySelector('.featuredBadge--overflow'); if (plus) plus.focus(); } function trapFocus(e) { if (e.key === 'Escape') { closeModal(); return; } // Simple focus trap: keep focus within modal const focusable = modalOverlay.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'); if (focusable.length === 0) return; const first = focusable[0]; const last = focusable[focusable.length - 1]; if (e.key === 'Tab') { if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); } else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); } } } modalClose.addEventListener('click', closeModal); modalOverlay.addEventListener('click', (e) => { if (e.target === modalOverlay) closeModal(); }); </script> </body> </html>
.lw { font-size: 60px; font-family: Arial, Helvetica, sans-serif; }
// Write JavaScript here
Check out the new AI-powered Python Playground
×