> ## Documentation Index > Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt > Use this file to discover all available pages before exploring further. # Angular Web SDK setup > Integrate OneSignal Web Push Notifications into your Angular application using the onesignal-ngx package. Learn how to install, configure, and troubleshoot service workers to deliver seamless push notifications. export const SdkReleasesIframe = ({sdkFilter = undefined, viewMode = undefined, height, ...frameProps}) => { const baseUrl = 'https://onesignal.github.io/sdk-releases'; const buildUrl = (theme, sdkFilter, viewMode) => { const url = new URL(baseUrl); const params = new URLSearchParams(); if (theme) { params.set('theme', theme); } if (sdkFilter) { params.set('sdk', sdkFilter); } if (viewMode) { params.set('viewMode', viewMode); } if (params.toString()) { url.search = params.toString(); } return url.toString(); }; const detectTheme = () => { if (document.documentElement.classList.contains('dark')) { return 'dark'; } return 'light'; }; const [theme, setTheme] = useState('light'); const [iframeSrc, setIframeSrc] = useState(() => { const initialTheme = detectTheme(); return buildUrl(initialTheme, sdkFilter, viewMode); }); useEffect(() => { const currentTheme = detectTheme(); setTheme(currentTheme); setIframeSrc(buildUrl(currentTheme, sdkFilter, viewMode)); const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); const handleThemeChange = () => { const newTheme = detectTheme(); setTheme(newTheme); setIframeSrc(buildUrl(newTheme, sdkFilter, viewMode)); }; if (mediaQuery.addEventListener) { mediaQuery.addEventListener('change', handleThemeChange); } else { mediaQuery.addListener(handleThemeChange); } window.addEventListener('storage', handleThemeChange); const observer = new MutationObserver(handleThemeChange); observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class', 'data-theme'] }); return () => { if (mediaQuery.removeEventListener) { mediaQuery.removeEventListener('change', handleThemeChange); } else { mediaQuery.removeListener(handleThemeChange); } window.removeEventListener('storage', handleThemeChange); observer.disconnect(); }; }, [sdkFilter, viewMode]); const getIframeHeight = () => { if (viewMode === 'table') { return '450'; } if (viewMode === 'mini') { return '170'; } return '800'; }; const iframeHeight = height || getIframeHeight(); return