Siteβ―Builder
Editing:
social-links.html
writable 0666
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Add your social links</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <style> :root{ --brand:#0066ff;--bg:#f9fbff;--fg:#111;--err:#d91c31; font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif } *{box-sizing:border-box} body{margin:0;display:flex;min-height:100vh;align-items:center;justify-content:center;background:var(--bg);color:var(--fg)} .card{width:clamp(320px,92vw,440px);background:#fff;padding:2.3rem;border-radius:14px; box-shadow:0 6px 24px rgba(0,0,0,.07)} h1{margin-top:0;text-align:center;font-size:1.8rem;color:var(--brand)} select,button{width:100%;padding:.65rem .8rem;font:inherit;border:1px solid #ccd2e2; border-radius:8px;margin:.8rem 0} button{background:var(--brand);color:#fff;border:none;font-weight:600;cursor:pointer} button:hover{filter:brightness(1.07)} .tags{display:flex;flex-wrap:wrap;gap:.6rem;margin-top:1.1rem} .tag{display:inline-flex;align-items:center;gap:.45rem;background:#edf1ff;padding:.4rem .75rem; border-radius:20px;font-size:.9rem} .tag svg{width:16px;height:16px;fill:#555} .tag .del{cursor:pointer;font-weight:700;color:#d91c31;font-size:1rem;line-height:1} .modal{ position:fixed;inset:0;display:none;align-items:center;justify-content:center; backdrop-filter:blur(3px);background:rgba(0,0,0,.35);padding:1rem;z-index:10} .modal.show{display:flex} .modal-content{background:#fff;padding:1.8rem;border-radius:12px;max-width:420px;width:100%; box-shadow:0 6px 22px rgba(0,0,0,.15)} .modal-content h3{margin-top:0;font-size:1.3rem;color:var(--brand)} .modal-content label{display:block;margin:1rem 0 .3rem;font-weight:600} .modal-content input{width:100%;padding:.55rem .65rem;border:1px solid #ccd2e2;border-radius:6px} .modal-content .actions{margin-top:1.4rem;display:flex;gap:1rem} .modal-content .actions button{flex:1} input:invalid{border-color:var(--err)} @media(prefers-color-scheme:dark){ :root{--bg:#0d1117;--fg:#e6edf3;--brand:#2f81f7} .card,.modal-content{background:#161b22} select,button,input{border-color:#30363d;background:#0d1117;color:var(--fg)} .tag{background:#243056} } </style> </head> <body> <main class="card"> <h1>Add your social links</h1> <select id="platformSel"> <option value="">βChoose a platformβ¦</option> </select> <button id="addBtn" disabled>Add link</button> <div class="tags" id="tagList"></div> </main> <!-- lightweight modal --> <div class="modal" id="modal"> <div class="modal-content"> <h3 id="modTitle">Add link</h3> <form id="modForm"> <label id="lblHandle"></label> <input id="inpHandle" autocomplete="off" required> <div class="actions"> <button type="button" onclick="closeModal()">Cancel</button> <button id="saveBtn">Save</button> </div> </form> </div> </div> <script> /* ------------------------------------------------------------------ 1. Platform catalogue β extend at will ------------------------------------------------------------------ */ const PLATFORMS = [ {id:'twitter', label:'TwitterΒ /Β X', url:'https://twitter.com/{handle}', prompt:'@handle', re:/^[A-Za-z0-9_]{1,15}$/}, {id:'facebook', label:'Facebook', url:'https://facebook.com/{handle}', prompt:'page or profile','re':/^[A-Za-z0-9.\-]{3,}$/}, {id:'instagram',label:'Instagram', url:'https://instagram.com/{handle}', prompt:'@handle', re:/^[A-Za-z0-9_.]{1,30}$/}, {id:'youtube', label:'YouTube', url:'https://youtube.com/{handle}', prompt:'channel/β¦', re:/^[A-Za-z0-9_\-]{1,}$/}, {id:'linkedin', label:'LinkedIn', url:'https://linkedin.com/in/{handle}', prompt:'public handle', re:/^[A-Za-z0-9\-]{3,100}$/}, {id:'tiktok', label:'TikTok', url:'https://tiktok.com/@{handle}', prompt:'@handle', re:/^[A-Za-z0-9_.]{2,24}$/}, {id:'pinterest',label:'Pinterest', url:'https://pinterest.com/{handle}', prompt:'username', re:/^[A-Za-z0-9_\-]{3,30}$/}, /* --- freeβform entry ------------------------- */ {id:'website', label:'Personal website', url:'{handle}', free:1 , prompt:'https://β¦', re:/^https?:\/\/.+/i}, {id:'nextdoor', label:'Nextdoor', url:'{handle}', free:1, prompt:'Neighbourhood URL', re:/^https?:\/\/.+/i} ]; /* DOM refs */ const sel = document.getElementById('platformSel'); const addBtn = document.getElementById('addBtn'); const modal = document.getElementById('modal'); const modTit = document.getElementById('modTitle'); const lblHand = document.getElementById('lblHandle'); const inpHand = document.getElementById('inpHandle'); const saveBtn = document.getElementById('saveBtn'); const form = document.getElementById('modForm'); const tagList = document.getElementById('tagList'); /* ------------------------------------------------------------------ 2. Populate dropdown ------------------------------------------------------------------ */ PLATFORMS.forEach(p=>{ const o = document.createElement('option'); o.value = p.id; o.textContent = p.label; sel.appendChild(o); }); /* ------------------------------------------------------------------ 3. UI interactions ------------------------------------------------------------------ */ sel.addEventListener('change', ()=>{ addBtn.disabled = !sel.value; if (sel.value) openModal(); // <ββ *autoβopen modal* }); addBtn.addEventListener('click', openModal); function openModal(){ const plat = PLATFORMS.find(p=>p.id===sel.value); if(!plat) return; modTit.textContent = `Add ${plat.label}`; lblHand.textContent= plat.free ? 'Full URL' : `Your ${plat.prompt}`; inpHand.value=''; inpHand.placeholder = plat.prompt; inpHand.pattern = plat.re.source; saveBtn.disabled = true; modal.classList.add('show'); inpHand.focus(); } function closeModal(){ modal.classList.remove('show'); sel.value=''; // reset selection addBtn.disabled=true; } /* Live validation */ inpHand.addEventListener('input',()=>{ saveBtn.disabled = !(new RegExp(inpHand.pattern,'i').test(inpHand.value.trim())); }); /* Persist in UI */ form.addEventListener('submit', (e)=>{ e.preventDefault(); const plat = PLATFORMS.find(p=>p.id===sel.value); const raw = inpHand.value.trim(); if(!plat || !raw) return; /* Build final URL */ const url = plat.free ? raw : plat.url.replace('{handle}', raw.replace(/^@/,'' )); /* Tag element */ const tag = document.createElement('span'); tag.className='tag'; tag.innerHTML = ` ${icon(plat.id)} <a href="${url}" target="_blank">${plat.id}</a> <span class="del" title="remove">Γ</span>`; tag.querySelector('.del').onclick = ()=> tag.remove(); tagList.appendChild(tag); closeModal(); }); /* Simple SVG icons (16β―Γβ―16) β extend as needed */ function icon(id){ switch(id){ case 'twitter': return '<svg viewBox="0 0 24 24"><path d="M22.46 6c-.77.35-1.6.58-2.46.69a4.3 4.3 0 001.9-2.38 8.59 8.59 0 01-2.72 1.04 4.28 4.28 0 00-7.28 3.91A12.16 12.16 0 013 4.89a4.28 4.28 0 001.33 5.72 4.25 4.25 0 01-1.94-.54v.06a4.28 4.28 0 003.44 4.2 4.3 4.3 0 01-1.93.07 4.28 4.28 0 003.99 2.97A8.6 8.6 0 012 19.54a12.14 12.14 0 006.56 1.93c7.88 0 12.2-6.53 12.2-12.2 0-.19 0-.39-.01-.58A8.63 8.63 0 0024 5.55a8.48 8.48 0 01-2.54.7z"/></svg>'; case 'facebook':return '<svg viewBox="0 0 24 24"><path d="M22 12.07A10 10 0 1011.93 22V14.7H9.1v-2.63h2.83V9.96c0-2.8 1.66-4.34 4.21-4.34 1.22 0 2.49.22 2.49.22v2.73h-1.4c-1.38 0-1.81.86-1.81 1.75v2.1h3.08l-.49 2.63h-2.59v7.23A10 10 0 0022 12.07z"/></svg>'; case 'linkedin':return '<svg viewBox="0 0 24 24"><path d="M4.98 3.5a2.5 2.5 0 115 0 2.5 2.5 0 01-5 0zM.5 8.75h4.95V24H.5zM8.12 8.75h4.74v2.07h.07c.66-1.25 2.28-2.57 4.7-2.57 5.02 0 5.95 3.3 5.95 7.59V24h-4.97v-8.65c0-2.06-.04-4.71-2.87-4.71-2.87 0-3.31 2.24-3.31 4.56V24H8.12z"/></svg>'; default: return ''; } } </script> </body> </html>
Save changes
Create folder
writable 0777
Create
Cancel