Maharashtra State Electricity Distribution Co. Ltd.

पुण्यश्लोक
/* Base sizing uses rem so zooming scales everything consistently */ :root { --btn-size: 2.25rem; /* button width/height (scales with font-size and browser zoom) */ --gap: 0.5rem; --radius: 0.5rem; --accent: #f05; --voice-bg: #555; } /* Container - allow wrapping when space is tight */ .wp-voice-search-form { display: flex; align-items: center; gap: var(--gap); position: relative; width: 100%; max-width: 60rem; /* practical maximum width on wide screens */ box-sizing: border-box; margin: 0 auto; padding: 0; } /* Input grows to fill available space, but won't force the buttons out. min-width:0 is critical to allow flex children to shrink inside overflowed containers. */ .wp-voice-search-input { flex: 1 1 auto; min-width: 0; padding: 0.45rem 0.75rem; font-size: 1rem; line-height: 1.2; border: 1px solid #ccc; border-radius: var(--radius); box-sizing: border-box; width: 100%; max-width: 100%; } /* Buttons are square, accessible size, and remain visible when zoomed */ .wp-voice-btn, .wp-search-btn { display: inline-flex; align-items: center; justify-content: center; width: var(--btn-size); height: var(--btn-size); min-width: var(--btn-size); min-height: var(--btn-size); border: none; border-radius: calc(var(--radius) / 1.2); cursor: pointer; background-color: var(--accent); color: #fff; font-size: 1rem; line-height: 1; box-sizing: border-box; padding: 0; } /* Voice button variant */ .wp-voice-btn { background-color: var(--voice-bg); } /* Make icons scale nicely inside buttons */ .wp-voice-btn i, .wp-search-btn i { font-size: 1rem; /* scales with zoom */ display: block; } /* Visible focus outlines for keyboard accessibility */ .wp-voice-btn:focus, .wp-search-btn:focus, .wp-voice-search-input:focus { outline: 3px solid rgba(0,0,0,0.12); outline-offset: 2px; } /* Popup positioned relative to the voice button; will not overflow input area */ .wp-speak-popup { display: none; position: absolute; top: calc(100% + 0.4rem); /* below the form */ right: 0; /* align to the right side of the form by default */ background: #e53935; color: white; padding: 0.45rem 0.6rem; border-radius: 0.4rem; font-size: 0.95rem; white-space: nowrap; z-index: 9999; box-shadow: 0 6px 18px rgba(0,0,0,0.12); } /* When popup should appear near the voice button specifically (JS toggles class) */ .wp-speak-popup.--anchor-voice { right: var(--btn-size); /* move left so it sits next to voice button */ } /* Responsive behavior: allow buttons to wrap beneath the input if extremely zoomed / narrow */ @media (max-width: 420px) { .wp-voice-search-form { gap: 0.4rem; } .wp-voice-btn, .wp-search-btn { width: 2rem; height: 2rem; } } /* If the container becomes very narrow, stack buttons below input for best usability */ @media (max-width: 360px) { .wp-voice-search-form { flex-wrap: wrap; } .wp-voice-search-input { width: 100%; } .wp-voice-btn, .wp-search-btn { margin-top: 0.25rem; } }
Speak…
document.addEventListener('DOMContentLoaded', function() { const forms = document.querySelectorAll('.wp-voice-search-form'); if (!('webkitSpeechRecognition' in window) && !('SpeechRecognition' in window)) { forms.forEach(form => { const voiceBtn = form.querySelector('.wp-voice-btn'); voiceBtn.disabled = true; voiceBtn.setAttribute('aria-disabled', 'true'); }); return; } // Choose available API const SpeechRec = window.SpeechRecognition || window.webkitSpeechRecognition; forms.forEach(form => { const voiceBtn = form.querySelector('.wp-voice-btn'); const voiceIcon = form.querySelector('.wp-voice-icon'); const searchInput = form.querySelector('.wp-voice-search-input'); const popup = form.querySelector('.wp-speak-popup'); const recognition = new SpeechRec(); recognition.lang = 'en-US'; recognition.interimResults = false; recognition.maxAlternatives = 1; // Helper to position popup near voice button when form width is small function anchorPopup() { // if form width is small (< input + 2 buttons), anchor to voice button const formRect = form.getBoundingClientRect(); const inputRect = searchInput.getBoundingClientRect(); // simple heuristic: if input takes < 60% of form, anchor to voice if ((inputRect.width / formRect.width) { popup.style.display = 'block'; voiceIcon.style.opacity = '0.5'; try { recognition.start(); } catch (e) { // if start throws because already started, ignore } // safety timeout in case onend doesn't fire (5s) const stopTimeout = setTimeout(() => { try { recognition.stop(); } catch(e){} popup.style.display = 'none'; }, 5000); // clear timeout when recognition ends recognition.addEventListener('end', () => clearTimeout(stopTimeout), { once: true }); }); recognition.onresult = (event) => { const transcript = event.results[0][0].transcript; searchInput.value = transcript; popup.style.display = 'none'; // submit the parent form const frm = searchInput.form; if (frm) frm.submit(); }; recognition.onend = () => { voiceIcon.style.opacity = '1'; popup.style.display = 'none'; }; recognition.onerror = (evt) => { // hide popup on error and restore icon voiceIcon.style.opacity = '1'; popup.style.display = 'none'; console.warn('Speech recognition error:', evt); }; }); });

Urja
Empowering the Consumer