# UI components

The CKEditor 5 framework provides several UI components that can be helpful when developing a new user interface. All UI classes come with the [`set()`](../../api/module_ui_view-View.md#function-set:KEY_VALUE) method, which sets the properties of the components, such as labels, icons, placeholders, etc.

> **Note**
>
> This article lists all available components and their variants. If you want to understand the implementation details, check the [UI library](ui-library.md) guide.

<a id="balloon">

## Balloon

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

A balloon panel is a floating component that can appear depending on the context. It can be pinned to a specific position or added dynamically at the caret position. You can use it to display any UI within the editor. You can create a balloon panel as an instance of the [`BalloonPanelView`](../../api/module_ui_panel_balloon_balloonpanelview-BalloonPanelView.md) class.

**NPM**

```js
import { BalloonPanelView, ButtonView } from 'ckeditor5';

const balloonButton = new ButtonView();
balloonButton.set( { label: 'Balloon button', withText: true } );
balloonButton.render();

const balloon = new BalloonPanelView();
balloon.render();
balloon.content.add( balloonButton );

const positions = BalloonPanelView.defaultPositions;
balloon.pin( {
	target: document.getElementById( 'balloon' ),
	positions: [ positions.southArrowNorth ]
} );

document.body.append( balloon.element );
```

**CDN**

```js
const { BalloonPanelView, ButtonView } = CKEDITOR;

const balloonButton = new ButtonView();
balloonButton.set( { label: 'Balloon button', withText: true } );
balloonButton.render();

const balloon = new BalloonPanelView();
balloon.render();
balloon.content.add( balloonButton );

const positions = BalloonPanelView.defaultPositions;
balloon.pin( {
	target: document.getElementById( 'balloon' ),
	positions: [ positions.southArrowNorth ]
} );

document.body.append( balloon.element );
```

Two positions describe the placement of the ballon. The first one describes the relationship between the element and the pinned balloon. The second one is the position of the balloon arrow. It creates many possible balloon positions:

* `northWestArrowSouthWest`
* `northWestArrowSouthMiddleWest`
* `northWestArrowSouth`
* `northWestArrowSouthMiddleEast`
* `northWestArrowSouthEast`
* `northArrowSouthWest`
* `northArrowSouthMiddleWest`
* `northArrowSouth`
* `northArrowSouthMiddleEast`
* `northArrowSouthEast`
* `northEastArrowSouthWest`
* `northEastArrowSouthMiddleWest`
* `northEastArrowSouth`
* `northEastArrowSouthMiddleEast`
* `northEastArrowSouthEast`
* `southWestArrowNorthWest`
* `southWestArrowNorthMiddleWest`
* `southWestArrowNorth`
* `southWestArrowNorthMiddleEast`
* `southWestArrowNorthEast`
* `southArrowNorthWest`
* `southArrowNorthMiddleWest`
* `southArrowNorth`
* `southArrowNorthMiddleEast`
* `southArrowNorthEast`
* `southEastArrowNorthWest`
* `southEastArrowNorthMiddleWest`
* `southEastArrowNorth`
* `southEastArrowNorthMiddleEast`
* `southEastArrowNorthEast`
* `viewportStickyNorth`

<a id="button">

## Button

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

There are two basic buttons in the CKEditor 5 UI library: a standard button and a switch. You can instantiate the standard button with the [`ButtonView`](../../api/module_ui_button_buttonview-ButtonView.md) class. By modifying the passed configuration, you can get different button variants and states. The [`ButtonLabelView`](../../api/module_ui_button_buttonlabelview-ButtonLabelView.md) class is a default implementation of the button’s label. It supports dynamic text via the [`text`](../../api/module_ui_button_buttonlabelview-ButtonLabelView.md#member-text) property.

<a id="action">

### Action

To get an action button, add the `ck-button-action` class.

**NPM**

```js
import { ButtonView } from 'ckeditor5';

const actionButton = new ButtonView();

actionButton.set( {
	label: 'Action button',
	withText: true,
	class: 'ck-button-action'
} );
actionButton.render();

document.getElementById( 'button-action' ).append( actionButton.element );
```

**CDN**

```js
const { ButtonView } = CKEDITOR;

const actionButton = new ButtonView();

actionButton.set( {
	label: 'Action button',
	withText: true,
	class: 'ck-button-action'
} );
actionButton.render();

document.getElementById( 'button-action' ).append( actionButton.element );
```

<a id="rounded">

### Rounded

To get a rounded button, add the `ck-rounded-corners` class.

**NPM**

```js
import { ButtonView } from 'ckeditor5';

const roundedButton = new ButtonView();

roundedButton.set( {
	label: 'Rounded button',
	withText: true,
	class: 'ck-rounded-corners'
} );
roundedButton.render();

document.getElementById( 'button-rounded' ).append( roundedButton.element );
```

**CDN**

```js
const { ButtonView } = CKEDITOR;

const roundedButton = new ButtonView();

roundedButton.set( {
	label: 'Rounded button',
	withText: true,
	class: 'ck-rounded-corners'
} );
roundedButton.render();

document.getElementById( 'button-rounded' ).append( roundedButton.element );
```

<a id="bold">

### Bold

To get a bold button, add the `ck-button-bold` class.

**NPM**

```js
import { ButtonView } from 'ckeditor5';

const boldButton = new ButtonView();

boldButton.set( {
	label: 'Bold button',
	withText: true,
	class: 'ck-button-bold'
} );
boldButton.render();

document.getElementById( 'button-bold' ).append( boldButton.element );
```

**CDN**

```js
const { ButtonView } = CKEDITOR;

const boldButton = new ButtonView();

boldButton.set( {
	label: 'Bold button',
	withText: true,
	class: 'ck-button-bold'
} );
boldButton.render();

document.getElementById( 'button-bold' ).append( boldButton.element );
```

<a id="icon">

### Icon

To get a button with an icon, import it first. Then set the `icon` property on the button. You can also add a custom icon to the dropdown by [providing the entire XML string of the icon](ui-library.md#setting-label-icon-and-tooltip). There are also classes you can use to style icons appropriately.

**NPM**

```js
import { ButtonView, IconCheck } from 'ckeditor5';

const saveButton = new ButtonView();

saveButton.set( {
	label: 'Save',
	withText: false,
	icon: IconCheck,
	class: 'ck-button-save'
} );
saveButton.render();

document.getElementById( 'button-icon' ).append( saveButton.element );
```

**CDN**

```js
const { ButtonView, IconCheck } = CKEDITOR;

const saveButton = new ButtonView();

saveButton.set( {
	label: 'Save',
	withText: false,
	icon: IconCheck,
	class: 'ck-button-save'
} );
saveButton.render();

document.getElementById( 'button-icon' ).append( saveButton.element );
```

<a id="keystrokes">

### Keystrokes

To get a button with a shortcut, add the `keystroke` property. To display the shortcut on the button, set the [`withKeystroke`](../../api/module_ui_button_button-Button.md#member-withKeystroke) property to `true`. If you also add a label, it will display next to the shortcut. You do not need to worry about different shortcuts for different operating systems – the shortcut is relative to the OS. For example, macOS will display the `Ctrl`+`I` shortcut as ⌘+`I`.

**NPM**

```js
import { ButtonView } from 'ckeditor5';

const keystrokeButton = new ButtonView();

keystrokeButton.set( {
	label: 'Italic',
	withText: true,
	withKeystroke: true,
	keystroke: 'Ctrl+I'
} );
keystrokeButton.render();

document.getElementById( 'button-keystroke' ).append( keystrokeButton.element );
```

**CDN**

```js
const { ButtonView } = CKEDITOR;

const keystrokeButton = new ButtonView();

keystrokeButton.set( {
	label: 'Italic',
	withText: true,
	withKeystroke: true,
	keystroke: 'Ctrl+I'
} );
keystrokeButton.render();

document.getElementById( 'button-keystroke' ).append( keystrokeButton.element );
```

<a id="tooltip">

### Tooltip

To get a button with a tooltip, add the `tooltip` property. You can use it to display additional information on button hover. If you set it to `true`, a label value is displayed.

**NPM**

```js
import { ButtonView } from 'ckeditor5';

const tooltipButton = new ButtonView();

tooltipButton.set( {
	label: 'Tooltip button',
	withText: true,
	tooltip: 'The content of the tooltip',
	tooltipPosition: 's'
} );
tooltipButton.render();

document.getElementById( 'button-tooltip' ).append( tooltipButton.element );
```

**CDN**

```js
const { ButtonView } = CKEDITOR;

const tooltipButton = new ButtonView();

tooltipButton.set( {
	label: 'Tooltip button',
	withText: true,
	tooltip: 'The content of the tooltip',
	tooltipPosition: 's'
} );
tooltipButton.render();

document.getElementById( 'button-tooltip' ).append( tooltipButton.element );
```

By default, the tooltip will appear to the south of the button. However, you can adjust its position with the [`tooltipPosition`](../../api/module_ui_tooltipmanager-TooltipPosition.md) property. You can set the property to:

* `n` – North
* `w` – West
* `s` – South
* `e` – East
* `se` – South-east
* `sw` – South-west

A tooltip needs the [`TooltipManager`](../../api/module_ui_tooltipmanager-TooltipManager.md) to work correctly. You need to add it during CKEditor creation.

```js
ClassicEditor
	.create( {
		// Editor configuration.
		//
	} )
	.then( editor => {
		this.tooltipManager = new TooltipManager( editor );
	} )
	.catch( error => {
		// Error handling.
		//
	} );
```

<a id="states">

### States

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

There are properties you can set to get various button states.

<a id="enabled">

#### Enabled

Buttons are enabled and clickable by default. You can also set the state explicitly by adding the [`isEnabled`](../../api/module_ui_button_button-Button.md#member-isEnabled) property with a `true` value.

**NPM**

```js
import { ButtonView } from 'ckeditor5';

const enabledButton = new ButtonView();

enabledButton.set( {
	label: 'Enabled state',
	withText: true,
	isEnabled: true
} );
enabledButton.render();

document.getElementById( 'button-enabled' ).append( enabledButton.element );
```

**CDN**

```js
const { ButtonView } = CKEDITOR;

const enabledButton = new ButtonView();

enabledButton.set( {
	label: 'Enabled state',
	withText: true,
	isEnabled: true
} );
enabledButton.render();

document.getElementById( 'button-enabled' ).append( enabledButton.element );
```

<a id="disabled">

#### Disabled

To disable a button, set the [`isEnabled`](../../api/module_ui_button_button-Button.md#member-isEnabled) property to `false`.

**NPM**

```js
import { ButtonView } from 'ckeditor5';

const disabledButton = new ButtonView();

disabledButton.set( {
	label: 'Disabled state',
	withText: true,
	isEnabled: false
} );
disabledButton.render();

document.getElementById( 'button-disabled' ).append( disabledButton.element );
```

**CDN**

```js
const { ButtonView } = CKEDITOR;

const disabledButton = new ButtonView();

disabledButton.set( {
	label: 'Disabled state',
	withText: true,
	isEnabled: false
} );
disabledButton.render();

document.getElementById( 'button-disabled' ).append( disabledButton.element );
```

<a id="on">

#### On

Some actions in the editor can constantly be active. To indicate them, you can set the [`isOn`](../../api/module_ui_button_button-Button.md#member-isOn) property to `true`.

**NPM**

```js
import { ButtonView } from 'ckeditor5';

const onButton = new ButtonView();

onButton.set( { label: 'On state', withText: true, isOn: true } );
onButton.render();

document.getElementById( 'button-on' ).append( onButton.element );
```

**CDN**

```js
const { ButtonView } = CKEDITOR;

const onButton = new ButtonView();

onButton.set( { label: 'On state', withText: true, isOn: true } );
onButton.render();

document.getElementById( 'button-on' ).append( onButton.element );
```

<a id="switch">

## Switch

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

You need a different class to instantiate a switch button – [`SwitchButtonView`](../../api/module_ui_button_switchbuttonview-SwitchButtonView.md). To make it work properly, you also need to add an event listener with the [`on()`](../../api/module_ui_button_switchbuttonview-SwitchButtonView.md#function-on) method. Every click triggers the flip of the [`isOn`](../../api/module_ui_button_switchbuttonview-SwitchButtonView.md#member-isOn) property. It is responsible for turning the button on and off.

**NPM**

```js
import { SwitchButtonView } from 'ckeditor5';

const switchButton = new SwitchButtonView();

switchButton.set( {
	label: 'Switch button',
	withText: true,
	isOn: false
} );
switchButton.render();
switchButton.on( 'execute', () => { switchButton.isOn = !switchButton.isOn } );

document.getElementById( 'button-switch' ).append( switchButton.element );
```

**CDN**

```js
const { SwitchButtonView } = CKEDITOR;

const switchButton = new SwitchButtonView();

switchButton.set( {
	label: 'Switch button',
	withText: true,
	isOn: false
} );
switchButton.render();
switchButton.on( 'execute', () => { switchButton.isOn = !switchButton.isOn } );

document.getElementById( 'button-switch' ).append( switchButton.element );
```

<a id="dropdown">

## Dropdown

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

A dropdown consists of two elements: a button and a panel. The button expands the dropdown menu. The dropdown panel can hold any UI element.

You can use the [`createDropdown()`](../../api/module_ui_dropdown_utils.md#function-createDropdown) helper method to create a dropdown. By default, it uses the [`DropdownButtonView`](../../api/module_ui_dropdown_button_dropdownbuttonview-DropdownButtonView.md) class. You can replace it with the [`ButtonView`](../../api/module_ui_button_buttonview-ButtonView.md) or [`SplitButtonView`](../../api/module_ui_dropdown_button_splitbuttonview-SplitButtonView.md) class.

<a id="list">

### List

Inside a dropdown, you can put a list. To do so, you can use the [`addListToDropdown()`](../../api/module_ui_dropdown_utils.md#function-addListToDropdown) helper function. Also, you must add items to a collection before putting them inside the dropdown.

**NPM**

```js
import {
	addListToDropdown,
	Collection,
	createDropdown,
	Locale,
	UIModel
} from 'ckeditor5';

const locale = new Locale();

const collection = new Collection();
collection.add( {
	type: 'button',
	model: new UIModel( {
		label: 'Button',
		withText: true
	} )
} );
collection.add( {
	type: 'switchbutton',
	model: new UIModel( {
		label: 'Switch button',
		withText: true
	} )
} );

const listDropdown = createDropdown( locale );
listDropdown.buttonView.set( {
	label: 'List dropdown',
	withText: true
} );
addListToDropdown( listDropdown, collection );
listDropdown.render();

document.getElementById( 'dropdown-list' ).append( listDropdown.element );
```

**CDN**

```js
const {
	addListToDropdown,
	Collection,
	createDropdown,
	Locale,
	UIModel
} = CKEDITOR;

const locale = new Locale();

const collection = new Collection();
collection.add( {
	type: 'button',
	model: new UIModel( {
		label: 'Button',
		withText: true
	} )
} );
collection.add( {
	type: 'switchbutton',
	model: new UIModel( {
		label: 'Switch button',
		withText: true
	} )
} );

const listDropdown = createDropdown( locale );
listDropdown.buttonView.set( {
	label: 'List dropdown',
	withText: true
} );
addListToDropdown( listDropdown, collection );
listDropdown.render();

document.getElementById( 'dropdown-list' ).append( listDropdown.element );
```

<a id="toolbar">

### Toolbar

You can use the [`addToolbarToDropdown()`](../../api/module_ui_dropdown_utils.md#function-addToolbarToDropdown) helper function to add a toolbar to the dropdown. Inside the toolbar, you can put buttons.

**NPM**

```js
import {
	addToolbarToDropdown,
	ButtonView,
	createDropdown,
	Locale,
	IconBold,
	IconItalic
} from 'ckeditor5';

const locale = new Locale();

const bold = new ButtonView();
const italic = new ButtonView();

bold.set( { label: 'Bold', withText: false, icon: IconBold } );
italic.set( { label: 'Italic', withText: false, icon: IconItalic } );

const buttons = [ bold, italic ];

const toolbarDropdown = createDropdown( locale );
toolbarDropdown.buttonView.set( {
	label: 'Toolbar dropdown',
	withText: true
} );
addToolbarToDropdown( toolbarDropdown, buttons );
toolbarDropdown.render();

document.getElementById( 'toolbar-button' ).append( toolbarDropdown.element );
```

**CDN**

```js
const {
	addToolbarToDropdown,
	ButtonView,
	createDropdown,
	Locale,
	IconBold,
	IconItalic
} = CKEDITOR;

const locale = new Locale();

const bold = new ButtonView();
const italic = new ButtonView();

bold.set( { label: 'Bold', withText: false, icon: IconBold } );
italic.set( { label: 'Italic', withText: false, icon: IconItalic } );

const buttons = [ bold, italic ];

const toolbarDropdown = createDropdown( locale );
toolbarDropdown.buttonView.set( {
	label: 'Toolbar dropdown',
	withText: true
} );
addToolbarToDropdown( toolbarDropdown, buttons );
toolbarDropdown.render();

document.getElementById( 'toolbar-button' ).append( toolbarDropdown.element );
```

<a id="menu">

### Menu

Finally, you can add a multi-level menu to a dropdown. Use the [`addMenuToDropdown()`](../../api/module_ui_dropdown_utils.md#function-addMenuToDropdown) helper function to simplify the process.

**NPM**

```js
import {
	addMenuToDropdown,
	createDropdown
} from 'ckeditor5';

const locale = new Locale(); // Can be `editor.locale`.
const body = new BodyCollection(); // Can be `editor.ui.view.body`.

const menuDropdown = createDropdown( locale );

// The menu items definitions.
const definition = [
	{
		id: 'menu_1',
		menu: 'Menu 1',
		children: [
			{
				id: 'menu_1_a',
				label: 'Item A'
			},
			{
				id: 'menu_1_b',
				label: 'Item B'
			}
		]
	},
	{
		id: 'top_a',
		label: 'Top Item A'
	},
	{
		id: 'top_b',
		label: 'Top Item B'
	}
];

addMenuToDropdown( menuDropdown, body, definition );

menuDropdown.render();

document.getElementById( 'menu-dropdown' ).append( menuDropdown.element );
```

**CDN**

```js
const {
	addMenuToDropdown,
	createDropdown
} = CKEDITOR;

const locale = new Locale(); // Can be `editor.locale`.
const body = new BodyCollection(); // Can be `editor.ui.view.body`.

const menuDropdown = createDropdown( locale );

// The menu items definitions.
const definition = [
	{
		id: 'menu_1',
		menu: 'Menu 1',
		children: [
			{
				id: 'menu_1_a',
				label: 'Item A'
			},
			{
				id: 'menu_1_b',
				label: 'Item B'
			}
		]
	},
	{
		id: 'top_a',
		label: 'Top Item A'
	},
	{
		id: 'top_b',
		label: 'Top Item B'
	}
];

addMenuToDropdown( menuDropdown, body, definition );

menuDropdown.render();

document.getElementById( 'menu-dropdown' ).append( menuDropdown.element );
```

<a id="split-button">

### Split button

Besides the standard button, you can also use the split button for a dropdown. It has two clickable sections: one for the main action and a second for expanding the dropdown with more options.

**NPM**

```js
import {
	addToolbarToDropdown,
	ButtonView,
	createDropdown,
	SplitButtonViewm,
	Locale,
	IconBold,
	IconItalic
} from 'ckeditor5';

const locale = new Locale();

const bold = new ButtonView();
const italic = new ButtonView();

bold.set( { label: 'Bold', withText: false, icon: IconBold } );
italic.set( { label: 'Italic', withText: false, icon: IconItalic } );

const buttons = [ bold, italic ];

const splitButtonDropdown = createDropdown( locale, SplitButtonView );
addToolbarToDropdown( splitButtonDropdown, buttons);
splitButtonDropdown.buttonView.set ( {
	label: 'Split button dropdown',
	withText: true
} );
splitButtonDropdown.render();

document.getElementById( 'dropdown-split-button' ).append( buttonDropdown.element );
```

**CDN**

```js
const {
	addToolbarToDropdown,
	ButtonView,
	createDropdown,
	SplitButtonViewm,
	Locale,
	IconBold,
	IconItalic
} = CKEDITOR;

const locale = new Locale();

const bold = new ButtonView();
const italic = new ButtonView();

bold.set( { label: 'Bold', withText: false, icon: IconBold } );
italic.set( { label: 'Italic', withText: false, icon: IconItalic } );

const buttons = [ bold, italic ];

const splitButtonDropdown = createDropdown( locale, SplitButtonView );
addToolbarToDropdown( splitButtonDropdown, buttons);
splitButtonDropdown.buttonView.set ( {
	label: 'Split button dropdown',
	withText: true
} );
splitButtonDropdown.render();

document.getElementById( 'dropdown-split-button' ).append( buttonDropdown.element );
```

<a id="states-2">

### States

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

Dropdowns use buttons. Because of that, states and properties remain the same.

<a id="enabled-2">

#### Enabled

Buttons in dropdowns are enabled and clickable by default. You can also set the state explicitly by adding the [`isEnabled`](../../api/module_ui_dropdown_button_dropdownbutton-DropdownButton.md#member-isEnabled) property with a `true` value.

**NPM**

```js
import { createDropdown, Locale } from 'ckeditor5';

const locale = new Locale();

const enabledDropdown = createDropdown( locale );
enabledDropdown.buttonView.set( {
	label: 'Enabled state',
	isEnabled: true,
	withText: true
} );
enabledDropdown.render();

document.getElementById( 'dropdown-enabled' ).append( enabledDropdown.element );
```

**CDN**

```js
const { createDropdown, Locale } = CKEDITOR;

const locale = new Locale();

const enabledDropdown = createDropdown( locale );
enabledDropdown.buttonView.set( {
	label: 'Enabled state',
	isEnabled: true,
	withText: true
} );
enabledDropdown.render();

document.getElementById( 'dropdown-enabled' ).append( enabledDropdown.element );
```

<a id="disabled-2">

#### Disabled

To disable a button, set the [`isEnabled`](../../api/module_ui_dropdown_button_dropdownbutton-DropdownButton.md#member-isEnabled) property to `false`. It prevents the dropdown from being expanded.

**NPM**

```js
import { createDropdown, Locale } from 'ckeditor5';

const locale = new Locale();

const disabledDropdown = createDropdown( locale );
disabledDropdown.buttonView.set( {
	label: 'Disabled state',
	isEnabled: false,
	withText: true
} );
disabledDropdown.render();

document.getElementById( 'dropdown-disabled' ).append( disabledDropdown.element );
```

**CDN**

```js
const { createDropdown, Locale } = CKEDITOR;

const locale = new Locale();

const disabledDropdown = createDropdown( locale );
disabledDropdown.buttonView.set( {
	label: 'Disabled state',
	isEnabled: false,
	withText: true
} );
disabledDropdown.render();

document.getElementById( 'dropdown-disabled' ).append( disabledDropdown.element );
```

<a id="dialog">

## Dialog

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

A dialog window is a draggable pop-up that you can display on top of the editor contents. It remains open when the user interacts with the editing area. You can use it to display any detached UI. Dialogs are brought by the [`Dialog`](../../api/module_ui_dialog_dialog-Dialog.md) plugin.

**NPM**

```js
// Necessary imports. Remember to install the packages first.
import {
	ButtonView,
	Dialog,
	View,
	Plugin,
	ClassicEditor,
	Paragraph,
	Essentials,
	Bold,
	Italic
} from 'ckeditor5';

// Create a plugin that brings a button that toggles the visibility of a dialog window.
// Read more about creating the plugins here: https://ckeditor.com/docs/ckeditor5/latest/framework/architecture/plugins.html.
class MinimalisticDialog extends Plugin {
	// Make sure the "Dialog" plugin is loaded.
	get requires() {
		return [ Dialog ];
	}

	init() {
		// Add a button to the component factory so it is available for the editor.
		this.editor.ui.componentFactory.add( 'showDialog', locale => {
			const buttonView = new ButtonView( locale );

			buttonView.set( {
				label: 'Show a dialog',
				tooltip: true,
				withText: true
			} );

			// Define the button behavior on press.
			buttonView.on( 'execute', () => {
				const dialog = this.editor.plugins.get( 'Dialog' );

				// If the button is turned on, hide the dialog.
				if ( buttonView.isOn ) {
					dialog.hide();
					buttonView.isOn = false;

					return;
				}

				buttonView.isOn = true;

				// Otherwise, show the dialog.
				// Create a view with some simple content. It will be displayed as a dialog's body.
				const textView = new View( locale );

				textView.setTemplate( {
					tag: 'div',
					attributes: {
						style: {
							padding: 'var(--ck-spacing-large)',
							whiteSpace: 'initial',
							width: '100%',
							maxWidth: '500px'
						},
						tabindex: -1
					},
					children: [
						'This is the content of the dialog.',
						'You can put here text, images, inputs, buttons, etc.'
					]
				} );

				// Tell the plugin to display a dialog with the title, content, and one action button.
				dialog.show( {
					title: 'Dialog with text',
					content: textView,
					actionButtons: [
						{
							label: 'OK',
							class: 'ck-button-action',
							withText: true,
							onExecute: () => dialog.hide()
						}
					],
					onHide() { buttonView.isOn = false; }
				} );
			} );

			return buttonView;
		} );
	}
}

// Create an editor instance. Remember to have an element with the `[id="editor"]` attribute in the document.
ClassicEditor
	.create( {
		attachTo: document.querySelector( '#editor' ),
		licenseKey: '<YOUR_LICENSE_KEY>', // Or 'GPL'.
		plugins: [ Essentials, Paragraph, Bold, Italic, MinimalisticDialog, Dialog ],
		toolbar: [ 'bold', 'italic', '|', 'showDialog' ]
	} )
	.catch( error => {
		console.error( error.stack );
	} );
```

**CDN**

```js
// Necessary imports. Remember to install the packages first.
const {
	ButtonView,
	Dialog,
	View,
	Plugin,
	ClassicEditor,
	Paragraph,
	Essentials,
	Bold,
	Italic
} = CKEDITOR;

// Create a plugin that brings a button that toggles the visibility of a dialog window.
// Read more about creating the plugins here: https://ckeditor.com/docs/ckeditor5/latest/framework/architecture/plugins.html.
class MinimalisticDialog extends Plugin {
	// Make sure the "Dialog" plugin is loaded.
	get requires() {
		return [ Dialog ];
	}

	init() {
		// Add a button to the component factory so it is available for the editor.
		this.editor.ui.componentFactory.add( 'showDialog', locale => {
			const buttonView = new ButtonView( locale );

			buttonView.set( {
				label: 'Show a dialog',
				tooltip: true,
				withText: true
			} );

			// Define the button behavior on press.
			buttonView.on( 'execute', () => {
				const dialog = this.editor.plugins.get( 'Dialog' );

				// If the button is turned on, hide the dialog.
				if ( buttonView.isOn ) {
					dialog.hide();
					buttonView.isOn = false;

					return;
				}

				buttonView.isOn = true;

				// Otherwise, show the dialog.
				// Create a view with some simple content. It will be displayed as a dialog's body.
				const textView = new View( locale );

				textView.setTemplate( {
					tag: 'div',
					attributes: {
						style: {
							padding: 'var(--ck-spacing-large)',
							whiteSpace: 'initial',
							width: '100%',
							maxWidth: '500px'
						},
						tabindex: -1
					},
					children: [
						'This is the content of the dialog.',
						'You can put here text, images, inputs, buttons, etc.'
					]
				} );

				// Tell the plugin to display a dialog with the title, content, and one action button.
				dialog.show( {
					title: 'Dialog with text',
					content: textView,
					actionButtons: [
						{
							label: 'OK',
							class: 'ck-button-action',
							withText: true,
							onExecute: () => dialog.hide()
						}
					],
					onHide() { buttonView.isOn = false; }
				} );
			} );

			return buttonView;
		} );
	}
}

// Create an editor instance. Remember to have an element with the `[id="editor"]` attribute in the document.
ClassicEditor
	.create( {
		attachTo: document.querySelector( '#editor' ),
		licenseKey: '<YOUR_LICENSE_KEY>',
		plugins: [ Essentials, Paragraph, Bold, Italic, MinimalisticDialog, Dialog ],
		toolbar: [ 'bold', 'italic', '|', 'showDialog' ]
	} )
	.catch( error => {
		console.error( error.stack );
	} );
```

See the guide about the [API of the dialog system](ui-library.md#dialogs-and-modals).

<a id="modal">

## Modal

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

Modal is a specific kind of dialog window. While open, it does not allow to interact with the editor content – it has to be closed first. You can use a modal to enforce the user interaction or interrupt them in some important situations.

To create a modal, use the optional [`isModal`](../../api/module_ui_dialog_dialog-DialogDefinition.md#member-isModal) property of the [`Dialog#show()`](../../api/module_ui_dialog_dialog-Dialog.md#function-show) method.

**NPM**

```js
// Necessary imports. Remember to install the packages first.
import {
	ButtonView,
	Dialog,
	View,
	Plugin,
	ClassicEditor,
	Paragraph,
	Essentials,
	Bold,
	Italic
} from 'ckeditor5';

// Create a plugin that brings a button which toggles the visibility of a modal window.
// Read more about creating the plugins here: https://ckeditor.com/docs/ckeditor5/latest/framework/architecture/plugins.html.
class MinimalisticModal extends Plugin {
	// Make sure the "Dialog" plugin is loaded.
	get requires() {
		return [ Dialog ];
	}

	init() {
		// Add a button to the component factory so it is available for the editor.
		this.editor.ui.componentFactory.add( 'showModal', locale => {
			const buttonView = new ButtonView( locale );

			buttonView.set( {
				label: 'Show a modal',
				tooltip: true,
				withText: true
			} );

			// Define the button behavior on press.
			buttonView.on( 'execute', () => {
				const dialog = this.editor.plugins.get( 'Dialog' );

				// If the button is turned on, hide the modal.
				if ( buttonView.isOn ) {
					dialog.hide();
					buttonView.isOn = false;

					return;
				}

				buttonView.isOn = true;

				// Otherwise, show the modal.
				// First, create a view with some simple content. It will be displayed as the dialog's body.
				const textView = new View( locale );

				textView.setTemplate( {
					tag: 'div',
					attributes: {
						style: {
							padding: 'var(--ck-spacing-large)',
							whiteSpace: 'initial',
							width: '100%',
							maxWidth: '500px'
						},
						tabindex: -1
					},
					children: [
						'This is a sample content of the modal.',
						'You can put here text, images, inputs, buttons, etc.'
					]
				} );

				// Tell the plugin to display a modal with the title, content, and one action button.
				dialog.show( {
					isModal: true,
					title: 'Modal with text',
					content: textView,
					actionButtons: [
						{
							label: 'OK',
							class: 'ck-button-action',
							withText: true,
							onExecute: () => dialog.hide()
						}
					],
					onHide() { buttonView.isOn = false; }
				} );
			} );

			return buttonView;
		} );
	}
}

// Create an editor instance. Remember to have an element with the `[id="editor"]` attribute in the document.
ClassicEditor
	.create( {
		attachTo: document.querySelector( '#editor' ),
		licenseKey: '<YOUR_LICENSE_KEY>', // Or 'GPL'.
		plugins: [ Essentials, Paragraph, Bold, Italic, MinimalisticDialog, Dialog ],
		toolbar: [ 'bold', 'italic', '|', 'showModal' ]
	} )
	.catch( error => {
		console.error( error.stack );
	} );
```

**CDN**

```js
// Necessary imports. Remember to install the packages first.
const {
	ButtonView,
	Dialog,
	View,
	Plugin,
	ClassicEditor,
	Paragraph,
	Essentials,
	Bold,
	Italic
} = CKEDITOR;

// Create a plugin that brings a button which toggles the visibility of a modal window.
// Read more about creating the plugins here: https://ckeditor.com/docs/ckeditor5/latest/framework/architecture/plugins.html.
class MinimalisticModal extends Plugin {
	// Make sure the "Dialog" plugin is loaded.
	get requires() {
		return [ Dialog ];
	}

	init() {
		// Add a button to the component factory so it is available for the editor.
		this.editor.ui.componentFactory.add( 'showModal', locale => {
			const buttonView = new ButtonView( locale );

			buttonView.set( {
				label: 'Show a modal',
				tooltip: true,
				withText: true
			} );

			// Define the button behavior on press.
			buttonView.on( 'execute', () => {
				const dialog = this.editor.plugins.get( 'Dialog' );

				// If the button is turned on, hide the modal.
				if ( buttonView.isOn ) {
					dialog.hide();
					buttonView.isOn = false;

					return;
				}

				buttonView.isOn = true;

				// Otherwise, show the modal.
				// First, create a view with some simple content. It will be displayed as the dialog's body.
				const textView = new View( locale );

				textView.setTemplate( {
					tag: 'div',
					attributes: {
						style: {
							padding: 'var(--ck-spacing-large)',
							whiteSpace: 'initial',
							width: '100%',
							maxWidth: '500px'
						},
						tabindex: -1
					},
					children: [
						'This is a sample content of the modal.',
						'You can put here text, images, inputs, buttons, etc.'
					]
				} );

				// Tell the plugin to display a modal with the title, content, and one action button.
				dialog.show( {
					isModal: true,
					title: 'Modal with text',
					content: textView,
					actionButtons: [
						{
							label: 'OK',
							class: 'ck-button-action',
							withText: true,
							onExecute: () => dialog.hide()
						}
					],
					onHide() { buttonView.isOn = false; }
				} );
			} );

			return buttonView;
		} );
	}
}

// Create an editor instance. Remember to have an element with the `[id="editor"]` attribute in the document.
ClassicEditor
	.create( {
		attachTo: document.querySelector( '#editor' ),
		licenseKey: '<YOUR_LICENSE_KEY>',
		plugins: [ Essentials, Paragraph, Bold, Italic, MinimalisticDialog, Dialog ],
		toolbar: [ 'bold', 'italic', '|', 'showModal' ]
	} )
	.catch( error => {
		console.error( error.stack );
	} );
```

See the guide about the [API of the dialog system](ui-library.md#dialogs-and-modals).

<a id="icons">

## Icons

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

The CKEditor 5 library has a collection of icons representing different editor functionalities. Icons are SVG files and follow the style of the surrounding text. You can instantiate an icon with the [`IconView`](../../api/module_ui_icon_iconview-IconView.md) class. The [`content`](../../api/module_ui_icon_iconview-IconView.md#member-content) property stores the SVG source of the icon.

**NPM**

```js
import { IconView, IconBold } from 'ckeditor5';

const icon = new IconView();

icon.content = IconBold;
icon.render();

document.getElementById( 'icon-bold' ).append( icon.element );
```

**CDN**

```js
const { IconView, IconBold } = CKEDITOR;

const icon = new IconView();

icon.content = IconBold;
icon.render();

document.getElementById( 'icon-bold' ).append( icon.element );
```

CKEditor 5 features use different icons. You can find them in the `@ckeditor/ckeditor5-icons` package.

You can also [add a custom icon to the dropdown](ui-library.md#setting-label-icon-and-tooltip) by providing the entire XML string of the icon

<a id="input">

## Input

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

The CKEditor 5 UI library contains some input elements. Usually, they are used in dropdowns and balloon panels, but you can also use them in the main toolbar.

To create them, use the [`LabeledFieldView`](../../api/module_ui_labeledfield_labeledfieldview-LabeledFieldView.md) class, which takes two parameters:

* An instance of the [`locale`](../../api/module_ui_labeledfield_labeledfieldview-LabeledFieldView.md#member-locale) class.
* A helper function, depending on the type of field you want to create.

<a id="text">

### Text

To create a text field, pass the [`createLabeledInputText()`](../../api/module_ui_labeledfield_utils.md#constant-createLabeledInputText) helper function as the second parameter to the [`LabeledFieldView`](../../api/module_ui_labeledfield_labeledfieldview-LabeledFieldView.md) class.

**NPM**

```js
import { createLabeledInputText, LabeledFieldView, Locale } from 'ckeditor5';

const locale = new Locale();

const textInput = new LabeledFieldView( locale, createLabeledInputText );
textInput.set( { label: 'Text input', value: 'Value of the input' } );
textInput.render();

document.getElementById( 'input-text' ).append( textInput.element );
```

**CDN**

```js
const { createLabeledInputText, LabeledFieldView, Locale } = CKEDITOR;

const locale = new Locale();

const textInput = new LabeledFieldView( locale, createLabeledInputText );
textInput.set( { label: 'Text input', value: 'Value of the input' } );
textInput.render();

document.getElementById( 'input-text' ).append( textInput.element );
```

<a id="number">

### Number

To create a number field, pass the [`createLabeledInputNumber()`](../../api/module_ui_labeledfield_utils.md#constant-createLabeledInputNumber) helper function as the second parameter to the [`LabeledFieldView`](../../api/module_ui_labeledfield_labeledfieldview-LabeledFieldView.md) class.

**NPM**

```js
import { createLabeledInputNumber, LabeledFieldView, Locale } from 'ckeditor5';

const locale = new Locale();

const numberInput = new LabeledFieldView( locale, createLabeledInputNumber );
numberInput.set( { label: 'Number input', value: 'Value of the input' } );
numberInput.render();

document.getElementById( 'input-number' ).append( numberInput.element );
```

**CDN**

```js
const { createLabeledInputNumber, LabeledFieldView, Locale } = CKEDITOR;

const locale = new Locale();

const numberInput = new LabeledFieldView( locale, createLabeledInputNumber );
numberInput.set( { label: 'Number input', value: 'Value of the input' } );
numberInput.render();

document.getElementById( 'input-number' ).append( numberInput.element );
```

<a id="states-3">

### States

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

Similarly to buttons, inputs can be enabled or disabled. The property names remain the same.

<a id="enabled-3">

#### Enabled

Inputs are enabled by default. You can also set the state explicitly by adding the [`isEnabled`](../../api/module_ui_labeledfield_labeledfieldview-LabeledFieldView.md#member-isEnabled) property with a `true` value.

**NPM**

```js
import { createLabeledInputText, LabeledFieldView, Locale } from 'ckeditor5';

const locale = new Locale();

const enabledInput = new LabeledFieldView( locale, createLabeledInputText );
enabledInput.set( { label: 'Enabled state', isEnabled: true } );
enabledInput.render();

document.getElementById( 'input-enabled' ).append( enabledInput.element );
```

**CDN**

```js
const { createLabeledInputText, LabeledFieldView, Locale } = CKEDITOR;

const locale = new Locale();

const enabledInput = new LabeledFieldView( locale, createLabeledInputText );
enabledInput.set( { label: 'Enabled state', isEnabled: true } );
enabledInput.render();

document.getElementById( 'input-enabled' ).append( enabledInput.element );
```

<a id="disabled-3">

#### Disabled

To disable an input, set the [`isEnabled`](../../api/module_ui_labeledfield_labeledfieldview-LabeledFieldView.md#member-isEnabled) property to `false`. It prevents the input from getting users’ data.

**NPM**

```js
import { createLabeledInputText, LabeledFieldView, Locale } from 'ckeditor5';

const locale = new Locale();

const disabledInput = new LabeledFieldView( locale, createLabeledInputText );
disabledInput.set( { label: 'Disabled state', isEnabled: false } );
disabledInput.render();

document.getElementById( 'input-disabled' ).append( disabledInput.element );
```

**CDN**

```js
const { createLabeledInputText, LabeledFieldView, Locale } = CKEDITOR;

const locale = new Locale();

const disabledInput = new LabeledFieldView( locale, createLabeledInputText );
disabledInput.set( { label: 'Disabled state', isEnabled: false } );
disabledInput.render();

document.getElementById( 'input-disabled' ).append( disabledInput.element );
```

<a id="search">

## Search

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

A search component allows you to filter a list of items based on a specified query. It consists of several components and interfaces:

* To create it, use the main [`SearchTextView`](../../api/module_ui_search_text_searchtextview-SearchTextView.md) class.
* The [`queryView`](../../api/module_ui_search_text_searchtextview-SearchTextView.md#member-queryView) property allows the user to enter the search query.
* The [`infoView`](../../api/module_ui_search_text_searchtextview-SearchTextView.md#member-infoView) property displays additional information about the search results.
* The [`filteredView`](../../api/module_ui_search_text_searchtextview-SearchTextView.md#member-filteredView) is a view filtered by the search query. Remember to specify the [`filter()`](../../api/module_ui_search_filteredview-FilteredView.md#function-filter) and [`focus()`](../../api/module_ui_search_filteredview-FilteredView.md#function-focus) methods for this view.

Some sub-components and classes that can help with better presentation of the results:

* The [`SearchResultsView`](../../api/module_ui_search_searchresultsview-SearchResultsView.md) component hosts the filtered and the information views. It is a sub-component of the [`SearchTextView`](../../api/module_ui_search_text_searchtextview-SearchTextView.md).
* The [`AutocompleteView`](../../api/module_ui_autocomplete_autocompleteview-AutocompleteView.md) component lists proposed results when the user starts typing and hides them when it is out of focus. It extends the [`SearchTextView`](../../api/module_ui_search_text_searchtextview-SearchTextView.md) class.
* To group list items, you can use the [`ListItemGroupView`](../../api/module_ui_list_listitemgroupview-ListItemGroupView.md) class.
* To highlight some results (or some text in general), you can use the [`HighlightedTextView`](../../api/module_ui_highlightedtext_highlightedtextview-HighlightedTextView.md) class.

**NPM**

```js
import { ListView, SearchTextView, Locale } from 'ckeditor5';

const locale = new Locale();

const filteredView = new ListView();
filteredView.filter = () => {
	return {
		resultsCount: 1,
		totalItemsCount: 5
	};
};

const searchView = new SearchTextView( locale, {
	filteredView,
	queryView: {
		label: 'Label'
	}
} );

searchView.render();

document.querySelector( '.ui-search' ).append( searchView.element );
```

**CDN**

```js
const { ListView, SearchTextView, Locale } = CKEDITOR;

const locale = new Locale();

const filteredView = new ListView();
filteredView.filter = () => {
	return {
		resultsCount: 1,
		totalItemsCount: 5
	};
};

const searchView = new SearchTextView( locale, {
	filteredView,
	queryView: {
		label: 'Label'
	}
} );

searchView.render();

document.querySelector( '.ui-search' ).append( searchView.element );
```

Check out the [AI Assistant](../../features/ai/ai-assistant/ai-assistant-overview.md#demo) feature to see how all the UI pieces work together in a more complex setup.

<a id="spinner">

## Spinner

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

You can use a spinner to indicate some loading process. There is only one essential property here – [`isVisible`](../../api/module_ui_spinner_spinnerview-SpinnerView.md#member-isVisible). As the name suggests, it controls whether the component is visible. The default is `false`.

**NPM**

```js
import { SpinnerView } from 'ckeditor5';

const spinner = new SpinnerView();

spinner.set( { isVisible: true } );
spinner.render();

document.querySelector( '.ui-spinner' ).append( spinner.element );
```

**CDN**

```js
const { SpinnerView } = CKEDITOR;

const spinner = new SpinnerView();

spinner.set( { isVisible: true } );
spinner.render();

document.querySelector( '.ui-spinner' ).append( spinner.element );
```

<a id="textarea">

## Textarea

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

The textarea is a component for inserting long blocks of text. You can specify the visible height of the component using the [`minRows`](../../api/module_ui_textarea_textareaview-TextareaView.md#member-minRows) property. Specify the [`maxRows`](../../api/module_ui_textarea_textareaview-TextareaView.md#member-minRows) property if you do not want the component to exceed a certain height. Textarea dimensions do not need to be fixed, and you can allow users to change them with the [`resize`](../../api/module_ui_textarea_textareaview-TextareaView.md#member-resize) option. By default, the property is set to `'none'`, and resizing is not allowed.

**NPM**

```js
import { TextareaView } from 'ckeditor5';

const textarea = new TextareaView();

textarea.set( {
	minRows: 4,
	maxRows: 10,
	resize: 'horizontal'
} );
textarea.render();

document.querySelector( '.ui-textarea' ).append( textarea.element );
```

**CDN**

```js
const { TextareaView } = CKEDITOR;

const textarea = new TextareaView();

textarea.set( {
	minRows: 4,
	maxRows: 10,
	resize: 'horizontal'
} );
textarea.render();

document.querySelector( '.ui-textarea' ).append( textarea.element );
```

<a id="toolbar-2">

## Toolbar

A toolbar is a base for other components. Usually, you would put other UI elements inside it. It can also be nested inside a balloon or dropdown. You can use the [`ToolbarView`](../../api/module_ui_toolbar_toolbarview-ToolbarView.md) class to instantiate a toolbar.

<a id="text-2">

### Text

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

You can put different UI elements inside a toolbar. A simple text node is one example. You can use the [`items`](../../api/module_ui_toolbar_toolbarview-ToolbarView.md#member-items) property to add a component to a toolbar.

**NPM**

```js
import { ToolbarView, View,	Locale } from 'ckeditor5';

const locale = new Locale();

const text = new View();
text.element = document.createTextNode( 'Toolbar text' );

const toolbarText = new ToolbarView( locale );
toolbarText.items.add( text );
toolbarText.render();

document.getElementById( 'toolbar-text' ).append( toolbarText.element );
```

**CDN**

```js
const { ToolbarView, View,	Locale } = CKEDITOR;

const locale = new Locale();

const text = new View();
text.element = document.createTextNode( 'Toolbar text' );

const toolbarText = new ToolbarView( locale );
toolbarText.items.add( text );
toolbarText.render();

document.getElementById( 'toolbar-text' ).append( toolbarText.element );
```

<a id="button-2">

### Button

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

You can place any previously listed button inside a toolbar.

**NPM**

```js
import { ButtonView, ToolbarView, Locale } from 'ckeditor5';

const locale = new Locale();

const button = new ButtonView();
button.set( { label: 'Button', withText: true } );

const toolbarButton = new ToolbarView( locale );
toolbarButton.items.add( button );
toolbarButton.render();

document.getElementById( 'toolbar-button' ).append( toolbarButton.element );
```

**CDN**

```js
const { ButtonView, ToolbarView, Locale } = CKEDITOR;

const locale = new Locale();

const button = new ButtonView();
button.set( { label: 'Button', withText: true } );

const toolbarButton = new ToolbarView( locale );
toolbarButton.items.add( button );
toolbarButton.render();

document.getElementById( 'toolbar-button' ).append( toolbarButton.element );
```

<a id="wrap">

### Wrap

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

A toolbar automatically wraps if you add more items and the space is limited.

**NPM**

```js
import { ButtonView, ToolbarView, Locale } from 'ckeditor5';

const locale = new Locale();

function createButton() {
	const button = new ButtonView();
	button.set( { label: 'Button', withText: true } );
	return button;
}

const buttons = [ createButton(), createButton(), createButton() ];

const toolbarWrap = new ToolbarView( locale );
buttons.forEach( button => toolbarWrap.items.add( button ) );
toolbarWrap.render();
toolbarWrap.element.style.width = '150px';

document.getElementById( 'toolbar-wrap' ).append( toolbarWrap.element );
```

**CDN**

```js
const { ButtonView, ToolbarView, Locale } = CKEDITOR;

const locale = new Locale();

function createButton() {
	const button = new ButtonView();
	button.set( { label: 'Button', withText: true } );
	return button;
}

const buttons = [ createButton(), createButton(), createButton() ];

const toolbarWrap = new ToolbarView( locale );
buttons.forEach( button => toolbarWrap.items.add( button ) );
toolbarWrap.render();
toolbarWrap.element.style.width = '150px';

document.getElementById( 'toolbar-wrap' ).append( toolbarWrap.element );
```

<a id="separator">

### Separator

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

You can divide toolbar elements with a separator to create logically connected groups. To instantiate a separator, use the [`ToolbarSeparatorView`](../../api/module_ui_toolbar_toolbarseparatorview-ToolbarSeparatorView.md) class. Adding the created instance between desired components will separate them visually.

**NPM**

```js
import { ButtonView, ToolbarSeparatorView, ToolbarView,	Locale } from 'ckeditor5';

const locale = new Locale();

function createButton() {
	const button = new ButtonView();
	button.set( { label: 'Button', withText: true } );
	return button;
}

const separator = new ToolbarSeparatorView();

const items = [ createButton(), separator, createButton() ];

const toolbarSeparator = new ToolbarView( locale );
items.forEach( item => toolbarSeparator.items.add( item ) );
toolbarSeparator.render();

document.getElementById( 'toolbar-separator' ).append( toolbarSeparator.element );
```

**CDN**

```js
const { ButtonView, ToolbarSeparatorView, ToolbarView,	Locale } = CKEDITOR;

const locale = new Locale();

function createButton() {
	const button = new ButtonView();
	button.set( { label: 'Button', withText: true } );
	return button;
}

const separator = new ToolbarSeparatorView();

const items = [ createButton(), separator, createButton() ];

const toolbarSeparator = new ToolbarView( locale );
items.forEach( item => toolbarSeparator.items.add( item ) );
toolbarSeparator.render();

document.getElementById( 'toolbar-separator' ).append( toolbarSeparator.element );
```

<a id="multi-row">

### Multi-row

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

By default, a toolbar has one row. However, it can span into multiple rows. You can instantiate a line break with the [`ToolbarLineBreakView`](../../api/module_ui_toolbar_toolbarlinebreakview-ToolbarLineBreakView.md) class. Adding the created instance after a desired component will place the following UI elements into the next row.

**NPM**

```js
import { ButtonView, ToolbarLineBreakView, ToolbarView, Locale } from 'ckeditor5';

const locale = new Locale();

function createButton() {
	const button = new ButtonView();
	button.set( { label: 'Button', withText: true } );
	return button;
}

const newLine = new ToolbarLineBreakView( locale );

const items = [ createButton(), newLine, createButton() ];

const toolbarMultiRow = new ToolbarView( locale );
items.forEach( item => toolbarMultiRow.items.add( item ) );
toolbarMultiRow.render();

document.getElementById( 'toolbar-multirow' ).append( toolbarMultiRow.element );
```

**CDN**

```js
const { ButtonView, ToolbarLineBreakView, ToolbarView, Locale } = CKEDITOR;

const locale = new Locale();

function createButton() {
	const button = new ButtonView();
	button.set( { label: 'Button', withText: true } );
	return button;
}

const newLine = new ToolbarLineBreakView( locale );

const items = [ createButton(), newLine, createButton() ];

const toolbarMultiRow = new ToolbarView( locale );
items.forEach( item => toolbarMultiRow.items.add( item ) );
toolbarMultiRow.render();

document.getElementById( 'toolbar-multirow' ).append( toolbarMultiRow.element );
```

<a id="compact">

### Compact

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

There is also a smaller version of a toolbar. To get a compact toolbar, set the [`isCompact`](../../api/module_ui_toolbar_toolbarview-ToolbarView.md#member-isCompact) property to `true`.

**NPM**

```js
import { ButtonView, ToolbarView, Locale } from 'ckeditor5';

const locale = new Locale();

const button = new ButtonView();
button.set( { label: 'Button', withText: true } );

const toolbarCompact = new ToolbarView( locale );
toolbarCompact.isCompact = true;
toolbarCompact.items.add( button );
toolbarCompact.render();

document.getElementById( 'toolbar-compact' ).append( toolbarCompact.element );
```

**CDN**

```js
const { ButtonView, ToolbarView, Locale } = CKEDITOR;

const locale = new Locale();

const button = new ButtonView();
button.set( { label: 'Button', withText: true } );

const toolbarCompact = new ToolbarView( locale );
toolbarCompact.isCompact = true;
toolbarCompact.items.add( button );
toolbarCompact.render();

document.getElementById( 'toolbar-compact' ).append( toolbarCompact.element );
```

---

Full index of the CKEditor 5 documentation: [llms.txt](../../../llms.txt)
