PageSourceSearch

https://webawesome.com/assets/scripts/theme.js

js webawesome.com collected 2026-09-24 21:47:25 UTC 3,677 bytes, 115 lines download raw bytes

1import { doViewTransition } from '../scripts/view-transitions.js';
2
3//
4// Updates the theme when a theme selector changes
5//
6async function updateTheme(value, isInitialLoad = false) {
7  const body = document.body;
8
9  // Get brand, palette, and theme name from the selected option
10  const themeSelector = document.querySelector('.theme-selector');
11  const selectedOption = themeSelector?.querySelector(`wa-dropdown-item[value="${value}"]`);
12  let brand = selectedOption?.getAttribute('data-brand') || 'blue';
13  let palette = selectedOption?.getAttribute('data-palette') || 'default';
14  let themeName = selectedOption?.textContent.trim() || 'Unknown';
15
16  if (!isInitialLoad) {
17    // Disable tooltip during theme transition
18    const tooltip = document.querySelector('#theme-tooltip');
19    if (tooltip) {
20      tooltip.disabled = true;
21    }
22
23    // Add fade-out class
24    body.classList.add('theme-transitioning');
25
26    // Wait for fade-out to complete
27    await new Promise(resolve => {
28      const handleTransitionEnd = event => {
29        if (event.target === body && event.propertyName === 'opacity') {
30          body.removeEventListener('transitionend', handleTransitionEnd);
31          resolve();
32        }
33      };
34      body.addEventListener('transitionend', handleTransitionEnd);
35    });
36  }
37
38  // Handle site theme vs regular theme
39  let href = `/dist/styles/themes/${value}.css`;
40
41  if (document.querySelector('wa-page')?.dataset.pageType === 'site') {
42    brand = 'orange';
43    href = `/assets/styles/theme-site.css`;
44    palette = 'default';
45    value = 'site';
46  } else {
47    localStorage.setItem('brand', brand);
48    localStorage.setItem('palette', palette);
49    localStorage.setItem('theme', value);
50    setCookie({ name: 'webawesome_brand', value: brand });
51    setCookie({ name: 'webawesome_palette', value: palette });
52    setCookie({ name: 'webawesome_theme', value });
53  }
54
55  // Update theme classes
56  const htmlElement = document.documentElement;
57  const classesToRemove = Array.from(htmlElement.classList).filter(
58    className =>
59      className.startsWith('wa-theme-') || className.startsWith('wa-brand-') || className.startsWith('wa-palette-'),
60  );
61  const themeStylesheet = document.getElementById('theme-stylesheet');
62
63  await doViewTransition(() => {
64    // Update the theme
65    if (themeStylesheet) {
66      themeStylesheet.href = href;
67    }
68
69    htmlElement.classList.remove(...classesToRemove);
70
71    // Add the new theme, brand, and palette classes
72    htmlElement.classList.add(`wa-theme-${value}`);
73    htmlElement.classList.add(`wa-brand-${brand}`);
74    htmlElement.classList.add(`wa-palette-${palette}`);
75
76    // Sync all theme selectors
77    document.querySelectorAll('.theme-selector').forEach(el => {
78      el.value = value;
79      el.setAttribute('value', value);
80    });
81
82    // Update tooltip content to reflect the new theme
83    const tooltip = document.querySelector('#theme-tooltip');
84    if (tooltip) {
85      tooltip.textContent = `${themeName} Theme`;
86    }
87  });
88
89  if (!isInitialLoad) {
90    // Remove transition class and re-enable tooltip after view transition completes
91    body.classList.remove('theme-transitioning');
92
93    const tooltip = document.querySelector('#theme-tooltip');
94    if (tooltip) {
95      tooltip.disabled = false;
96    }
97  }
98}
99
100// Handle changes
101document.addEventListener('input', event => {
102  if (event.target.matches('.theme-selector')) {
103    updateTheme(event.target.value);
104  }
105});
106
107// Initialize
108function initializeTheme() {
109  const savedTheme = localStorage.getItem('theme') || 'default';
110  updateTheme(savedTheme, true);
111}
112
113initializeTheme();
114
115document.addEventListener('turbo:render', initializeTheme);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.