The UI component system provides the visual interface for mention functionality including dropdown lists, item views, and DOM wrapper components.
The main dropdown view that displays mention suggestions as a scrollable list.
/**
* The main mention dropdown view extending ListView.
* Manages mention suggestion display and selection.
*/
class MentionsView extends ListView {
/**
* Currently selected mention item.
*/
selected: MentionListItemView | undefined;
/**
* Preferred position for dropdown positioning.
*/
position: string | undefined;
/**
* Selects the first item in the list.
*/
selectFirst(): void;
/**
* Selects the next item with cycling behavior.
* If last item is selected, cycles to first item.
*/
selectNext(): void;
/**
* Selects the previous item with cycling behavior.
* If first item is selected, cycles to last item.
*/
selectPrevious(): void;
/**
* Selects item at the specified index with boundary handling.
* @param index - Index of item to select (handles out-of-bounds)
*/
select(index: number): void;
/**
* Triggers the execute event on the currently selected item.
*/
executeSelected(): void;
}Usage Examples:
import { MentionsView } from "@ckeditor/ckeditor5-mention";
// Create mentions view
const mentionsView = new MentionsView(editor.locale);
// Handle navigation
mentionsView.selectFirst();
mentionsView.selectNext();
mentionsView.executeSelected();
// Listen for selection events
mentionsView.on('execute', (evt, data) => {
console.log('Selected mention:', data.item, data.marker);
});Individual list item view for mention suggestions with highlight functionality.
/**
* Individual list item view for mention suggestions.
* Extends ListItemView with mention-specific functionality.
*/
class MentionListItemView extends ListItemView {
/**
* The mention feed item associated with this view.
*/
item: MentionFeedItem;
/**
* The marker character associated with this mention.
*/
marker: string;
/**
* Highlights the item (adds visual selection state).
*/
highlight(): void;
/**
* Removes highlight from the item.
*/
removeHighlight(): void;
}Usage Examples:
import { MentionListItemView } from "@ckeditor/ckeditor5-mention";
// Create list item
const listItem = new MentionListItemView(editor.locale);
listItem.item = { id: '@alice', text: 'Alice Johnson' };
listItem.marker = '@';
// Handle highlighting
listItem.highlight();
listItem.removeHighlight();
// Listen for execution
listItem.on('execute', () => {
console.log('Item executed:', listItem.item);
});Wrapper view for custom DOM elements in mention lists, providing button-like behavior.
/**
* Wraps DOM elements for use in mention lists with button-like behavior.
* Allows rendering custom HTML elements in the mention dropdown.
*/
class MentionDomWrapperView extends View {
/**
* The wrapped HTML element.
*/
domElement: HTMLElement;
/**
* Controls whether the wrapper is in "on" state (highlighted).
* @observable
* @default false
*/
isOn: boolean;
/**
* Creates a new DOM wrapper view.
* @param locale - Editor locale
* @param domElement - HTML element to wrap
*/
constructor(locale: Locale, domElement: HTMLElement);
/**
* Renders the wrapped DOM element.
*/
render(): void;
/**
* Focuses the wrapped DOM element.
*/
focus(): void;
}Usage Examples:
import { MentionDomWrapperView } from "@ckeditor/ckeditor5-mention";
// Create custom DOM element
const customElement = document.createElement('div');
customElement.innerHTML = `
<img src="/avatar.jpg" alt="User" />
<span>Alice Johnson</span>
<small>Engineering</small>
`;
// Wrap in mention view
const wrapper = new MentionDomWrapperView(editor.locale, customElement);
// Handle state changes
wrapper.on('change:isOn', (evt, name, isOn) => {
console.log('Wrapper highlight state:', isOn);
});
// Handle clicks
wrapper.on('execute', () => {
console.log('Custom element clicked');
});
// Render and focus
wrapper.render();
wrapper.focus();// Using MentionDomWrapperView with custom renderer
const itemRenderer: MentionItemRenderer = (item) => {
// Create rich HTML element
const element = document.createElement('div');
element.className = 'custom-mention-item';
element.innerHTML = `
<div class="mention-avatar">
<img src="${item.avatar}" alt="${item.text}" />
</div>
<div class="mention-content">
<div class="mention-name">${item.text}</div>
<div class="mention-role">${item.role}</div>
</div>
<div class="mention-status ${item.online ? 'online' : 'offline'}"></div>
`;
return element; // Will be wrapped in MentionDomWrapperView automatically
};
// Use in feed configuration
const feedConfig: MentionFeed = {
marker: '@',
feed: fetchUsers,
itemRenderer: itemRenderer
};// The MentionsView supports multiple positioning strategies
const positioningOptions = {
// Southeast of caret (default)
'caret_se': 'Position below and to the right',
// Northeast of caret
'caret_ne': 'Position above and to the right',
// Southwest of caret
'caret_sw': 'Position below and to the left',
// Northwest of caret
'caret_nw': 'Position above and to the left'
};
// Position is automatically determined but can be influenced
// by the editor's UI language direction and available space// The MentionsView handles these keyboard interactions automatically:
const keyboardControls = {
'ArrowDown': 'selectNext()',
'ArrowUp': 'selectPrevious()',
'Enter': 'executeSelected()', // Default commit key
'Tab': 'executeSelected()', // Default commit key
'Escape': 'Hide dropdown'
};
// Custom commit keys can be configured
const config: MentionConfig = {
feeds: [/* ... */],
commitKeys: [13, 9, 32] // Enter, Tab, Space
};// MentionsView automatically handles scrolling for long lists
const longFeedConfig: MentionFeed = {
marker: '@',
feed: async (searchString) => {
// Return large dataset
const users = await fetchAllUsers(searchString);
return users; // Could be 100+ items
},
dropdownLimit: 10 // Only show 10 at a time
};
// The view will:
// 1. Limit visible items to dropdownLimit
// 2. Automatically scroll to selected items
// 3. Handle keyboard navigation within visible area// All UI components include accessibility features:
const accessibilityFeatures = {
// MentionsView
'tabindex': '-1',
'class': 'ck-mentions',
'role': 'listbox',
// MentionListItemView
'role': 'option',
'aria-selected': 'true|false',
// MentionDomWrapperView
'class': 'ck-button ck-on|ck-off',
'tabindex': '0'
};
// Screen reader support is built-in// CSS classes applied by UI components
const cssClasses = {
// Main dropdown
'.ck-mentions': 'Main mentions dropdown container',
// Balloon panel
'.ck-mention-balloon': 'Contextual balloon containing dropdown',
// List items
'.ck-button': 'Applied to all mention list items',
'.ck-on': 'Applied to highlighted/selected items',
'.ck-off': 'Applied to non-highlighted items',
// Mention spans in content
'.mention': 'Applied to mention spans in editor content'
};
// Custom CSS can override these styles// Execute event when item is selected
mentionsView.on('execute', (evt, data) => {
console.log('Item:', data.item);
console.log('Marker:', data.marker);
});// Execute event when item is activated
listItemView.on('execute', () => {
console.log('List item executed');
});// State change events
wrapperView.on('change:isOn', (evt, name, isOn) => {
console.log('Highlight state changed:', isOn);
});
// Click/execution events
wrapperView.on('execute', () => {
console.log('Wrapped element executed');
});