Реализация Options Page (страница настроек) браузерного расширения

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация Options Page (страница настроек) браузерного расширения
Простая
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация Options Page (страница настроек) браузерного расширения

Options Page — отдельная страница расширения для управления настройками. В отличие от Popup, она не закрывается сама по себе и имеет полноэкранное пространство. Открывается через chrome.runtime.openOptionsPage() или из меню расширений браузера.

Два режима отображения

Полноэкранная страница (options_page) — открывается в отдельной вкладке браузера. Больше места, привычный интерфейс.

Встроенная в браузер (options_ui) — открывается прямо в chrome://extensions/ в нижней части карточки расширения. Доступна только в Chrome/Edge.

{
  "manifest_version": 3,
  "options_page": "options/options.html",

  // ИЛИ (взаимоисключающие):
  "options_ui": {
    "page": "options/options.html",
    "open_in_tab": false
  }
}

open_in_tab: false — показывать прямо в chrome://extensions/. open_in_tab: true — открывать в новой вкладке (аналогично options_page).

Структура React-приложения настроек

// options/App.tsx
import { useEffect, useState } from 'react';
import browser from 'webextension-polyfill';

interface Settings {
  enabled: boolean;
  theme: 'light' | 'dark' | 'system';
  highlightColor: string;
  blockedDomains: string[];
  shortcut: string;
}

const defaultSettings: Settings = {
  enabled: true,
  theme: 'system',
  highlightColor: '#fbbf24',
  blockedDomains: [],
  shortcut: 'Ctrl+Shift+Y',
};

export function OptionsApp() {
  const [settings, setSettings] = useState<Settings>(defaultSettings);
  const [saved, setSaved] = useState(false);

  useEffect(() => {
    browser.storage.sync.get('settings').then(({ settings: stored }) => {
      if (stored) setSettings({ ...defaultSettings, ...stored });
    });
  }, []);

  async function saveSettings(updated: Settings) {
    setSettings(updated);
    await browser.storage.sync.set({ settings: updated });
    setSaved(true);
    setTimeout(() => setSaved(false), 2000);
  }

  return (
    <div className="options">
      <h1>Настройки расширения</h1>

      <GeneralSection settings={settings} onChange={saveSettings} />
      <AppearanceSection settings={settings} onChange={saveSettings} />
      <BlocklistSection settings={settings} onChange={saveSettings} />

      {saved && <div className="options__saved">Настройки сохранены</div>}
    </div>
  );
}

Секции настроек

function GeneralSection({ settings, onChange }) {
  return (
    <section className="options__section">
      <h2>Основные</h2>

      <label className="options__field">
        <span>Расширение активно</span>
        <input
          type="checkbox"
          checked={settings.enabled}
          onChange={e => onChange({ ...settings, enabled: e.target.checked })}
        />
      </label>
    </section>
  );
}

function AppearanceSection({ settings, onChange }) {
  return (
    <section className="options__section">
      <h2>Внешний вид</h2>

      <label className="options__field">
        <span>Тема</span>
        <select
          value={settings.theme}
          onChange={e => onChange({ ...settings, theme: e.target.value as Settings['theme'] })}
        >
          <option value="system">Системная</option>
          <option value="light">Светлая</option>
          <option value="dark">Тёмная</option>
        </select>
      </label>

      <label className="options__field">
        <span>Цвет выделения</span>
        <input
          type="color"
          value={settings.highlightColor}
          onChange={e => onChange({ ...settings, highlightColor: e.target.value })}
        />
      </label>
    </section>
  );
}

Список блокировок с редактированием

function BlocklistSection({ settings, onChange }) {
  const [newDomain, setNewDomain] = useState('');

  const addDomain = () => {
    const trimmed = newDomain.trim().replace(/^https?:\/\//, '').replace(/\/$/, '');
    if (!trimmed || settings.blockedDomains.includes(trimmed)) return;
    onChange({ ...settings, blockedDomains: [...settings.blockedDomains, trimmed] });
    setNewDomain('');
  };

  const removeDomain = (domain: string) => {
    onChange({
      ...settings,
      blockedDomains: settings.blockedDomains.filter(d => d !== domain),
    });
  };

  return (
    <section className="options__section">
      <h2>Исключённые сайты</h2>

      <div className="options__add-domain">
        <input
          value={newDomain}
          onChange={e => setNewDomain(e.target.value)}
          onKeyDown={e => e.key === 'Enter' && addDomain()}
          placeholder="example.com"
        />
        <button onClick={addDomain}>Добавить</button>
      </div>

      <ul className="options__domain-list">
        {settings.blockedDomains.map(domain => (
          <li key={domain}>
            <span>{domain}</span>
            <button onClick={() => removeDomain(domain)}>✕</button>
          </li>
        ))}
      </ul>
    </section>
  );
}

Открытие Options Page из других контекстов

// Из Popup
document.getElementById('btn-settings').addEventListener('click', () => {
  browser.runtime.openOptionsPage();
});

// Из Background (Service Worker)
chrome.action.onClicked.addListener(() => {
  chrome.runtime.openOptionsPage();
});

// Прямая ссылка (например, в onboarding-странице)
const optionsUrl = browser.runtime.getURL('options/options.html');
browser.tabs.create({ url: optionsUrl });

Синхронизация настроек между устройствами

browser.storage.sync автоматически синхронизирует данные через Google/Microsoft аккаунт:

// Подписка на изменения — если пользователь изменил настройки на другом устройстве
browser.storage.onChanged.addListener((changes, area) => {
  if (area === 'sync' && changes.settings) {
    const newSettings = changes.settings.newValue;
    applySettingsToContentScripts(newSettings);
  }
});

async function applySettingsToContentScripts(settings) {
  const tabs = await browser.tabs.query({ url: ['http://*/*', 'https://*/*'] });
  for (const tab of tabs) {
    browser.tabs.sendMessage(tab.id, {
      type: 'SETTINGS_UPDATED',
      settings,
    }).catch(() => {}); // игнорируем, если content script не загружен
  }
}

Сброс настроек

async function resetToDefaults() {
  if (!confirm('Сбросить все настройки к значениям по умолчанию?')) return;
  await browser.storage.sync.remove('settings');
  setSettings(defaultSettings);
}

Сроки

Options Page с базовыми настройками (5–10 параметров), сохранением в storage.sync и открытием из Popup — 1–2 рабочих дня.