Skip to content

Commit

Permalink
Improved placeholders and font color grids in high contrast mode (#16284
Browse files Browse the repository at this point in the history
)

Feature (utils): Implemented the `env#isMediaForcedColors` property for forced colors detection (e.g. high contrast mode on Windows). See #14907.

Feature (ui): Implemented `ck-media-forced-colors` and `ck-media-default-colors` mixins for detecting forced colors (e.g. high contrast mode on Windows). See #14907.

Fix (theme-lark): The caret should be visible in a placeholder while in forced colors mode (e.g. high contrast mode on Windows). Improved the look of the placeholders in the forced colors mode. Closes #14907.

Fix (theme-lark): The color grid component should render as a grid of labels in the forced colors mode (e.g. high contrast mode on Windows). Closes #14907.
  • Loading branch information
oleq authored May 7, 2024
1 parent 67d2d60 commit 15cbe77
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 37 deletions.
12 changes: 11 additions & 1 deletion packages/ckeditor5-image/theme/imagecaption.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

@import "@ckeditor/ckeditor5-ui/theme/mixins/_mediacolors.css";

:root {
--ck-color-image-caption-background: hsl(0, 0%, 97%);
--ck-color-image-caption-text: hsl(0, 0%, 20%);
Expand All @@ -19,11 +21,19 @@
padding: .6em;
font-size: .75em;
outline-offset: -1px;

/* Improve placeholder rendering in high-constrast mode (https://github.com/ckeditor/ckeditor5/issues/14907). */
@media (forced-colors: active) {
background-color: unset;
color: unset;
}
}

