DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

Search Bar in a Firefox New Tab Extension: Which Engine, How to Handle

Search Bar in a Firefox New Tab Extension: Which Engine, How to Handle

Adding a search bar to a new tab extension sounds simple — it's just a text input and a redirect. But there are enough details to get right that it's worth writing down.

The Basic Implementation

<form id="search-form" role="search">
  <input
    type="search"
    id="search-input"
    placeholder="Search..."
    autocomplete="off"
    autofocus
  />
</form>
Enter fullscreen mode Exit fullscreen mode
document.getElementById('search-form').addEventListener('submit', e => {
  e.preventDefault();
  const query = document.getElementById('search-input').value.trim();
  if (query) {
    window.location.href = buildSearchUrl(query);
  }
});
Enter fullscreen mode Exit fullscreen mode

Supporting Multiple Search Engines

const SEARCH_ENGINES = {
  google: {
    name: 'Google',
    url: 'https://www.google.com/search?q=',
    icon: '🔍'
  },
  duckduckgo: {
    name: 'DuckDuckGo',
    url: 'https://duckduckgo.com/?q=',
    icon: '🦆'
  },
  bing: {
    name: 'Bing',
    url: 'https://www.bing.com/search?q=',
    icon: '🔷'
  },
  brave: {
    name: 'Brave Search',
    url: 'https://search.brave.com/search?q=',
    icon: '🦁'
  },
  startpage: {
    name: 'Startpage',
    url: 'https://www.startpage.com/search?q=',
    icon: '🔒'
  },
};

function buildSearchUrl(query, engine = 'google') {
  const { url } = SEARCH_ENGINES[engine] || SEARCH_ENGINES.google;
  return url + encodeURIComponent(query);
}
Enter fullscreen mode Exit fullscreen mode

Keyboard Shortcut: Focus Search on Any Key

For power users — pressing any letter key should focus the search bar:

document.addEventListener('keydown', e => {
  // Don't steal focus if user is typing in another input
  if (document.activeElement.tagName === 'INPUT') return;
  if (document.activeElement.tagName === 'TEXTAREA') return;

  // Skip special keys
  if (e.ctrlKey || e.metaKey || e.altKey) return;
  if (e.key.length !== 1) return; // Skip Shift, Enter, etc.

  const searchInput = document.getElementById('search-input');
  searchInput.focus();
  // Don't prevent default — let the keystroke go into the input
});
Enter fullscreen mode Exit fullscreen mode

URL Detection: Smart Redirect

Users often type URLs into search bars. Detect and redirect directly:

function isUrl(input) {
  // Has a dot and no spaces -> likely a URL
  if (!input.includes('.') || input.includes(' ')) return false;

  // Check known TLDs
  const tldPattern = /\.(com|net|org|io|dev|co|app|ai|me|uk|de|fr|ca|au)(\/.*)?$/i;
  if (tldPattern.test(input)) return true;

  // Has http(s):// prefix
  if (/^https?:\/\//i.test(input)) return true;

  return false;
}

function buildSearchUrl(query, engine = 'google') {
  if (isUrl(query)) {
    // Navigate directly to URL
    if (/^https?:\/\//i.test(query)) return query;
    return 'https://' + query;
  }

  const { url } = SEARCH_ENGINES[engine] || SEARCH_ENGINES.google;
  return url + encodeURIComponent(query);
}
Enter fullscreen mode Exit fullscreen mode

Open in New Tab vs Same Tab

Let users decide:

document.getElementById('search-form').addEventListener('submit', e => {
  e.preventDefault();
  const query = document.getElementById('search-input').value.trim();
  if (!query) return;

  const url = buildSearchUrl(query, currentEngine);

  if (openInNewTab) {
    window.open(url, '_blank');
  } else {
    window.location.href = url;
  }
});

// Also handle Ctrl+Enter for "new tab" regardless of setting
document.getElementById('search-input').addEventListener('keydown', e => {
  if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
    e.preventDefault();
    const query = e.target.value.trim();
    if (query) window.open(buildSearchUrl(query), '_blank');
  }
});
Enter fullscreen mode Exit fullscreen mode

Search Suggestions (Optional)

For DuckDuckGo, there's a free suggestions API:

async function getSuggestions(query) {
  if (query.length < 2) return [];
  try {
    const resp = await fetch(
      `https://duckduckgo.com/ac/?q=${encodeURIComponent(query)}&type=list`
    );
    const [, suggestions] = await resp.json();
    return suggestions.slice(0, 5);
  } catch {
    return [];
  }
}
Enter fullscreen mode Exit fullscreen mode

Note: This requires host_permissions for https://duckduckgo.com/ in your manifest.

Accessibility

Don't forget:

<form role="search" aria-label="Web search">
  <label for="search-input" class="visually-hidden">Search the web</label>
  <input
    type="search"
    id="search-input"
    aria-label="Search query"
    placeholder="Search or enter address"
  />
  <button type="submit" aria-label="Search">
    <svg><!-- search icon --></svg>
  </button>
</form>
Enter fullscreen mode Exit fullscreen mode

What Engine to Default To?

I use Google as default in Weather & Clock Dashboard because it's what most users expect. But DuckDuckGo is a close second for privacy-conscious users, and it's trivially changeable in settings.

The key principle: match the user's existing habits. A new tab extension is productivity infrastructure — it should disappear into the workflow, not require relearning.


Weather & Clock Dashboard — free Firefox new tab with search, weather, and clocks. MIT licensed, no tracking.

Top comments (0)