Explorar el Código

Merge pull request #12 from ckeditor/t/ckeditor5-ui-default/12

t/ckeditor5-ui-default/12: Implement dropdown component
Piotrek Koszuliński hace 9 años
padre
commit
b00e728f45

+ 82 - 207
packages/ckeditor5-theme-lark/tests/manual/theme.html

@@ -6,24 +6,18 @@
 			line-height: 3em;
 		}
 
-		#icons, #iconsColored {
-			overflow: hidden;
+		*[id^="icon"] .ck-icon + .ck-icon,
+		*[id^="button"] .ck-button + .ck-button,
+		*[id^="dropdown"] .ck-dropdown + .ck-dropdown,
+		*[id^="toolbar"] .ck-button + .ck-button {
+			margin-left: 0.3em;
 		}
 
-		#iconsColored {
+		.icon-color {
 			color: red;
 		}
 
-		#buttonResponsive div > div {
-			font-size: 1.3em;
-			line-height: 2.8em;
-		}
-
-		#buttonResponsive div .ck-button {
-			font-size: inherit;
-		}
-
-		@keyframes iconColorChange {
+		@keyframes icon-color-change {
 			0% {
 				color: white;
 				background: orange;
@@ -38,214 +32,95 @@
 			}
 		}
 
-		#iconColorChange {
+		#icon-color-change {
 			border: 0;
-			animation: iconColorChange 3s infinite;
+			animation: icon-color-change 3s infinite;
+		}
+
+		.button-responsive > div {
+			font-size: 1.5em;
+			line-height: 2.8em;
+		}
+
+		.button-responsive div .ck-button {
+			font-size: inherit;
 		}
 	</style>
 </head>
 
-<div id="editor"></div>
-
 <h2>Icon</h2>
-<h3>Icon: In–text</h3>
-
-<p>Icons
-	<svg class="ck-icon"><use xlink:href="#ck-icon-quote"></use></svg>
-	and
-	<svg class="ck-icon"><use xlink:href="#ck-icon-bold"></use></svg> in a plain paragraph.
-	<span style="color: red">
-		Icons
-		<svg class="ck-icon"><use xlink:href="#ck-icon-link"></use></svg>
-		follow the
-		<svg class="ck-icon"><use xlink:href="#ck-icon-source"></use></svg>
-		color of text.
-	</span>
-</p>
-
-<h3>Icon: Availability</h3>
-<p id="icons" class="ck-reset-all"></p>
-
-<h3>Icon: Availability (colored)</h3>
-<p id="iconsColored" class="ck-reset-all"></p>
+
+	<h3>Icon: In–text</h3>
+
+	<p>Icons <span id="icon-plain-1"></span> and <span id="icon-plain-2"></span> in a plain paragraph.</p>
+	<p class="icon-color">
+		Icons <span id="icon-color-1"></span> follow the <span id="icon-color-2"></span> color of text.
+	</p>
+
+	<h3>Icon: Availability</h3>
+	<p id="icon-availability" class="ck-reset-all"></p>
+
+	<h3>Icon: Availability (colored)</h3>
+	<p id="icon-availability-color" class="ck-reset-all icon-color"></p>
 
 <hr/>
 
 <h2>Button</h2>
