Skip to content

Commit

Permalink
Add theme support to the SolidusAdmin UI with dark and dimmed variants
Browse files Browse the repository at this point in the history
- Save the user preference alongside the system preference so that
  when the system switches the UI will follow along.
- Use the session to store preferences so that we start the page
  with the correct theme(s).
- Keep the current theme in the select tag up to date at page load
  and whenever the system changes.

Add dark and dimmed theme variants

dark:
  Full black background with no alteration on images.

dimmed:
  Dark gray background with dimmed images, easier on the eyes but
  less accurate colors.
  • Loading branch information
elia committed Nov 15, 2023
1 parent 74efa66 commit b94c635
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 2 deletions.
12 changes: 12 additions & 0 deletions admin/app/assets/stylesheets/solidus_admin/dark.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* = require solidus_admin/tailwind.css
*/

html {
-webkit-filter: invert(100%);
filter: invert(100%) hue-rotate(180deg);
}

main img {
filter: invert(100%) hue-rotate(-180deg);
}
11 changes: 11 additions & 0 deletions admin/app/assets/stylesheets/solidus_admin/dimmed.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* = require solidus_admin/tailwind.css
*/

html {
filter: invert(91%) hue-rotate(180deg);
}

main img {
filter: invert(91%) brightness(1.5) contrast(1.5) hue-rotate(-180deg);
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,26 @@
</li>
<% end %>

<li class="h-8 items-center hover:bg-gray-25 rounded dark:hidden flex">
<%= autosubmit_select_tag(
"switch_to_theme",
options_for_select(theme_options_for_select, session[:admin_light_theme]),
icon: 'sun-line',
) do %>
<%= hidden_field_tag(:system_theme, :light) %>
<% end %>
</li>

<li class="h-8 items-center hover:bg-gray-25 rounded hidden dark:flex">
<%= autosubmit_select_tag(
"switch_to_theme",
options_for_select(theme_options_for_select, session[:admin_dark_theme]),
icon: 'moon-line',
) do %>
<%= hidden_field_tag(:system_theme, :dark) %>
<% end %>
</li>

<li class="h-8 flex items-center hover:bg-gray-25 rounded">
<%= link_to @account_path, class: 'flex gap-2 items-center px-2' do %>
<%= icon_tag("user-3-line", class: "w-5 h-5 fill-current shrink") %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ def locale_options_for_select(available_locales)
end.sort
end

def theme_options_for_select
SolidusAdmin::Config.themes.keys.map { |theme| [theme.to_s.humanize, theme] }.sort
end

def autosubmit_select_tag(name, options, icon:, &block)
form_tag(request.fullpath, method: :get, 'data-turbo': false, class: "w-full") do
safe_join([
Expand Down
1 change: 1 addition & 0 deletions admin/app/controllers/solidus_admin/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class BaseController < ApplicationController
include SolidusAdmin::ControllerHelpers::Authentication
include SolidusAdmin::ControllerHelpers::Authorization
include SolidusAdmin::ControllerHelpers::Locale
include SolidusAdmin::ControllerHelpers::Theme
include SolidusAdmin::ComponentsHelper
include SolidusAdmin::AuthenticationAdapters::Backend if defined?(Spree::Backend)

Expand Down
30 changes: 30 additions & 0 deletions admin/app/controllers/solidus_admin/controller_helpers/theme.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module SolidusAdmin::ControllerHelpers::Theme
extend ActiveSupport::Concern

included do
before_action :update_user_theme
end

private

def update_user_theme
requested_theme = params[:switch_to_theme].presence or return

# Avoid interpolating user content into the session key
system_theme = params[:system_theme].presence == "dark" ? "dark" : "light"
session_key = :"admin_#{system_theme}_theme"

if theme_is_available?(requested_theme) && requested_theme.to_sym != session[session_key]
session[session_key] = requested_theme

flash[:notice] = t('spree.theme_changed')
redirect_to params.except(:switch_to_theme, :system_theme).permit!.to_h.merge(account_menu_open: true)
end
end

def theme_is_available?(theme)
theme && SolidusAdmin::Config.themes.key?(theme.to_sym)
end
end
4 changes: 3 additions & 1 deletion admin/app/views/layouts/solidus_admin/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
<head>
<%= favicon_link_tag 'solidus_admin/favicon.ico' %>
<title><%= solidus_admin_title %></title>
<%= stylesheet_link_tag "solidus_admin/application.css", "inter-font", "data-turbo-track": "reload" %>
<%= stylesheet_link_tag "inter-font", "data-turbo-track": "reload" %>
<%= stylesheet_link_tag SolidusAdmin::Config.theme_path(session[:admin_light_theme]), media: '(prefers-color-scheme: light)', "data-turbo-track": "reload" %>
<%= stylesheet_link_tag SolidusAdmin::Config.theme_path(session[:admin_dark_theme]), media: '(prefers-color-scheme: dark)', "data-turbo-track": "reload" %>
<%= javascript_importmap_tags "solidus_admin/application", shim: false, importmap: SolidusAdmin.importmap %>
</head>

Expand Down
20 changes: 20 additions & 0 deletions admin/lib/solidus_admin/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,26 @@ def components

# The HTTP method used to logout the user in the admin interface.
preference :logout_link_method, :string, default: :delete

# @!attribute [rw] themes
# @return [Hash] A hash containing the themes that are available for the admin panel
preference :themes, :hash, default: {
solidus: 'solidus_admin/application',
solidus_dark: 'solidus_admin/dark',
solidus_dimmed: 'solidus_admin/dimmed',
}

# @!attribute [rw] theme
# @return [String] Default admin theme name
preference :theme, :string, default: 'solidus'

# @!attribute [rw] dark_theme
# @return [String] Default admin theme name
preference :dark_theme, :string, default: 'solidus_dark'

def theme_path(user_theme)
themes.fetch(user_theme&.to_sym, themes[theme.to_sym])
end
end
end

Expand Down
5 changes: 4 additions & 1 deletion admin/spec/features/accounts_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
expect(current_path).to eq("/admin/users/#{user.id}/edit")
end

it "can change locale", :js do
it "can change locale and theme", :js do
I18n.config.available_locales_set << :"en-UK"
I18n.config.available_locales_set << "en-UK"
I18n.backend.store_translations('en-UK', spree: { i18n: { this_file_language: "English (UK)" } })
Expand All @@ -30,5 +30,8 @@
expect(page).to have_content("English (UK)")
select "English (US)", from: 'switch_to_locale'
expect(page).to have_content("English (US)")

within('.dark\:hidden') { select "Solidus dark", from: "switch_to_theme" }
expect(page).to have_content("Solidus dark")
end
end

0 comments on commit b94c635

Please sign in to comment.