From 351fc843451fe9ff2a97a7fc9a0317b12cda7b03 Mon Sep 17 00:00:00 2001 From: Elia Schito Date: Mon, 13 Nov 2023 17:10:05 +0100 Subject: [PATCH] Add theme support to the SolidusAdmin UI with dark and dimmed variants - 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. --- .../assets/stylesheets/solidus_admin/dark.css | 12 ++++++++ .../stylesheets/solidus_admin/dimmed.css | 11 +++++++ .../navigation/account/component.html.erb | 20 +++++++++++++ .../layout/navigation/account/component.rb | 4 +++ .../solidus_admin/base_controller.rb | 1 + .../solidus_admin/controller_helpers/theme.rb | 30 +++++++++++++++++++ .../solidus_admin/application.html.erb | 4 ++- admin/lib/solidus_admin/configuration.rb | 20 +++++++++++++ 8 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 admin/app/assets/stylesheets/solidus_admin/dark.css create mode 100644 admin/app/assets/stylesheets/solidus_admin/dimmed.css create mode 100644 admin/app/controllers/solidus_admin/controller_helpers/theme.rb diff --git a/admin/app/assets/stylesheets/solidus_admin/dark.css b/admin/app/assets/stylesheets/solidus_admin/dark.css new file mode 100644 index 00000000000..e03ce11406e --- /dev/null +++ b/admin/app/assets/stylesheets/solidus_admin/dark.css @@ -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); +} diff --git a/admin/app/assets/stylesheets/solidus_admin/dimmed.css b/admin/app/assets/stylesheets/solidus_admin/dimmed.css new file mode 100644 index 00000000000..48f987743f8 --- /dev/null +++ b/admin/app/assets/stylesheets/solidus_admin/dimmed.css @@ -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); +} diff --git a/admin/app/components/solidus_admin/layout/navigation/account/component.html.erb b/admin/app/components/solidus_admin/layout/navigation/account/component.html.erb index c396d5528bc..4b10ff51939 100644 --- a/admin/app/components/solidus_admin/layout/navigation/account/component.html.erb +++ b/admin/app/components/solidus_admin/layout/navigation/account/component.html.erb @@ -36,6 +36,26 @@ <% end %> +
  • + <%= 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 %> +
  • + + +
  • <%= 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") %> diff --git a/admin/app/components/solidus_admin/layout/navigation/account/component.rb b/admin/app/components/solidus_admin/layout/navigation/account/component.rb index f4f1dd3af93..79c7308c471 100644 --- a/admin/app/components/solidus_admin/layout/navigation/account/component.rb +++ b/admin/app/components/solidus_admin/layout/navigation/account/component.rb @@ -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([ diff --git a/admin/app/controllers/solidus_admin/base_controller.rb b/admin/app/controllers/solidus_admin/base_controller.rb index 457bc8243be..44665e05295 100644 --- a/admin/app/controllers/solidus_admin/base_controller.rb +++ b/admin/app/controllers/solidus_admin/base_controller.rb @@ -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) diff --git a/admin/app/controllers/solidus_admin/controller_helpers/theme.rb b/admin/app/controllers/solidus_admin/controller_helpers/theme.rb new file mode 100644 index 00000000000..a8a34aa4646 --- /dev/null +++ b/admin/app/controllers/solidus_admin/controller_helpers/theme.rb @@ -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_back_or_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 diff --git a/admin/app/views/layouts/solidus_admin/application.html.erb b/admin/app/views/layouts/solidus_admin/application.html.erb index 8d81debc164..615cb0cab31 100644 --- a/admin/app/views/layouts/solidus_admin/application.html.erb +++ b/admin/app/views/layouts/solidus_admin/application.html.erb @@ -3,7 +3,9 @@ <%= favicon_link_tag 'solidus_admin/favicon.ico' %> <%= solidus_admin_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 %> diff --git a/admin/lib/solidus_admin/configuration.rb b/admin/lib/solidus_admin/configuration.rb index e2973ef9bfb..4a03a5d84de 100644 --- a/admin/lib/solidus_admin/configuration.rb +++ b/admin/lib/solidus_admin/configuration.rb @@ -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