Skip to content

Commit

Permalink
Refactor theme selection to use single ThemeController instance
Browse files Browse the repository at this point in the history
  • Loading branch information
sparshalc committed Feb 6, 2024
1 parent 833ecf3 commit 2495f0a
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 22 deletions.
7 changes: 4 additions & 3 deletions app/components/theme/mobile_switcher_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
data-transition-leave-end="opacity-0"
class="absolute hidden z-10 mt-1 max-h-60 w-full min-w-max rounded-md bg-white dark:bg-gray-700 py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm" tabindex="-1" role="listbox" aria-labelledby="listbox-label" aria-activedescendant="listbox-option-3">

<ul data-controller="theme-switcher" data-theme-switcher-current-theme-value="<%= current_theme.to_s %>" data-theme-switcher-url-value="<%= themes_path(format: :turbo_stream) %>">
<% Users::Theme.default_themes.each do |theme| %>
<%= link_to themes_path(theme: theme.name), class: 'text-gray-700 dark:text-gray-300 group flex items-center px-3 py-2 text-sm', data: { turbo_method: :put, controller: 'theme-switcher', 'theme-switcher-theme-value': current_theme.to_s } do %>
<li class="text-gray-700 dark:text-gray-300 group flex items-center px-3 py-2 text-sm cursor-pointer" data-action="click->theme-switcher#handleThemeChangeRequest" data-theme="<%= theme.name %>">
<%= inline_svg_tag "icons/#{theme.icon}.svg", class: 'mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-500 dark:text-gray-300 dark:group-hover:text-gray-400', title: "#{theme.name} mode option", aria: true %>
<%= "#{theme.name.capitalize} mode" %>
<% end %>
</li>
<% end %>

</ul>
</ul>
</div>
</div>
13 changes: 8 additions & 5 deletions app/components/theme/switcher_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@
aria-orientation="vertical"
aria-labelledby="user-menu-button"
tabindex="-1">
<% Users::Theme.default_themes.each do |theme| %>
<%= link_to themes_path(theme: theme.name), class: 'text-gray-700 dark:text-gray-300 group flex items-center px-3 py-2 text-sm', data: { turbo_method: :put, controller: 'theme-switcher', 'theme-switcher-theme-value': current_theme.to_s } do %>
<%= inline_svg_tag "icons/#{theme.icon}.svg", class: 'mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-500 dark:text-gray-300 dark:group-hover:text-gray-400', title: "#{theme.name} mode option", aria: true %>
<%= "#{theme.name.capitalize} mode" %>

<ul data-controller="theme-switcher" data-theme-switcher-current-theme-value="<%= current_theme.to_s %>" data-theme-switcher-url-value="<%= themes_path(format: :turbo_stream) %>">
<% Users::Theme.default_themes.each do |theme| %>
<li class="text-gray-700 dark:text-gray-300 group flex items-center px-3 py-2 text-sm cursor-pointer" data-action="click->theme-switcher#handleThemeChangeRequest" data-theme="<%= theme.name %>">
<%= inline_svg_tag "icons/#{theme.icon}.svg", class: 'mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-500 dark:text-gray-300 dark:group-hover:text-gray-400', title: "#{theme.name} mode option", aria: true %>
<%= "#{theme.name.capitalize} mode" %>
</li>
<% end %>
<% end %>
</ul>
</div>
</div>
<% end %>
43 changes: 29 additions & 14 deletions app/javascript/controllers/theme_switcher_controller.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,49 @@
import { Controller } from '@hotwired/stimulus';
import { put } from '@rails/request.js';

export default class ThemeSwitcherController extends Controller {
static values = {
theme: String,
currentTheme: String,
url: String,
};

connect() {
const userThemePreference = this.getUserThemePreference();
const userThemePreference = this.currentThemeValue;

this.updateTheme(userThemePreference);
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', () => this.updateTheme(userThemePreference));
this.addThemeChangeListener(userThemePreference);
}

addThemeChangeListener(userThemePreference) {
const themeChangeHandler = () => this.updateTheme(userThemePreference);
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', themeChangeHandler);
}

async handleThemeChangeRequest(event) {
const { theme } = event.currentTarget.dataset;

await this.updateThemeAndSendRequest(theme);
}

updateTheme(userThemePreference) {
if (!['light', 'dark'].includes(userThemePreference)) {
const userSystemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
this.setUserTheme(userSystemTheme);
} else {
this.setUserTheme(userThemePreference);
}
async updateThemeAndSendRequest(theme) {
this.updateTheme(theme);
await put(this.urlValue, { body: JSON.stringify({ theme }) });
}

getUserThemePreference() {
return this.themeValue;
updateTheme(theme) {
const validThemes = ['light', 'dark'];
const userSystemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
const selectedTheme = validThemes.includes(theme) ? theme : userSystemTheme;

this.setUserTheme(selectedTheme);
}

// eslint-disable-next-line class-methods-use-this
setUserTheme(theme) {
const rootElement = document.getElementById('root-element');
rootElement.removeAttribute('class');
const availableThemes = ['system', 'light', 'dark'];

availableThemes.forEach((t) => rootElement.classList.remove(t));
rootElement.classList.add(theme);
}
}

0 comments on commit 2495f0a

Please sign in to comment.