浏览代码

Merge pull request #362 from ckeditor/t/ckeditor5/645

Feature: Updated UI components to bring the support for the refreshed Lark theme (see ckeditor/ckeditor5#645).

BREAKING CHANGE: The DOM structure of the dropdown component has changed. Please refer to the documentation to find out more.

BREAKING CHANGE: Basic properties of the balloon panel component have changed (i.e. the location of the arrow, the default positions), which may have an impact on existing integrations.
Piotrek Koszuliński 7 年之前
父节点
当前提交
d4cf2957cb

+ 18 - 0
packages/ckeditor5-ui/src/dropdown/dropdownview.js

@@ -8,8 +8,10 @@
  */
 
 import View from '../view';
+import IconView from '../icon/iconview';
 import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
 import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';
+import dropdownArrowIcon from '../../theme/icons/dropdown-arrow.svg';
 
 import '../../theme/components/dropdown/dropdown.css';
 
@@ -108,6 +110,14 @@ export default class DropdownView extends View {
 		 */
 		this.keystrokes = new KeystrokeHandler();
 
+		/**
+		 * The arrow icon of the dropdown.
+		 *
+		 * @readonly
+		 * @member {module:ui/icon/iconview~IconView} #arrowView
+		 */
+		const arrowView = this.arrowView = new IconView();
+
 		this.setTemplate( {
 			tag: 'div',
 
@@ -120,10 +130,18 @@ export default class DropdownView extends View {
 
 			children: [
 				buttonView,
+				arrowView,
 				panelView
 			]
 		} );
 
+		arrowView.content = dropdownArrowIcon;
+		arrowView.extendTemplate( {
+			attributes: {
+				class: 'ck-dropdown__arrow'
+			}
+		} );
+
 		buttonView.extendTemplate( {
 			attributes: {
 				class: [

+ 1 - 0
packages/ckeditor5-ui/src/labeledinput/labeledinputview.js

@@ -73,6 +73,7 @@ export default class LabeledInputView extends View {
 			tag: 'div',
 			attributes: {
 				class: [
+					'ck-labeled-input',
 					bind.if( 'isReadOnly', 'ck-disabled' )
 				]
 			},

+ 4 - 2
packages/ckeditor5-ui/src/panel/balloon/balloonpanelview.js

@@ -222,8 +222,10 @@ export default class BalloonPanelView extends View {
 		const positionOptions = Object.assign( {}, {
 			element: this.element,
 			positions: [
+				defaultPositions.southArrowNorth,
 				defaultPositions.southArrowNorthWest,
 				defaultPositions.southArrowNorthEast,
+				defaultPositions.northArrowSouth,
 				defaultPositions.northArrowSouthWest,
 				defaultPositions.northArrowSouthEast
 			],
@@ -391,7 +393,7 @@ function getDomElement( object ) {
  * @default 30
  * @member {Number} module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowHorizontalOffset
  */
-BalloonPanelView.arrowHorizontalOffset = 30;
+BalloonPanelView.arrowHorizontalOffset = 25;
 
 /**
  * A vertical offset of the arrow from the edge of the balloon. Controlled by CSS.
@@ -410,7 +412,7 @@ BalloonPanelView.arrowHorizontalOffset = 30;
  * @default 15
  * @member {Number} module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowVerticalOffset
  */
-BalloonPanelView.arrowVerticalOffset = 15;
+BalloonPanelView.arrowVerticalOffset = 10;
 
 /**
  * A default set of positioning functions used by the balloon panel view

+ 10 - 2
packages/ckeditor5-ui/tests/dropdown/dropdownview.js

@@ -8,6 +8,7 @@ import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';
 import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
 import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
 import ButtonView from '../../src/button/buttonview';
+import IconView from '../../src/icon/iconview';
 import DropdownPanelView from '../../src/dropdown/dropdownpanelview';
 
 describe( 'DropdownView', () => {
@@ -54,14 +55,21 @@ describe( 'DropdownView', () => {
 
 		it( 'creates #element from template', () => {
 			expect( view.element.classList.contains( 'ck-dropdown' ) ).to.be.true;
-			expect( view.element.firstChild ).to.equal( buttonView.element );
-			expect( view.element.lastChild ).to.equal( panelView.element );
+			expect( view.element.children ).to.have.length( 3 );
+			expect( view.element.children[ 0 ] ).to.equal( buttonView.element );
+			expect( view.element.children[ 1 ] ).to.equal( view.arrowView.element );
+			expect( view.element.children[ 2 ] ).to.equal( panelView.element );
 		} );
 
 		it( 'sets view#buttonView class', () => {
 			expect( view.buttonView.element.classList.contains( 'ck-dropdown__button' ) ).to.be.true;
 		} );
 
+		it( 'creates #arrowView icon instance', () => {
+			expect( view.arrowView ).to.be.instanceOf( IconView );
+			expect( view.arrowView.element.classList.contains( 'ck-dropdown__arrow' ) );
+		} );
+
 		describe( 'bindings', () => {
 			describe( 'view#isOpen to view.buttonView#execute', () => {
 				it( 'is activated', () => {

+ 4 - 0
packages/ckeditor5-ui/tests/labeledinput/labeledinputview.js

@@ -37,6 +37,10 @@ describe( 'LabeledInputView', () => {
 	} );
 
 	describe( 'template', () => {
+		it( 'should have the CSS class', () => {
+			expect( view.element.classList.contains( 'ck-labeled-input' ) ).to.be.true;
+		} );
+
 		it( 'should have label view', () => {
 			expect( view.template.children[ 0 ] ).to.equal( view.labelView );
 		} );

+ 40 - 36
packages/ckeditor5-ui/tests/panel/balloon/balloonpanelview.js

@@ -180,8 +180,10 @@ describe( 'BalloonPanelView', () => {
 				element: view.element,
 				target,
 				positions: [
+					BalloonPanelView.defaultPositions.southArrowNorth,
 					BalloonPanelView.defaultPositions.southArrowNorthWest,
 					BalloonPanelView.defaultPositions.southArrowNorthEast,
+					BalloonPanelView.defaultPositions.northArrowSouth,
 					BalloonPanelView.defaultPositions.northArrowSouthWest,
 					BalloonPanelView.defaultPositions.northArrowSouthEast
 				],
@@ -212,7 +214,7 @@ describe( 'BalloonPanelView', () => {
 
 				view.attachTo( { target, limiter } );
 
-				expect( view.position ).to.equal( 'arrow_nw' );
+				expect( view.position ).to.equal( 'arrow_n' );
 			} );
 
 			it( 'should put balloon on the `south east` side of the target element when ' +
@@ -297,8 +299,8 @@ describe( 'BalloonPanelView', () => {
 
 				view.attachTo( { target, limiter } );
 
-				expect( view.top ).to.equal( 15 );
-				expect( view.left ).to.equal( -80 );
+				expect( view.top ).to.equal( BalloonPanelView.arrowVerticalOffset );
+				expect( view.left ).to.equal( -100 );
 
 				positionedAncestor.remove();
 			} );
@@ -322,8 +324,8 @@ describe( 'BalloonPanelView', () => {
 
 				view.attachTo( { target, limiter } );
 
-				expect( view.top ).to.equal( 115 );
-				expect( view.left ).to.equal( 20 );
+				expect( view.top ).to.equal( BalloonPanelView.arrowVerticalOffset + 100 );
+				expect( view.left ).to.equal( 0 );
 
 				positionedAncestor.remove();
 			} );
@@ -669,10 +671,12 @@ describe( 'BalloonPanelView', () => {
 	} );
 
 	describe( 'defaultPositions', () => {
-		let positions, balloonRect, targetRect;
+		let positions, balloonRect, targetRect, arrowHOffset, arrowVOffset;
 
 		beforeEach( () => {
 			positions = BalloonPanelView.defaultPositions;
+			arrowHOffset = BalloonPanelView.arrowHorizontalOffset;
+			arrowVOffset = BalloonPanelView.arrowVerticalOffset;
 
 			targetRect = {
 				top: 100,
@@ -701,7 +705,7 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "northArrowSouth" position', () => {
 			expect( positions.northArrowSouth( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 35,
+				top: 50 - arrowVOffset,
 				left: 125,
 				name: 'arrow_s'
 			} );
@@ -709,16 +713,16 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "northArrowSouthEast" position', () => {
 			expect( positions.northArrowSouthEast( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 35,
-				left: 130,
+				top: 50 - arrowVOffset,
+				left: 100 + arrowHOffset,
 				name: 'arrow_se'
 			} );
 		} );
 
 		it( 'should define the "northArrowSouthWest" position', () => {
 			expect( positions.northArrowSouthWest( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 35,
-				left: 120,
+				top: 50 - arrowVOffset,
+				left: 150 - arrowHOffset,
 				name: 'arrow_sw'
 			} );
 		} );
@@ -727,7 +731,7 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "northWestArrowSouth" position', () => {
 			expect( positions.northWestArrowSouth( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 35,
+				top: 50 - arrowVOffset,
 				left: 75,
 				name: 'arrow_s'
 			} );
@@ -735,16 +739,16 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "northWestArrowSouthWest" position', () => {
 			expect( positions.northWestArrowSouthWest( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 35,
-				left: 70,
+				top: 50 - arrowVOffset,
+				left: 100 - arrowHOffset,
 				name: 'arrow_sw'
 			} );
 		} );
 
 		it( 'should define the "northWestArrowSouthEast" position', () => {
 			expect( positions.northWestArrowSouthEast( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 35,
-				left: 80,
+				top: 50 - arrowVOffset,
+				left: 50 + arrowHOffset,
 				name: 'arrow_se'
 			} );
 		} );
@@ -753,7 +757,7 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "northEastArrowSouth" position', () => {
 			expect( positions.northEastArrowSouth( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 35,
+				top: 50 - arrowVOffset,
 				left: 175,
 				name: 'arrow_s'
 			} );
@@ -761,16 +765,16 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "northEastArrowSouthEast" position', () => {
 			expect( positions.northEastArrowSouthEast( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 35,
-				left: 180,
+				top: 50 - arrowVOffset,
+				left: 150 + arrowHOffset,
 				name: 'arrow_se'
 			} );
 		} );
 
 		it( 'should define the "northEastArrowSouthWest" position', () => {
 			expect( positions.northEastArrowSouthWest( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 35,
-				left: 170,
+				top: 50 - arrowVOffset,
+				left: 200 - arrowHOffset,
 				name: 'arrow_sw'
 			} );
 		} );
@@ -779,7 +783,7 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "southArrowNorth" position', () => {
 			expect( positions.southArrowNorth( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 215,
+				top: 200 + arrowVOffset,
 				left: 125,
 				name: 'arrow_n'
 			} );
@@ -787,16 +791,16 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "southArrowNorthEast" position', () => {
 			expect( positions.southArrowNorthEast( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 215,
-				left: 130,
+				top: 200 + arrowVOffset,
+				left: 100 + arrowHOffset,
 				name: 'arrow_ne'
 			} );
 		} );
 
 		it( 'should define the "southArrowNorthWest" position', () => {
 			expect( positions.southArrowNorthWest( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 215,
-				left: 120,
+				top: 200 + arrowVOffset,
+				left: 150 - arrowHOffset,
 				name: 'arrow_nw'
 			} );
 		} );
@@ -805,7 +809,7 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "southWestArrowNorth" position', () => {
 			expect( positions.southWestArrowNorth( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 215,
+				top: 200 + arrowVOffset,
 				left: 75,
 				name: 'arrow_n'
 			} );
@@ -813,16 +817,16 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "southWestArrowNorthWest" position', () => {
 			expect( positions.southWestArrowNorthWest( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 215,
-				left: 70,
+				top: 200 + arrowVOffset,
+				left: 100 - arrowHOffset,
 				name: 'arrow_nw'
 			} );
 		} );
 
 		it( 'should define the "southWestArrowNorthEast" position', () => {
 			expect( positions.southWestArrowNorthEast( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 215,
-				left: 80,
+				top: 200 + arrowVOffset,
+				left: 50 + arrowHOffset,
 				name: 'arrow_ne'
 			} );
 		} );
@@ -831,7 +835,7 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "southEastArrowNorth" position', () => {
 			expect( positions.southEastArrowNorth( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 215,
+				top: 200 + arrowVOffset,
 				left: 175,
 				name: 'arrow_n'
 			} );
@@ -839,16 +843,16 @@ describe( 'BalloonPanelView', () => {
 
 		it( 'should define the "southEastArrowNorthEast" position', () => {
 			expect( positions.southEastArrowNorthEast( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 215,
-				left: 180,
+				top: 200 + arrowVOffset,
+				left: 150 + arrowHOffset,
 				name: 'arrow_ne'
 			} );
 		} );
 
 		it( 'should define the "southEastArrowNorthWest" position', () => {
 			expect( positions.southEastArrowNorthWest( targetRect, balloonRect ) ).to.deep.equal( {
-				top: 215,
-				left: 170,
+				top: 200 + arrowVOffset,
+				left: 200 - arrowHOffset,
 				name: 'arrow_nw'
 			} );
 		} );

+ 0 - 5
packages/ckeditor5-ui/theme/components/button/button.css

@@ -12,13 +12,8 @@ a.ck-button {
 	@mixin ck-unselectable;
 	@mixin ck-tooltip_enabled;
 
-	display: inline-block;
 	position: relative;
 
-	@mixin ck-button-icon {
-		display: inline-block;
-	}
-
 	&.ck-button_with-text {
 		& .ck-button__label {
 			display: inline-block;

+ 1 - 5
packages/ckeditor5-ui/theme/components/dropdown/dropdown.css

@@ -9,11 +9,7 @@
 	display: inline-block;
 	position: relative;
 
-	/* A triangle displayed to indicate this is actually a dropdown. */
-	&::after {
-		content: '';
-		width: 0;
-		height: 0;
+	& .ck-dropdown__arrow {
 		pointer-events: none;
 		z-index: var(--ck-z-default);
 

+ 6 - 1
packages/ckeditor5-ui/theme/components/icon/icon.css

@@ -4,8 +4,13 @@
  */
 
 svg.ck-icon {
-	font-size: 1em;
+	/* Multiplied by the height of the line in "px" should give SVG "viewport" dimensions */
+	font-size: 0.8333333333em;
+
+	/* Must be consistent with .ck-button__label's vertical align. Otherwise, buttons with and
+	without labels (but with icons) have different sizes in Chrome */
 	vertical-align: middle;
+
 	color: inherit;
 
 	/* Inherit cursor style (#5). */

+ 1 - 0
packages/ckeditor5-ui/theme/icons/dropdown-arrow.svg

@@ -0,0 +1 @@
+<svg width="10" height="10" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg"><path d="M.941 4.523a.75.75 0 1 1 1.06-1.06l3.006 3.005 3.005-3.005a.75.75 0 1 1 1.06 1.06l-3.549 3.55a.75.75 0 0 1-1.168-.136L.941 4.523z" fill="#000" fill-rule="evenodd"/></svg>