Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[admin] dark mode #5511

Merged
merged 9 commits into from
Nov 15, 2023
Prev Previous commit
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.
  • Loading branch information
elia committed Nov 15, 2023
commit b94c635483390b8780ef48d3b9222dd4d8bdbcbb
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
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
Loading