Skip to content

Commit

Permalink
Merge pull request #12262 from ckeditor/ck/12067-button-tooltips-for-…
Browse files Browse the repository at this point in the history
…keyboard

Feature (ui): Implemented a TooltipManager class to manage UI tooltips across components and features. Closes #12067.

MINOR BREAKING CHANGE (ui): The TooltipView UI component has been removed, please use the new tooltip API instead. Please note that this change does not affect integrations that configure tooltips using ButtonView#tooltip property.

MINOR BREAKING CHANGE (ui): The static properties of BalloonPanelView have been renamed. BalloonPanelView.arrowVerticalOffset is heightOffset and BalloonPanelView.arrowHorizontalOffset is sideOffset.
  • Loading branch information
arkflpc authored Aug 22, 2022
2 parents 80440eb + 04288fa commit 1acdf50
Show file tree
Hide file tree
Showing 35 changed files with 1,835 additions and 641 deletions.
10 changes: 10 additions & 0 deletions packages/ckeditor5-core/src/editor/editorui.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import ComponentFactory from '@ckeditor/ckeditor5-ui/src/componentfactory';
import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
import TooltipManager from '@ckeditor/ckeditor5-ui/src/tooltipmanager';

import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
import mix from '@ckeditor/ckeditor5-utils/src/mix';
Expand Down Expand Up @@ -54,6 +55,14 @@ export default class EditorUI {
*/
this.focusTracker = new FocusTracker();

/**
* Manages the tooltips displayed on mouseover and focus across the UI.
*
* @readonly
* @member {module:ui/tooltipmanager~TooltipManager}
*/
this.tooltipManager = new TooltipManager( editor );

/**
* Stores viewport offsets from every direction.
*
Expand Down Expand Up @@ -157,6 +166,7 @@ export default class EditorUI {
this.stopListening();

this.focusTracker.destroy();
this.tooltipManager.destroy( this.editor );

// Clean–up the references to the CKEditor instance stored in the native editable DOM elements.
for ( const domElement of this._editableElementsMap.values() ) {
Expand Down
24 changes: 23 additions & 1 deletion packages/ckeditor5-core/tests/editor/editorui.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import EditorUI from '../../src/editor/editorui';
import Editor from '../../src/editor/editor';

import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
import ComponentFactory from '@ckeditor/ckeditor5-ui/src/componentfactory';
import ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';
import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
import TooltipManager from '@ckeditor/ckeditor5-ui/src/tooltipmanager';

import testUtils from '../_utils/utils';

Expand Down Expand Up @@ -42,6 +43,10 @@ describe( 'EditorUI', () => {
expect( ui.focusTracker ).to.be.instanceOf( FocusTracker );
} );

it( 'should create #tooltipManager', () => {
expect( ui.tooltipManager ).to.be.instanceOf( TooltipManager );
} );

it( 'should have #element getter', () => {
expect( ui.element ).to.null;
} );
Expand Down Expand Up @@ -121,6 +126,23 @@ describe( 'EditorUI', () => {
expect( fooElement.ckeditorInstance ).to.be.null;
expect( barElement.ckeditorInstance ).to.be.null;
} );

it( 'should destroy #focusTracker', () => {
const destroySpy = sinon.spy( ui.focusTracker, 'destroy' );

ui.destroy();

sinon.assert.calledOnce( destroySpy );
} );

it( 'should destroy #tooltipManager', () => {
const destroySpy = sinon.spy( ui.tooltipManager, 'destroy' );

ui.destroy();

sinon.assert.calledOnce( destroySpy );
sinon.assert.calledWithExactly( destroySpy, editor );
} );
} );

describe( 'setEditableElement()', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,6 @@ The HTML structure of every non-previewable media in the editor is as follows:
</div>
<a class="ck-media__placeholder__url" target="new" href="[ URL of the media]">
<span class="ck-media__placeholder__url__text">[ URL of the media]</span>
<span class="ck ck-tooltip ck-tooltip_s">...</span>
</a>
</div>
</div>
Expand Down
13 changes: 6 additions & 7 deletions packages/ckeditor5-media-embed/src/mediaregistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @module media-embed/mediaregistry
*/

import { TooltipView, IconView, Template } from 'ckeditor5/src/ui';
import { IconView, Template } from 'ckeditor5/src/ui';
import { logWarning, toArray } from 'ckeditor5/src/utils';

import mediaPlaceholderIcon from '../theme/icons/media-placeholder.svg';
Expand Down Expand Up @@ -185,7 +185,7 @@ class Media {
* @see module:utils/locale~Locale#t
* @method
*/
this._t = locale.t;
this._locale = locale;

/**
* The output of the `RegExp.match` which validated the {@link #url} of this media.
Expand Down Expand Up @@ -271,10 +271,9 @@ class Media {
* @returns {String}
*/
_getPlaceholderHtml() {
const tooltip = new TooltipView();
const icon = new IconView();
const t = this._locale.t;

tooltip.text = this._t( 'Open media in new tab' );
icon.content = mediaPlaceholderIcon;
icon.viewBox = mediaPlaceholderIconViewBox;

Expand All @@ -297,7 +296,8 @@ class Media {
class: 'ck-media__placeholder__url',
target: '_blank',
rel: 'noopener noreferrer',
href: this.url
href: this.url,
'data-cke-tooltip-text': t( 'Open media in new tab' )
},
children: [
{
Expand All @@ -306,8 +306,7 @@ class Media {
class: 'ck-media__placeholder__url__text'
},
children: [ this.url ]
},
tooltip
}
]
}
]
Expand Down
13 changes: 8 additions & 5 deletions packages/ckeditor5-media-embed/tests/mediaembedediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -1272,11 +1272,14 @@ describe( 'MediaEmbedEditing', () => {
'<div[^>]+>' +
'<div class="ck ck-media__placeholder ck-reset_all">' +
'<div class="ck-media__placeholder__icon">.*</div>' +
`<a class="ck-media__placeholder__url" href="${ expectedUrl }" rel="noopener noreferrer" target="_blank">` +
`<span class="ck-media__placeholder__url__text">${ expectedUrl }</span>` +
'<span class="ck ck-tooltip ck-tooltip_s">' +
'<span class="ck ck-tooltip__text">Open media in new tab</span>' +
'</span>' +
'<a ' +
'class="ck-media__placeholder__url" ' +
'data-cke-tooltip-text="Open media in new tab" ' +
`href="${ expectedUrl }" ` +
'rel="noopener noreferrer" ' +
'target="_blank"' +
'>' +
`<span class="ck-media__placeholder__url__text">${ expectedUrl }</span>` +
'</a>' +
'</div>' +
'</div>' +
Expand Down
8 changes: 0 additions & 8 deletions packages/ckeditor5-media-embed/theme/mediaembedediting.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,18 @@
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

@import "@ckeditor/ckeditor5-ui/theme/components/tooltip/mixins/_tooltip.css";

.ck-media__wrapper {
& .ck-media__placeholder {
display: flex;
flex-direction: column;
align-items: center;

& .ck-media__placeholder__url {
@mixin ck-tooltip_enabled;

/* Otherwise the URL will overflow when the content is very narrow. */
max-width: 100%;

position: relative;

&:hover {
@mixin ck-tooltip_visible;
}

& .ck-media__placeholder__url__text {
overflow: hidden;
display: block;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

@import "@ckeditor/ckeditor5-ui/theme/components/tooltip/mixins/_tooltip.css";
@import "@ckeditor/ckeditor5-ui/theme/mixins/_unselectable.css";
@import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";
@import "../mixins/_focus.css";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
@import "../../../mixins/_shadow.css";

:root {
--ck-balloon-border-width: 1px;
--ck-balloon-arrow-offset: 2px;
--ck-balloon-arrow-height: 10px;
--ck-balloon-arrow-half-width: 8px;
Expand All @@ -20,7 +21,7 @@
min-height: 15px;

background: var(--ck-color-panel-background);
border: 1px solid var(--ck-color-panel-border);
border: var(--ck-balloon-border-width) solid var(--ck-color-panel-border);

&.ck-balloon-panel_with-arrow {
&::before,
Expand All @@ -39,11 +40,12 @@

&::before {
border-color: transparent transparent var(--ck-color-panel-border) transparent;
margin-top: calc( -1 * var(--ck-balloon-border-width) );
}

&::after {
border-color: transparent transparent var(--ck-color-panel-background) transparent;
margin-top: var(--ck-balloon-arrow-offset);
margin-top: calc( var(--ck-balloon-arrow-offset) - var(--ck-balloon-border-width) );
}
}

Expand All @@ -56,11 +58,46 @@
&::before {
border-color: var(--ck-color-panel-border) transparent transparent;
filter: drop-shadow(var(--ck-balloon-arrow-drop-shadow));
margin-bottom: calc( -1 * var(--ck-balloon-border-width) );
}

&::after {
border-color: var(--ck-color-panel-background) transparent transparent transparent;
margin-bottom: var(--ck-balloon-arrow-offset);
margin-bottom: calc( var(--ck-balloon-arrow-offset) - var(--ck-balloon-border-width) );
}
}

&[class*="arrow_e"] {
&::before,
&::after {
border-width: var(--ck-balloon-arrow-half-width) 0 var(--ck-balloon-arrow-half-width) var(--ck-balloon-arrow-height);
}

&::before {
border-color: transparent transparent transparent var(--ck-color-panel-border);
margin-right: calc( -1 * var(--ck-balloon-border-width) );
}

&::after {
border-color: transparent transparent transparent var(--ck-color-panel-background);
margin-right: calc( var(--ck-balloon-arrow-offset) - var(--ck-balloon-border-width) );
}
}

&[class*="arrow_w"] {
&::before,
&::after {
border-width: var(--ck-balloon-arrow-half-width) var(--ck-balloon-arrow-height) var(--ck-balloon-arrow-half-width) 0;
}

&::before {
border-color: transparent var(--ck-color-panel-border) transparent transparent;
margin-left: calc( -1 * var(--ck-balloon-border-width) );
}

&::after {
border-color: transparent var(--ck-color-panel-background) transparent transparent;
margin-left: calc( var(--ck-balloon-arrow-offset) - var(--ck-balloon-border-width) );
}
}

Expand Down Expand Up @@ -149,4 +186,22 @@
top: calc(-1 * var(--ck-balloon-arrow-height));
}
}

&.ck-balloon-panel_arrow_e {
&::before,
&::after {
right: calc(-1 * var(--ck-balloon-arrow-height));
margin-top: calc(-1 * var(--ck-balloon-arrow-half-width));
top: 50%;
}
}

&.ck-balloon-panel_arrow_w {
&::before,
&::after {
left: calc(-1 * var(--ck-balloon-arrow-height));
margin-top: calc(-1 * var(--ck-balloon-arrow-half-width));
top: 50%;
}
}
}
Loading

0 comments on commit 1acdf50

Please sign in to comment.