/* Editing styles */
.ck.ck-editor__editable .image > figcaption.image__caption_highlighted {
animation: ck-image-caption-highlight .6s ease-out;
@mixin ck-media-default-colors {
animation: ck-image-caption-highlight .6s ease-out;
}

@media (prefers-reduced-motion: reduce) {
animation: none;
Expand Down
2 changes: 1 addition & 1 deletion packages/ckeditor5-table/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"main": "src/index.ts",
"dependencies": {
"ckeditor5": "41.3.1",
"@ckeditor/ckeditor5-ui": "41.3.1",
"lodash-es": "4.17.21"
},
"devDependencies": {
Expand All @@ -36,7 +37,6 @@
"@ckeditor/ckeditor5-paragraph": "41.3.1",
"@ckeditor/ckeditor5-theme-lark": "41.3.1",
"@ckeditor/ckeditor5-typing": "41.3.1",
"@ckeditor/ckeditor5-ui": "41.3.1",
"@ckeditor/ckeditor5-undo": "41.3.1",
"@ckeditor/ckeditor5-utils": "41.3.1",
"@ckeditor/ckeditor5-widget": "41.3.1",
Expand Down
14 changes: 12 additions & 2 deletions packages/ckeditor5-table/theme/tablecaption.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

@import "@ckeditor/ckeditor5-ui/theme/mixins/_mediacolors.css";

:root {
--ck-color-selector-caption-background: hsl(0, 0%, 97%);
--ck-color-selector-caption-text: hsl(0, 0%, 20%);
Expand All @@ -20,12 +22,20 @@
padding: .6em;
font-size: .75em;
outline-offset: -1px;

/* Improve placeholder rendering in high-constrast mode (https://github.com/ckeditor/ckeditor5/issues/14907). */
@mixin ck-media-forced-colors {
background-color: unset;
color: unset;
}
}

/* Editing styles */
.ck.ck-editor__editable .table > figcaption {
&.table__caption_highlighted {
animation: ck-table-caption-highlight .6s ease-out;
@mixin ck-media-default-colors {
&.table__caption_highlighted {
animation: ck-table-caption-highlight .6s ease-out;
}
}

&.ck-placeholder::before {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,37 @@
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

@import "@ckeditor/ckeditor5-ui/theme/mixins/_mediacolors.css";

/* See ckeditor/ckeditor5#936. */
.ck.ck-placeholder, .ck .ck-placeholder {
@mixin ck-media-forced-colors {
/*
* This is needed for Edge on Windows to use the right color for the placeholder content (::before).
* See https://github.com/ckeditor/ckeditor5/issues/14907.
*/
forced-color-adjust: preserve-parent-color;
}

&::before {
cursor: text;
color: var(--ck-color-engine-placeholder-text);

@mixin ck-media-default-colors {
color: var(--ck-color-engine-placeholder-text);
}

@mixin ck-media-forced-colors {
/*
* In the high contrast mode there is no telling between regular and placeholder text. Using
* italic text to address that issue. See https://github.com/ckeditor/ckeditor5/issues/14907.
*/
font-style: italic;

/*
* Without this margin, the caret will not show up and blink when the user puts the selection
* in the placeholder (Edge on Windows). See https://github.com/ckeditor/ckeditor5/issues/14907.
*/
margin-left: 1px;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

@import "../../../mixins/_rounded.css";
@import "@ckeditor/ckeditor5-ui/theme/mixins/_mediacolors.css";

:root {
--ck-color-grid-tile-size: 24px;
Expand All @@ -20,13 +21,52 @@
}

.ck.ck-color-grid__tile {
width: var(--ck-color-grid-tile-size);
height: var(--ck-color-grid-tile-size);
min-width: var(--ck-color-grid-tile-size);
min-height: var(--ck-color-grid-tile-size);
padding: 0;
transition: .2s ease box-shadow;
border: 0;

@mixin ck-media-default-colors {
width: var(--ck-color-grid-tile-size);
height: var(--ck-color-grid-tile-size);
min-width: var(--ck-color-grid-tile-size);
min-height: var(--ck-color-grid-tile-size);
padding: 0;
border: 0;

&.ck-on,
&:focus:not( .ck-disabled ),
&:hover:not( .ck-disabled ) {
/* Disable the default .ck-button's border ring. */
border: 0;
}

&.ck-color-selector__color-tile_bordered {
box-shadow: 0 0 0 1px var(--ck-color-base-border);
}

&.ck-on {
box-shadow: inset 0 0 0 1px var(--ck-color-base-background), 0 0 0 2px var(--ck-color-base-text);
}

&:focus:not( .ck-disabled ),
&:hover:not( .ck-disabled ) {
box-shadow: inset 0 0 0 1px var(--ck-color-base-background), 0 0 0 2px var(--ck-color-focus-border);
}
}

/*
* In high contrast mode, the colors are replaced with text labels.
* See https://github.com/ckeditor/ckeditor5/issues/14907.
*/
@mixin ck-media-forced-colors {
width: unset;
height: unset;
min-width: unset;
min-height: unset;
padding: 0 var(--ck-spacing-small);

& .ck-button__label {
display: inline-block;
}
}

@media (prefers-reduced-motion: reduce) {
transition: none;
Expand All @@ -37,34 +77,16 @@
transition: unset;
}

&.ck-color-selector__color-tile_bordered {
box-shadow: 0 0 0 1px var(--ck-color-base-border);
}

& .ck.ck-icon {
display: none;
color: var(--ck-color-color-grid-check-icon);
}

&.ck-on {
box-shadow: inset 0 0 0 1px var(--ck-color-base-background), 0 0 0 2px var(--ck-color-base-text);

& .ck.ck-icon {
display: block;
}
}

&.ck-on,
&:focus:not( .ck-disabled ),
&:hover:not( .ck-disabled ) {
/* Disable the default .ck-button's border ring. */
border: 0;
}

&:focus:not( .ck-disabled ),
&:hover:not( .ck-disabled ) {
box-shadow: inset 0 0 0 1px var(--ck-color-base-background), 0 0 0 2px var(--ck-color-focus-border);
}
}

.ck.ck-color-grid__label {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

@import "../mixins/_focus.css";
@import "../mixins/_shadow.css";
@import "@ckeditor/ckeditor5-ui/theme/mixins/_mediacolors.css";

:root {
--ck-widget-outline-thickness: 3px;
Expand Down Expand Up @@ -47,8 +48,9 @@
&:focus {
@mixin ck-focus-ring;
@mixin ck-box-shadow var(--ck-inner-shadow);

background-color: var(--ck-color-widget-editable-focus-background);
@mixin ck-media-default-colors {
background-color: var(--ck-color-widget-editable-focus-background);
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions packages/ckeditor5-ui/src/colorgrid/colortileview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import ButtonView from '../button/buttonview.js';

import type { Locale } from '@ckeditor/ckeditor5-utils';
import { env, type Locale } from '@ckeditor/ckeditor5-utils';

import checkIcon from '../../theme/icons/color-tile-check.svg';

Expand Down Expand Up @@ -41,7 +41,8 @@ export default class ColorTileView extends ButtonView {
this.extendTemplate( {
attributes: {
style: {
backgroundColor: bind.to( 'color' )
// https://github.com/ckeditor/ckeditor5/issues/14907
backgroundColor: bind.to( 'color', color => env.isMediaForcedColors ? null : color )
},
class: [
'ck',
Expand Down
28 changes: 25 additions & 3 deletions packages/ckeditor5-ui/tests/colorgrid/colortileview.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,28 @@
import ColorTileView from '../../src/colorgrid/colortileview.js';
import ButtonView from '../../src/button/buttonview.js';
import checkIcon from '../../theme/icons/color-tile-check.svg';
import { env } from '@ckeditor/ckeditor5-utils';

import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils.js';

describe( 'ColorTileView', () => {
let colorTile;

testUtils.createSinonSandbox();

beforeEach( () => {
colorTile = new ColorTileView();
} );

afterEach( () => {
colorTile.destroy();
} );

it( 'inherits from ButtonView', () => {
expect( new ColorTileView() ).to.be.instanceOf( ButtonView );
expect( colorTile ).to.be.instanceOf( ButtonView );
} );

it( 'has proper attributes and classes', () => {
const colorTile = new ColorTileView();
colorTile.render();

expect( colorTile.color ).to.be.undefined;
Expand All @@ -29,8 +43,16 @@ describe( 'ColorTileView', () => {
expect( colorTile.element.classList.contains( 'ck-color-selector__color-tile_bordered' ) ).to.be.true;
} );

// https://github.com/ckeditor/ckeditor5/issues/14907
it( 'should not set the background-color in the forced-colors mode for a better UX (displaying a label instead)', () => {
testUtils.sinon.stub( env, 'isMediaForcedColors' ).value( true );

colorTile.render();

expect( colorTile.element.style.backgroundColor ).to.equal( '' );
} );

it( 'has a check icon', () => {
const colorTile = new ColorTileView();
colorTile.render();

expect( colorTile.icon ).to.equal( checkIcon );
Expand Down
20 changes: 20 additions & 0 deletions packages/ckeditor5-ui/theme/mixins/_mediacolors.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

@define-mixin ck-media-forced-colors {
@media (forced-colors: active) {
& {
@mixin-content;
}
}
}

@define-mixin ck-media-default-colors {
@media (forced-colors: none) {
& {
@mixin-content;
}
}
}
14 changes: 14 additions & 0 deletions packages/ckeditor5-utils/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ export interface EnvType {
*/
readonly isBlink: boolean;

/**
* Indicates that the the user agent has enabled a forced colors mode (e.g. Windows High Contrast mode).
*/
readonly isMediaForcedColors: boolean;

/**
* Indicates that "prefer reduced motion" browser setting is active.
*/
Expand Down Expand Up @@ -104,6 +109,8 @@ const env: EnvType = {

isBlink: isBlink( userAgent ),

isMediaForcedColors: isMediaForcedColors(),

get isMotionReduced() {
return isMotionReduced();
},
Expand Down Expand Up @@ -209,6 +216,13 @@ export function isRegExpUnicodePropertySupported(): boolean {
return isSupported;
}

/**
* Checks if the user agent has enabled a forced colors mode (e.g. Windows High Contrast mode).
*/
export function isMediaForcedColors(): boolean {
return window.matchMedia( '(forced-colors: active)' ).matches;
}

/**
* Checks if user enabled "prefers reduced motion" setting in browser.
*/
Expand Down
Loading

0 comments on commit 15cbe77

Please sign in to comment.