-<h3>Button: States</h3>
-
-<div class="ck-reset-all">
-	<button class="ck-button">State: normal (none)</button>
-	<button class="ck-button ck-disabled">State: disabled</button>
-	<button class="ck-button ck-on">State: on</button>
-</div>
-
-<h3>Button: Types</h3>
-
-<div class="ck-reset-all">
-	<button class="ck-button ck-button-action">Action button</button>
-	<button class="ck-button ck-rounded-corners">Rounded corners</button>
-	<button class="ck-button ck-button-bold">Bold text</button>
-</div>
-
-<h3>Button: Icon</h3>
-<div class="ck-reset-all" >
-	<div id="buttonIcon" class="wrappable"></div>
-
-	<br/>
-
-	<button class="ck-button">
-		<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-bold"></use></svg>
-		Icon to the left
-	</button>
-	<button class="ck-button">
-		<svg class="ck-icon ck-icon-right"><use xlink:href="#ck-icon-bold"></use></svg>
-		Icon to the right (RTL)
-	</button>
-	<button class="ck-button" style="border-radius: 100px; border: 0">
-		<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-image"></use></svg>
-		Custom style with icon
-	</button>
-
-	<br/>
-	<br/>
-
-	<button class="ck-button ck-disabled">
-		<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-bold"></use></svg>
-		Disabled with icon
-	</button>
-
-	<button class="ck-button ck-disabled ck-button-notext">
-		<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-bold"></use></svg>
-	</button>
-	<button id="iconColorChange" class="ck-button">
-		<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-bold"></use></svg>
-		Icon follows text color
-	</button>
-</div>
-
-<h3>Button: Responsiveness</h3>
-<div id="buttonResponsive" class="ck-reset-all">
-	<div>
-		<button class="ck-button">A button</button>
-		<button class="ck-button ck-button-action">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-image"></use></svg>
-			Image
-		</button>
-		<button class="ck-button">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-bold"></use></svg>
-			Bold
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-link"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-image"></use></svg>
-		</button>
+
+	<h3>Button: States</h3>
+	<div id="button-states" class="ck-reset-all"></div>
+
+	<h3>Button: Types</h3>
+	<div id="button-types" class="ck-reset-all"></div>
+
+	<h3>Button: Icon</h3>
+	<div class="ck-reset-all" >
+		<div id="button-icon" class="wrappable"></div>
+
+		<br/>
+
+		<div id="button-icon-custom"></div>
+
+		<br/>
+		<br/>
+
+		<div id="button-icon-states"></div>
+	</div>
+
+	<h3>Button: Responsiveness</h3>
+	<div id="button-responsive-1" class="button-responsive ck-reset-all">
+		<div id="button-responsive-2" class="button-responsive">
+			<div id="button-responsive-3" class="button-responsive"></div>
+		</div>
 	</div>
-</div>
+
+<hr/>
+
+<h2>Dropdown</h2>
+
+	<h3>ListDropdown</h3>
+	<div id="dropdown"></div>
 
 <hr/>
 
 <h2>Toolbar</h2>
 
-<h3>Toolbar: Text</h3>
-<div class="ck-reset-all">
-	<div class="ck-toolbar">
-		Just text and some <svg class="ck-icon"><use xlink:href="#ck-icon-bold"></use></svg> icon.
-	</div>
-</div>
-
-<h3>Toolbar: Button</h3>
-<div class="ck-reset-all">
-	<div class="ck-toolbar">
-		<button class="ck-button">A button</button>
-		<button class="ck-button ck-disabled">Disabled button</button>
-		<button class="ck-button ck-button-active">Active button</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-bold"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-link"></use></svg>
-		</button>
-		And some text.
-	</div>
-</div>
+	<h3>Toolbar: Text</h3>
+	<div id="toolbar-text" class="ck-reset-all"></div>
 
