Apply darker course colors for high contrast UI

fixes: LS-2854
flag=high_contrast_course_colors

test plan:

- Create a user

- Enable High Contrast UI on their account.

- Navigate to calendar, course list and dashboard.

- Create a course for you, and right after, visit the calendar,
so the calendar flow defines a color for the course

- Create another course and got straight to the dashboard,
so the dashboard flow defines a color for that course

- Define a custom hash for a third course

- Check the colors on the course list, calendar and dashboard

- Enable the High Contrast Course Colors

- Check that all the colors now have a contrast ratio of at least 4.5:1

Change-Id: Idd5d4475acceb4742a29938237b88b0d403de611
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/279764
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Product-Review: Luis Oliveira <luis.oliveira@instructure.com>
Reviewed-by: Robin Kuss <rkuss@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
This commit is contained in:
Luis Oliveira 2021-11-29 23:34:05 -03:00
parent 129f6c2225
commit 4d95fa28db
5 changed files with 53 additions and 4 deletions

View File

@ -139,6 +139,7 @@ gem "simple_oauth", "0.3.1", require: false
gem "twilio-ruby", "5.36.0", require: false gem "twilio-ruby", "5.36.0", require: false
gem "vault", "0.15.0", require: false gem "vault", "0.15.0", require: false
gem "vericite_api", "1.5.3" gem "vericite_api", "1.5.3"
gem "wcag_color_contrast", "0.1.0"
gem "week_of_month", "1.2.5", gem "week_of_month", "1.2.5",
github: "instructure/week-of-month", ref: "b3013639e9474f302b5a6f27e4e45313e8d24902" github: "instructure/week-of-month", ref: "b3013639e9474f302b5a6f27e4e45313e8d24902"
gem "will_paginate", "3.3.0", require: false # required for folio-pagination gem "will_paginate", "3.3.0", require: false # required for folio-pagination

View File

@ -1602,6 +1602,15 @@ class User < ActiveRecord::Base
get_preference(:new_user_tutorial_statuses) || {} get_preference(:new_user_tutorial_statuses) || {}
end end
def apply_contrast(colors)
colors.each do |key, _v|
until WCAGColorContrast.ratio(colors[key].delete("#"), "ffffff") >= 4.5
rgb = colors[key].match(/^#(..)(..)(..)$/).captures.map { |c| (c.hex.to_i * 0.85).round }
colors[key] = "#%02x%02x%02x" % rgb
end
end
end
def custom_colors def custom_colors
colors_hash = get_preference(:custom_colors) || {} colors_hash = get_preference(:custom_colors) || {}
if Shard.current != shard if Shard.current != shard
@ -1615,6 +1624,9 @@ class User < ActiveRecord::Base
["#{opts.join("_")}_#{new_id}", value] ["#{opts.join("_")}_#{new_id}", value]
end.to_h end.to_h
end end
return apply_contrast colors_hash if prefers_high_contrast? && uses_high_contrast_course_colors?
colors_hash colors_hash
end end
@ -1716,6 +1728,10 @@ class User < ActiveRecord::Base
!!feature_enabled?(:high_contrast) !!feature_enabled?(:high_contrast)
end end
def uses_high_contrast_course_colors?
Account.site_admin.feature_enabled?(:high_contrast_course_colors)
end
def auto_show_cc? def auto_show_cc?
!!feature_enabled?(:auto_show_cc) !!feature_enabled?(:auto_show_cc)
end end

View File

@ -177,6 +177,14 @@ high_contrast:
High Contrast enhances the color contrast of the UI (text, buttons, etc.), making those items more High Contrast enhances the color contrast of the UI (text, buttons, etc.), making those items more
distinct and easier to identify. Note: Institution branding will be disabled. distinct and easier to identify. Note: Institution branding will be disabled.
applies_to: User applies_to: User
high_contrast_course_colors:
state: allowed
display_name: High Contrast Course Colors
description:
high_contrast_course_colors_description: |-
High Contrast Course Colors darkens system provided and color picker course colors
(not manually defined ones) to improve contrast ratio
applies_to: SiteAdmin
important_dates: important_dates:
state: hidden state: hidden
display_name: Important Dates display_name: Important Dates

View File

@ -3606,6 +3606,33 @@ describe User do
end end
end end
describe "#custom_colors" do
context "user has high_contrast and high_contrast_course_colors enables" do
let(:user) { user_model }
before do
user.enable_feature!(:high_contrast)
Account.site_admin.enable_feature!(:high_contrast_course_colors)
end
it "sufficiently darkens colors with a contrast below 4.5" do
user.preferences[:custom_colors] = {
user_1: "#5a92de",
course_1: "#199eb7",
course_2: "#ffffff",
course_3: "#c8c8c8",
course_4: "#767777"
}
expect(user.custom_colors.map { |_k, v| WCAGColorContrast.ratio(v.delete("#"), "ffffff") }).to all(be >= 4.5)
end
it "leaves colors with enough contrast alone" do
user.preferences[:custom_colors] = { user_1: "#757777" }
expect(user.custom_colors[:user_1]).to be("#757777")
end
end
end
describe "#prefers_no_celebrations?" do describe "#prefers_no_celebrations?" do
let(:user) { user_model } let(:user) { user_model }

View File

@ -1024,10 +1024,7 @@ export default class Calendar {
// Get any custom colors that have been set // Get any custom colors that have been set
$.getJSON(`/api/v1/users/${this.options.userId}/colors/`, data => { $.getJSON(`/api/v1/users/${this.options.userId}/colors/`, data => {
const customColors = data.custom_colors const customColors = data.custom_colors
const colors = colorSlicer.getColors(this.contextCodes.length, 275, { const colors = colorSlicer.getColors(this.contextCodes.length, 275)
unsafe: !ENV.use_high_contrast
})
const newCustomColors = {} const newCustomColors = {}
const html = this.contextCodes const html = this.contextCodes
.map((contextCode, index) => { .map((contextCode, index) => {