From 3319e685268ba9a66225cde90f3f3b7f87b59b94 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 4 May 2020 13:20:57 +0200 Subject: [PATCH] Auto-adjusts text colors based on the selected theme colors --- CHANGELOG.md | 1 + app/assets/stylesheets/app.nav.scss | 1 - app/assets/templates/home/members.html | 2 +- app/controllers/api/i_calendar_controller.rb | 2 +- app/models/stylesheet.rb | 57 ++++++++++++------- .../api/i_calendar/_i_calendar.json.jbuilder | 2 +- .../20191127153729_create_i_calendars.rb | 2 +- 7 files changed, 43 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0f6041df..878dcd245 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Interface to manage partners - Ability to define, per availability, a custom duration for the reservation slots - Corrected the documentation about BOOK_SLOT_AT_SAME_TIME +- Auto-adjusts text colors based on the selected theme colors - Fix a bug: unable to change group if the previous was deactivated - Fix a bug: unable to create events or trainings that are not multiples of SLOT_DURATION - Fix a bug: unable to delete an unreserved event diff --git a/app/assets/stylesheets/app.nav.scss b/app/assets/stylesheets/app.nav.scss index a2d0cbf1e..f632fd94f 100644 --- a/app/assets/stylesheets/app.nav.scss +++ b/app/assets/stylesheets/app.nav.scss @@ -107,7 +107,6 @@ > li.menu-spacer { height: 1px; margin: 6px 80% 6px 5px; - background: linear-gradient(45deg, black, transparent); } ul { diff --git a/app/assets/templates/home/members.html b/app/assets/templates/home/members.html index de16e1254..030de6ea1 100644 --- a/app/assets/templates/home/members.html +++ b/app/assets/templates/home/members.html @@ -10,7 +10,7 @@ - {{member.name}} + {{member.name}} diff --git a/app/controllers/api/i_calendar_controller.rb b/app/controllers/api/i_calendar_controller.rb index 76cd5beb1..4a02fc5a2 100644 --- a/app/controllers/api/i_calendar_controller.rb +++ b/app/controllers/api/i_calendar_controller.rb @@ -47,6 +47,6 @@ class API::ICalendarController < API::ApiController end def i_calendar_params - params.require(:i_calendar).permit(:name, :url, :color, :text_color, :text_hidden) + params.require(:i_calendar).permit(:name, :url, :color, :primary_text_color, :text_hidden) end end diff --git a/app/models/stylesheet.rb b/app/models/stylesheet.rb index 7dfddc278..48700fa58 100644 --- a/app/models/stylesheet.rb +++ b/app/models/stylesheet.rb @@ -4,6 +4,11 @@ # a picture for the background of the user's profile. # There's only one stylesheet record in the database, which is updated on each colour change. class Stylesheet < ApplicationRecord + + # brightness limits to change the font color to black or white + BRIGHTNESS_HIGH_LIMIT = 180 + BRIGHTNESS_LOW_LIMIT = 40 + validates_presence_of :contents ## ===== COMMON ===== @@ -60,45 +65,59 @@ class Stylesheet < ApplicationRecord Stylesheet.find_by(name: 'theme') end + def self.primary_text_color + Stylesheet.primary.paint.brightness >= BRIGHTNESS_HIGH_LIMIT ? 'black' : 'white' + end + + def self.primary_decoration_color + Stylesheet.primary.paint.brightness <= BRIGHTNESS_LOW_LIMIT ? 'white' : 'black' + end + + def self.secondary_text_color + Stylesheet.secondary.paint.brightness <= BRIGHTNESS_LOW_LIMIT ? 'white' : 'black' + end + def self.css # rubocop:disable Metrics/AbcSize <<~CSS .bg-red { background-color: #{Stylesheet.primary}; } .bg-red-dark { background-color: #{Stylesheet.primary}; } #nav .nav { background-color: #{Stylesheet.primary}; } - #nav .nav > li > a { color: white; } - #nav .nav > li > a:hover, #nav .nav > li > a:focus { background-color: #{Stylesheet.primary_light}; } - #nav .nav > li > a.active { border-left: 3px solid #{Stylesheet.primary_dark}; background-color: #{Stylesheet.primary_light}; } - #nav .nav > li > a.active { border-left: 3px solid #{Stylesheet.primary_dark}; background-color: #{Stylesheet.primary_light}; } - .btn-theme { background-color: #{Stylesheet.primary}; color: white; } - .btn-theme:active, .btn-theme:hover { background-color: #{Stylesheet.primary_dark}; } - .label-theme { background-color: #{Stylesheet.primary} } + #nav .nav > li > a { color: #{Stylesheet.primary_text_color}; } + #nav .nav > li > a:hover, #nav .nav > li > a:focus { background-color: #{Stylesheet.primary_light}; color: #{Stylesheet.primary_text_color}; } + #nav .nav > li > a.active { border-left: 3px solid #{Stylesheet.primary_dark}; background-color: #{Stylesheet.primary_light}; color: #{Stylesheet.primary_text_color}; } + .nav-primary ul.nav > li.menu-spacer { background: linear-gradient(45deg, #{Stylesheet.primary_decoration_color}, transparent); } + .nav-primary .text-bordeau { color: #{Stylesheet.primary_decoration_color}; } + .btn-theme { background-color: #{Stylesheet.primary}; color: #{Stylesheet.primary_text_color}; } + .btn-theme:active, .btn-theme:hover { background-color: #{Stylesheet.primary_dark}; color: #{Stylesheet.primary_text_color}; } + .label-theme { background-color: #{Stylesheet.primary}; color: #{Stylesheet.primary_text_color}; } .btn-link { color: #{Stylesheet.primary} !important; } .btn-link:hover { color: #{Stylesheet.primary_dark} !important; } a { color: #{Stylesheet.primary}; } a:hover, a:focus { color: #{Stylesheet.primary_dark}; } h2, h3, h5 { color: #{Stylesheet.primary}; } h5:after { background-color: #{Stylesheet.primary}; } - .bg-yellow { background-color: #{Stylesheet.secondary} !important; } - .event:hover { background-color: #{Stylesheet.primary}; } + .bg-yellow { background-color: #{Stylesheet.secondary} !important; color: #{Stylesheet.secondary_text_color}; } + .event:hover { background-color: #{Stylesheet.primary}; color: #{Stylesheet.secondary_text_color}; } .widget h3 { color: #{Stylesheet.primary}; } .modal-header h1, .custom-invoice .modal-header h1 { color: #{Stylesheet.primary}; } - .block-link:hover, .fc-toolbar .fc-button:hover, .fc-toolbar .fc-button:active, .fc-toolbar .fc-button.fc-state-active { background-color: #{Stylesheet.secondary}; } + .block-link:hover, .fc-toolbar .fc-button:hover, .fc-toolbar .fc-button:active, .fc-toolbar .fc-button.fc-state-active { background-color: #{Stylesheet.secondary}; color: #{Stylesheet.secondary_text_color} !important; } + .block-link:hover .user-name { color: #{Stylesheet.secondary_text_color} !important; } .carousel-control:hover, .carousel-control:focus, .carousel-caption .title a:hover { color: #{Stylesheet.secondary}; } - .well.well-warning { border-color: #{Stylesheet.secondary}; background-color: #{Stylesheet.secondary}; } + .well.well-warning { border-color: #{Stylesheet.secondary}; background-color: #{Stylesheet.secondary}; color: #{Stylesheet.secondary_text_color}; } .text-yellow { color: #{Stylesheet.secondary} !important; } .red { color: #{Stylesheet.primary} !important; } - .btn-warning, .editable-buttons button[type=submit].btn-primary { background-color: #{Stylesheet.secondary} !important; border-color: #{Stylesheet.secondary} !important; } - .btn-warning:hover, .editable-buttons button[type=submit].btn-primary:hover, .btn-warning:focus, .editable-buttons button[type=submit].btn-primary:focus, .btn-warning.focus, .editable-buttons button.focus[type=submit].btn-primary, .btn-warning:active, .editable-buttons button[type=submit].btn-primary:active, .btn-warning.active, .editable-buttons button.active[type=submit].btn-primary, .open > .btn-warning.dropdown-toggle, .editable-buttons .open > button.dropdown-toggle[type=submit].btn-primary { background-color: #{Stylesheet.secondary_dark} !important; border-color: #{Stylesheet.secondary_dark} !important; } - .btn-warning-full { border-color: #{Stylesheet.secondary}; background-color: #{Stylesheet.secondary}; } - .heading .heading-btn a:hover { background-color: #{Stylesheet.secondary}; } + .btn-warning, .editable-buttons button[type=submit].btn-primary { background-color: #{Stylesheet.secondary} !important; border-color: #{Stylesheet.secondary} !important; color: #{Stylesheet.secondary_text_color}; } + .btn-warning:hover, .editable-buttons button[type=submit].btn-primary:hover, .btn-warning:focus, .editable-buttons button[type=submit].btn-primary:focus, .btn-warning.focus, .editable-buttons button.focus[type=submit].btn-primary, .btn-warning:active, .editable-buttons button[type=submit].btn-primary:active, .btn-warning.active, .editable-buttons button.active[type=submit].btn-primary, .open > .btn-warning.dropdown-toggle, .editable-buttons .open > button.dropdown-toggle[type=submit].btn-primary { background-color: #{Stylesheet.secondary_dark} !important; border-color: #{Stylesheet.secondary_dark} !important; color: #{Stylesheet.secondary_text_color}; } + .btn-warning-full { border-color: #{Stylesheet.secondary}; background-color: #{Stylesheet.secondary}; color: #{Stylesheet.secondary_text_color} !important; } + .heading .heading-btn a:hover { background-color: #{Stylesheet.secondary}; color: #{Stylesheet.secondary_text_color}; } .pricing-panel .content .wrap { border-color: #{Stylesheet.secondary}; } - .pricing-panel .cta-button .btn:hover, .pricing-panel .cta-button .custom-invoice .modal-body .elements li:hover, .custom-invoice .modal-body .elements .pricing-panel .cta-button li:hover { background-color: #{Stylesheet.secondary} !important; } + .pricing-panel .cta-button .btn:hover, .pricing-panel .cta-button .custom-invoice .modal-body .elements li:hover, .custom-invoice .modal-body .elements .pricing-panel .cta-button li:hover { background-color: #{Stylesheet.secondary} !important; color: #{Stylesheet.secondary_text_color}; } a.label:hover, .form-control.form-control-ui-select .select2-choices a.select2-search-choice:hover, a.label:focus, .form-control.form-control-ui-select .select2-choices a.select2-search-choice:focus { color: #{Stylesheet.primary}; } .about-picture { background: linear-gradient( rgba(255,255,255,0.12), rgba(255,255,255,0.13) ), linear-gradient( #{Stylesheet.primary_with_alpha(0.78)}, #{Stylesheet.primary_with_alpha(0.82)} ), url('/about-fablab.jpg') no-repeat; } - .social-icons > div:hover { background-color: #{Stylesheet.secondary}; } + .social-icons > div:hover { background-color: #{Stylesheet.secondary}; color: #{Stylesheet.secondary_text_color}; } .profile-top { background: linear-gradient( rgba(255,255,255,0.12), rgba(255,255,255,0.13) ), linear-gradient(#{Stylesheet.primary_with_alpha(0.78)}, #{Stylesheet.primary_with_alpha(0.82)} ), url('#{CustomAsset.get_url('profile-image-file') || '/about-fablab.jpg'}') no-repeat; } - .profile-top .social-links a:hover { background-color: #{Stylesheet.secondary} !important; border-color: #{Stylesheet.secondary} !important; } - section#cookies-modal div.cookies-consent .cookies-actions button.accept { background-color: #{Stylesheet.secondary}; } + .profile-top .social-links a:hover { background-color: #{Stylesheet.secondary} !important; border-color: #{Stylesheet.secondary} !important; color: #{Stylesheet.secondary_text_color}; } + section#cookies-modal div.cookies-consent .cookies-actions button.accept { background-color: #{Stylesheet.secondary}; color: #{Stylesheet.secondary_text_color}; } CSS end diff --git a/app/views/api/i_calendar/_i_calendar.json.jbuilder b/app/views/api/i_calendar/_i_calendar.json.jbuilder index dfa627cd3..248540c77 100644 --- a/app/views/api/i_calendar/_i_calendar.json.jbuilder +++ b/app/views/api/i_calendar/_i_calendar.json.jbuilder @@ -1,3 +1,3 @@ # frozen_string_literal: true -json.extract! i_cal, :id, :name, :url, :color, :text_color, :text_hidden +json.extract! i_cal, :id, :name, :url, :color, :primary_text_color, :text_hidden diff --git a/db/migrate/20191127153729_create_i_calendars.rb b/db/migrate/20191127153729_create_i_calendars.rb index e8bf543a5..f3cf21d19 100644 --- a/db/migrate/20191127153729_create_i_calendars.rb +++ b/db/migrate/20191127153729_create_i_calendars.rb @@ -8,7 +8,7 @@ class CreateICalendars < ActiveRecord::Migration[4.2] t.string :url t.string :name t.string :color - t.string :text_color + t.string :primary_text_color t.boolean :text_hidden t.timestamps null: false