-<h3>Toolbar: Rounded</h3>
-<div class="ck-reset-all">
-	<div class="ck-rounded-corners ck-toolbar">
-		<button class="ck-button">A button which corners are also rounded because of toolbar class</button>
-		<button class="ck-button ck-button-notext"><svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-bold"></use></svg></button>
-	</div>
-</div>
-
-<h3>Toolbar: Wrapping content</h3>
-<div class="ck-reset-all">
-	<div class="ck-toolbar" style="width: 80px">
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-bold"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-italic"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-underline"></use></svg>
-		</button>
-	</div>
-</div>
-
-<h3>Toolbar: Item separators</h3>
-<div class="ck-reset-all">
-	<div class="ck-toolbar">
-		<button class="ck-button">First</button>
-		<button class="ck-button">Second</button>
-		<span class="ck-toolbar-separator"></span>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-bold"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-italic"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-underline"></use></svg>
-		</button>
-		<span class="ck-toolbar-separator"></span>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-link"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-image"></use></svg>
-		</button>
-	</div>
-</div>
-
-<h3>Toolbar: Multi-row</h3>
-<div class="ck-reset-all">
-	<div class="ck-toolbar">
-		<button class="ck-button">First row</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-bold"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-italic"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-underline"></use></svg>
-		</button>
-		<span class="ck-toolbar-newline"></span>
-		<button class="ck-button">Second row</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-link"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-image"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-table"></use></svg>
-		</button>
-		<button class="ck-button ck-button-notext">
-			<svg class="ck-icon ck-icon-left"><use xlink:href="#ck-icon-source"></use></svg>
-		</button>
-	</div>
-</div>
+	<h3>Toolbar: Button</h3>
+	<div id="toolbar-button" class="ck-reset-all"></div>
+
+	<h3>Toolbar: Rounded</h3>
+	<div id="toolbar-rounded" class="ck-reset-all ck-rounded-corners"></div>
+
+	<h3>Toolbar: Wrapping content</h3>
+	<div id="toolbar-wrap" class="ck-reset-all"></div>
+
+	<h3>Toolbar: Item separators</h3>
+	<div id="toolbar-separator" class="ck-reset-all"></div>
+
+	<h3>Toolbar: Multi-row</h3>
+	<div id="toolbar-multi-row" class="ck-reset-all"></div>
+
+<div id="body"></div>

+ 371 - 29
packages/ckeditor5-theme-lark/tests/manual/theme.js

@@ -5,51 +5,393 @@
 
 'use strict';
 
+import testUtils from '/tests/ckeditor5/_utils/utils.js';
+
+import Collection from '/ckeditor5/utils/collection.js';
 import IconManagerView from '/ckeditor5/ui/iconmanagerview.js';
 import Model from '/ckeditor5/ui/model.js';
+import Controller from '/ckeditor5/ui/controller.js';
+import View from '/ckeditor5/ui/view.js';
+
+import iconManagerModel from '/theme/iconmanagermodel.js';
 import IconView from '/ckeditor5/ui/icon/iconview.js';
+
+import Button from '/ckeditor5/ui/button/button.js';
 import ButtonView from '/ckeditor5/ui/button/buttonview.js';
-import iconManagerModel from '/theme/iconmanagermodel.js';
 
-function setupIconManager() {
-	const iconManagerView = new IconManagerView( iconManagerModel );
-	document.body.appendChild( iconManagerView.element );
-	iconManagerView.init();
+import ListDropdown from '/ckeditor5/ui/dropdown/list/listdropdown.js';
+import ListDropdownView from '/ckeditor5/ui/dropdown/list/listdropdownview.js';
+
+import Toolbar from '/ckeditor5/ui/toolbar/toolbar.js';
+import ToolbarView from '/ckeditor5/ui/toolbar/toolbarview.js';
+
+testUtils.createTestUIController( {
+	'icon-plain-1':					'#icon-plain-1',
+	'icon-plain-2':					'#icon-plain-2',
+	'icon-color-1':					'#icon-color-1',
+	'icon-color-2':					'#icon-color-2',
+	'icon-availability':			'#icon-availability',
+	'icon-availability-color':		'#icon-availability-color',
+
+	'button-states':				'#button-states',
+	'button-types':					'#button-types',
+	'button-icon':					'#button-icon',
+	'button-custom':				'#button-custom',
+	'button-icon-custom':			'#button-icon-custom',
+	'button-icon-states':			'#button-icon-states',
+	'button-responsive-1':			'#button-responsive-1',
+	'button-responsive-2':			'#button-responsive-2',
+	'button-responsive-3':			'#button-responsive-3',
+
+	dropdown:						'#dropdown',
+
+	'toolbar-text':					'#toolbar-text',
+	'toolbar-button':				'#toolbar-button',
+	'toolbar-rounded':				'#toolbar-rounded',
+	'toolbar-wrap':					'#toolbar-wrap',
+	'toolbar-separator':			'#toolbar-separator',
+	'toolbar-multi-row':			'#toolbar-multi-row',
+
+	body:							'div#body'
+} ).then( ui => {
+	renderIcon( ui );
+	renderButton( ui );
+	renderDropdown( ui );
+	renderToolbar( ui );
+} );
+
+function renderIcon( ui ) {
+	// --- IconManager ------------------------------------------------------------
+
+	ui.add( 'body', new Controller( null, new IconManagerView( iconManagerModel ) ) );
+
+	// --- In-text ------------------------------------------------------------
+
+	ui.add( 'icon-plain-1', icon( 'bold' ) );
+	ui.add( 'icon-plain-2', icon( 'quote' ) );
+
+	ui.add( 'icon-color-1', icon( 'bold' ) );
+	ui.add( 'icon-color-2', icon( 'quote' ) );
+
+	// --- Availability ------------------------------------------------------------
+
+	iconManagerModel.icons.forEach( i => {
+		ui.add( 'icon-availability', icon( i ) );
+		ui.add( 'icon-availability-color', icon( i ) );
+	} );
 }
 
-function renderIcons() {
-	const containers = [
-		document.getElementById( 'icons' ),
-		document.getElementById( 'iconsColored' )
-	];
-	const buttonIcons = document.getElementById( 'buttonIcon' );
+function renderButton( ui ) {
+	// --- States ------------------------------------------------------------
+
+	ui.add( 'button-states', button( {
+		label: 'State: normal (none)',
+	} ) );
+
+	ui.add( 'button-states', button( {
+		label: 'State: disabled',
+		isEnabled: false
+	} ) );
+
+	ui.add( 'button-states', button( {
+		label: 'State: on',
+		isOn: true
+	} ) );
+
+	// --- Types ------------------------------------------------------------
+
+	const actionButton = button( { label: 'Action button' } );
+	const roundedButton = button( { label: 'Rounded corners' } );
+	const boldButton = button( { label: 'Bold text' } );
+
+	// TODO: It requires model interface.
+	actionButton.view.element.classList.add( 'ck-button-action' );
+
+	// TODO: It requires model interface.
+	roundedButton.view.element.classList.add( 'ck-rounded-corners' );
+
+	// TODO: It requires model interface.
+	boldButton.view.element.classList.add( 'ck-button-bold' );
+
+	ui.add( 'button-types', actionButton );
+	ui.add( 'button-types', roundedButton );
+	ui.add( 'button-types', boldButton );
+
+	// --- Icon ------------------------------------------------------------
 
 	iconManagerModel.icons.forEach( i => {
-		const view = new IconView( new Model( { icon: i } ) );
-		const button = new ButtonView( new Model( { label: i, icon: i, isEnabled: true } ) );
-		button.init();
+		ui.add( 'button-icon', button( {
+			label: i,
+			icon: i,
+			iconAlign: 'LEFT'
+		} ) );
+	} );
+
+	ui.add( 'button-icon-custom', button( {
+		label: 'Icon to the left',
+		icon: 'bold',
+		iconAlign: 'LEFT'
+	} ) );
+
+	ui.add( 'button-icon-custom', button( {
+		label: 'Icon to the right (RTL)',
+		icon: 'bold',
+		iconAlign: 'RIGHT'
+	} ) );
+
+	const styledButton = button( {
+		label: 'Button with icon and custom styles',
+		icon: 'italic',
+		iconAlign: 'LEFT'
+	} );
+
+	// TODO: It probably requires model interface.
+	styledButton.view.element.setAttribute( 'style', 'border-radius: 100px; border: 0' );
+
+	ui.add( 'button-icon-custom', styledButton );
+
+	ui.add( 'button-icon-states', button( {
+		label: 'Disabled',
+		icon: 'bold',
+		iconAlign: 'LEFT',
+		isEnabled: false
+	} ) );
+
+	const notextButton = button( {
+		label: '',
+		icon: 'bold',
+		iconAlign: 'LEFT'
+	} );
+
+	// TODO: It requires model interface.
+	notextButton.view.element.classList.add( 'ck-button-notext' );
+
+	ui.add( 'button-icon-states', notextButton );
+
+	const colChangeButton = button( {
+		label: 'Icon follows text color',
+		icon: 'bold',
+		iconAlign: 'LEFT'
+	} );
+
+	// TODO: It requires model interface.
+	colChangeButton.view.element.id = 'icon-color-change';
+
+	ui.add( 'button-icon-states', colChangeButton );
+
+	// --- Responsive ------------------------------------------------------------
+
+	for ( let i = 1; i < 4; i++ ) {
+		ui.add( `button-responsive-${ i }`, button( {
+			label: 'A button',
+			isEnabled: true
+		} ) );
+
+		ui.add( `button-responsive-${ i }`, button( {
+			label: 'Bold',
+			icon: 'bold',
+			iconAlign: 'LEFT',
+			isEnabled: true
+		} ) );
 
-		containers.forEach( c => {
-			c.appendChild( view.element.cloneNode( 1 ) );
-			c.appendChild( document.createTextNode( ' ' ) );
+		const notextButton = button( {
+			label: '',
+			icon: 'link',
+			iconAlign: 'LEFT'
 		} );
 
-		buttonIcons.appendChild( button.element );
-		buttonIcons.appendChild( document.createTextNode( ' ' ) );
+		// TODO: It requires model interface.
+		notextButton.view.element.classList.add( 'ck-button-notext' );
+		notextButton.view.element.classList.add( 'ck-button-action' );
+
+		ui.add( `button-responsive-${ i }`, notextButton );
+	}
+}
+
+function renderDropdown( ui ) {
+	// --- ListDropdown ------------------------------------------------------------
+
+	const collection = new Collection( { idProperty: 'label' } );
+
+	[ 'Arial', 'Tahoma', 'Georgia' ].forEach( font => {
+		collection.add( new Model( {
+			label: font,
+			style: `font-family: ${ font }`
+		} ) );
+	} );
+
+	const itemListModel = new Model( {
+		items: collection
+	} );
+
+	const enabledModel = new Model( {
+		label: 'Normal state',
+		isEnabled: true,
+		isOn: false,
+		content: itemListModel
+	} );
+
+	const disabledModel = new Model( {
+		label: 'Disabled',
+		isEnabled: false,
+		isOn: false,
+		content: itemListModel
+	} );
+
+	ui.add( 'dropdown', new ListDropdown( enabledModel, new ListDropdownView( enabledModel ) ) );
+	ui.add( 'dropdown', new ListDropdown( disabledModel, new ListDropdownView( disabledModel ) ) );
+}
+
+function renderToolbar( ui ) {
+	// --- Text ------------------------------------------------------------
+
+	ui.add( 'toolbar-text', toolbar( [
+		icon( 'bold' ),
+		text()
+	] ) );
+
+	// --- Button ------------------------------------------------------------
+
+	ui.add( 'toolbar-button', toolbar( [
+		button(),
+		text(),
+		button( {
+			label: 'Button with icon',
+			icon: 'bold',
+			iconAlign: 'LEFT'
+		} )
+	] ) );
+
+	// --- Rounded ------------------------------------------------------------
+
+	ui.add( 'toolbar-rounded', toolbar( [
+		button( {
+			label: 'A button which corners are also rounded because of toolbar class'
+		} ),
+		button( {
+			label: 'Button with icon',
+			icon: 'bold',
+			iconAlign: 'LEFT'
+		} )
+	] ) );
+
+	// --- Wrap ------------------------------------------------------------
+
+	const wrapToolbar = toolbar( [
+		button(),
+		button(),
+		button()
+	] );
+
+	wrapToolbar.view.element.style.width = '150px';
+
+	ui.add( 'toolbar-wrap', wrapToolbar );
+
+	// --- Separator ------------------------------------------------------------
+
+	ui.add( 'toolbar-separator', toolbar( [
+		button(),
+		button(),
+		toolbarSeparator(),
+		button( {
+			label: 'Link',
+			icon: 'link',
+			iconAlign: 'LEFT'
+		} ),
+		toolbarSeparator(),
+		button( {
+			label: 'Unlink RTL',
+			icon: 'unlink',
+			iconAlign: 'RIGHT'
+		} )
+	] ) );
+
+	// --- Multi row ------------------------------------------------------------
+
+	ui.add( 'toolbar-multi-row', toolbar( [
+		button(),
+		button(),
+		toolbarNewLine(),
+		button( {
+			label: 'Link',
+			icon: 'link',
+			iconAlign: 'LEFT'
+		} ),
+		button( {
+			label: 'Unlink RTL',
+			icon: 'unlink',
+			iconAlign: 'RIGHT'
+		} ),
+		button( {
+			label: 'Link',
+			icon: 'link',
+			iconAlign: 'LEFT'
+		} )
+	] ) );
+}
+
+const TextView = class extends View {
+	constructor() {
+		super();
+
+		this.element = document.createTextNode( 'Sample text' );
+	}
+};
+
+function text() {
+	return new Controller( null, new TextView( null ) );
+}
+
+function icon( name ) {
+	return new Controller( null, new IconView( new Model( { icon: name } ) ) );
+}
+
+function button( { label = 'Button', isEnabled = true, isOn = false, icon, iconAlign } = {} ) {
+	const model = new Model( { label, isEnabled, isOn, icon, iconAlign } );
+
+	return new Button( model, new ButtonView( model ) );
+}
+
+function toolbar( children = [] ) {
+	const toolbar = new Toolbar( null, new ToolbarView( null ) );
+
+	children.forEach( c => {
+		toolbar.add( 'buttons', c );
 	} );
+
+	return toolbar;
 }
 
-function renderResponsiveButtons() {
-	const responsive = document.getElementById( 'buttonResponsive' );
-	let current = responsive.firstElementChild;
+const ToolbarSeparatorView = class extends View {
+	constructor() {
+		super();
 
-	for ( let i = 3; i--; ) {
-		const clone = current.cloneNode( 1 );
-		current.appendChild( clone );
-		current = clone;
+		this.template = {
+			tag: 'span',
+			attributes: {
+				class: 'ck-toolbar-separator'
+			}
+		};
 	}
+};
+
+function toolbarSeparator() {
+	return new Controller( null, new ToolbarSeparatorView( null ) );
 }
 
-setupIconManager();
-renderIcons();
-renderResponsiveButtons();
+const ToolbarNewlineView = class extends View {
+	constructor() {
+		super();
+
+		this.template = {
+			tag: 'span',
+			attributes: {
+				class: 'ck-toolbar-newline'
+			}
+		};
+	}
+};
+
+function toolbarNewLine() {
+	return new Controller( null, new ToolbarNewlineView( null ) );
+}

+ 42 - 0
packages/ckeditor5-theme-lark/theme/components/dropdown.scss

@@ -0,0 +1,42 @@
+// Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+// For licensing, see LICENSE.md or http://ckeditor.com/license
+
+.ck-dropdown {
+	display: inline-block;
+	position: relative;
+}
+
+.ck-dropdown__button {
+	&:after {
+		content: '';
+		width: 0;
+		height: 0;
+		border-style: solid;
+		border-width: .4em .4em 0 .4em;
+		border-color: ck-color( 'text', 30 ) transparent;
+		position: relative;
+		top: .9em;
+		margin-left: ck-spacing( 'medium' );
+	}
+}
+
+.ck-dropdown__panel {
+	border: 1px solid ck-border-color( 'foreground' );
+	display: none;
+	box-shadow: 0 0 5px ck-color( 'foreground', -15 );
+	position: absolute;
+	left: 0px;
+
+	// Compensate double border from button and from box when positioned below the button.
+	bottom: 2px;
+
+	transform: translateY( 100% );
+	background: ck-color( 'background' );
+	z-index: ck-z();
+
+	@include ck-rounded-corners();
+
+	&-active {
+		display: inline-block;
+	}
+}

+ 20 - 9
packages/ckeditor5-theme-lark/theme/components/editor.scss

@@ -3,6 +3,8 @@
 
 // TODO/NOTE: This along with _editor helper will probably become a creator theme.
 @include ck-editor {
+	@include ck-rounded-corners();
+
 	.ck-editor__top {
 		.ck-toolbar {
 			border-top: 0;
@@ -28,18 +30,13 @@
 		overflow: auto;
 		padding: 0 ck-spacing();
 	}
-}
-
-.ck-editor,
-.ck-editor-bottom {
-	background: ck-color( 'foreground' );
-	border: 1px solid ck-border-color( 'foreground' );
-}
 
-@include ck-editor {
 	.ck-toolbar {
+		// Toolbars should not react to ck-rounded-corners() mixin.
+		border-radius: 0;
+
 		.ck-button {
-			border: 0;
+			border-width: 0;
 		}
 
 		// Make sure the next button does not overlap focused one.
@@ -54,5 +51,19 @@
 		.ck-button.ck-on {
 			@include ck-button-colors( 'foreground', -10 );
 		}
+
+		.ck-dropdown__button {
+			border-width: 1px;
+		}
+
+		.ck-dropdown__button:not(:hover):not(:focus):not(.ck-on) {
+			background: ck-color( 'background' );
+		}
 	}
 }
+
+.ck-editor,
+.ck-editor-bottom {
+	background: ck-color( 'foreground' );
+	border: 1px solid ck-border-color( 'foreground' );
+}

+ 27 - 0
packages/ckeditor5-theme-lark/theme/components/list.scss

@@ -0,0 +1,27 @@
+// Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+// For licensing, see LICENSE.md or http://ckeditor.com/license
+
+.ck-list {
+	overflow: hidden;
+	list-style-type: none;
+	background: ck-color( 'background' );
+
+	@include ck-unselectable();
+	@include ck-rounded-corners();
+
+	&__item {
+		display: block;
+		padding: ck-spacing( 'medium' );
+		cursor: pointer;
+		min-width: 12em;
+
+		&:hover,
+		&:focus {
+			background: ck-color( 'foreground' );
+		}
+
+		&:last-of-type {
+			border: none;
+		}
+	}
+}

+ 1 - 1
packages/ckeditor5-theme-lark/theme/helpers/_rounded.scss

@@ -6,7 +6,7 @@
  *
  * @access public
  */
-$ck-border-radius: 3px !default;
+$ck-border-radius: 2px !default;
 
 /**
  * Implements rounded corner interface for .ck-rounded-corners class.

+ 12 - 0
packages/ckeditor5-theme-lark/theme/helpers/_zindex.scss

@@ -0,0 +1,12 @@
+// Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+// For licensing, see LICENSE.md or http://ckeditor.com/license
+
+$ck-def-z: (
+	'default': 1
+	// 'modal': 10
+	// 'topmost': 9999
+);
+
+@function ck-z( $index: 'default' ) {
+	@return map-get( $ck-def-z, $index );
+}

+ 3 - 0
packages/ckeditor5-theme-lark/theme/theme.scss

@@ -6,10 +6,13 @@
 @import 'helpers/rounded';
 @import 'helpers/spacing';
 @import 'helpers/states';
+@import 'helpers/zindex';
 @import 'helpers/editor';
 
 @import 'components/reset';
 @import 'components/icon';
 @import 'components/button';
 @import 'components/toolbar';
+@import 'components/dropdown';
+@import 'components/list';
 @import 'components/editor';