Skip to content

feat(ui): the toolbox became vertical #2014

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 36 commits into from
Apr 25, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
11c0405
the popover component, vertical toolbox
neSpecc Jan 13, 2022
015f409
toolbox position improved
neSpecc Jan 13, 2022
229b9a2
popover width improved
neSpecc Jan 13, 2022
9a15cf5
always show the plus button
neSpecc Feb 2, 2022
3a3403e
search field added
neSpecc Feb 5, 2022
06a5766
Merge branch 'next' into feat/vertical-toolbox
neSpecc Feb 10, 2022
a020ca5
search input in popover
neSpecc Mar 2, 2022
a005b07
trying to create mobile toolbox
neSpecc Mar 12, 2022
e7b2698
Merge branch 'next' into feat/vertical-toolbox
neSpecc Mar 13, 2022
2bc1427
Merge branch 'next' into feat/vertical-toolbox
neSpecc Apr 5, 2022
c29d244
feat(toolbox): popover adapted for mobile devices (#2004)
TatianaFomina Apr 7, 2022
f947d36
Vertical toolbox fixes (#2017)
TatianaFomina Apr 14, 2022
5e00998
Extend element interface to avoid ts errors
TatianaFomina Apr 16, 2022
f3e253f
Do not subscribe to block hovered if mobile
TatianaFomina Apr 16, 2022
262baee
Add unsubscribing from overlay click event
TatianaFomina Apr 16, 2022
0c006d6
Rename isMobile to isMobileScreen
TatianaFomina Apr 16, 2022
adb8b77
Cleanup
TatianaFomina Apr 16, 2022
ae2ac42
fix: popover opening direction (#2022)
TatianaFomina Apr 17, 2022
d44b9a9
Update src/components/flipper.ts
TatianaFomina Apr 17, 2022
83a8c86
Fixes
TatianaFomina Apr 17, 2022
054f23d
Merge branch 'next' into feat/vertical-toolbox
TatianaFomina Apr 17, 2022
6a31e72
Merge branch 'feat/vertical-toolbox' of https://github.com/codex-team…
TatianaFomina Apr 17, 2022
2bc4c80
Fix test
TatianaFomina Apr 17, 2022
b43a22a
Clear search on popover hide
TatianaFomina Apr 18, 2022
7c2cb80
Fix popover width
TatianaFomina Apr 18, 2022
9c2d665
Fix for tests
TatianaFomina Apr 18, 2022
ede63a4
Update todos
TatianaFomina Apr 18, 2022
b5dd459
Linter fixes
TatianaFomina Apr 19, 2022
061b2c9
rm todo about beforeInsert
neSpecc Apr 19, 2022
ca7b2ab
i18n for search labels done
neSpecc Apr 19, 2022
cc0530c
rm methods for hiding/showing of +
neSpecc Apr 19, 2022
c36eca2
some code style update
neSpecc Apr 19, 2022
3a98e9b
Merge branch 'next' into feat/vertical-toolbox
neSpecc Apr 22, 2022
04376f9
Update CHANGELOG.md
neSpecc Apr 22, 2022
25b06c0
make the list items a little bit compact
neSpecc Apr 22, 2022
70fd937
fix z-index issue caused by block-appearing animation
neSpecc Apr 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/assets/search.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 34 additions & 41 deletions src/components/flipper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,22 @@ export interface FlipperOptions {
items?: HTMLElement[];

/**
* Defines arrows usage. By default Flipper leafs items also via RIGHT/LEFT.
*
* true by default
*
* Pass 'false' if you don't need this behaviour
* (for example, Inline Toolbar should be closed by arrows,
* because it means caret moving with selection clearing)
* Optional callback for button click
*/
allowArrows?: boolean;
activateCallback?: (item: HTMLElement) => void;

/**
* Optional callback for button click
* List of keys allowed for handling.
* Can include codes of the following keys:
* - Tab
* - Enter
* - Arrow up
* - Arrow down
* - Arrow right
* - Arrow left
* If not specified all keys are enabled
*/
activateCallback?: (item: HTMLElement) => void;
allowedKeys?: number[];
}

/**
Expand All @@ -53,11 +55,9 @@ export default class Flipper {
private activated = false;

/**
* Flag that allows arrows usage to flip items
*
* @type {boolean}
* List codes of the keys allowed for handling
*/
private readonly allowArrows: boolean = true;
private readonly allowedKeys: number[];

/**
* Call back for button click/enter
Expand All @@ -68,9 +68,9 @@ export default class Flipper {
* @param {FlipperOptions} options - different constructing settings
*/
constructor(options: FlipperOptions) {
this.allowArrows = _.isBoolean(options.allowArrows) ? options.allowArrows : true;
this.iterator = new DomIterator(options.items, options.focusedItemClass);
this.activateCallback = options.activateCallback;
this.allowedKeys = options.allowedKeys || Flipper.usedKeys;
}

/**
Expand Down Expand Up @@ -120,15 +120,6 @@ export default class Flipper {
document.removeEventListener('keydown', this.onKeyDown);
}

/**
* Return current focused button
*
* @returns {HTMLElement|null}
*/
public get currentItem(): HTMLElement|null {
return this.iterator.currentItem;
}

/**
* Focus first item
*/
Expand All @@ -142,13 +133,22 @@ export default class Flipper {
*/
public flipLeft(): void {
this.iterator.previous();
this.flipCallback();
}

/**
* Focuses next flipper iterator item
*/
public flipRight(): void {
this.iterator.next();
this.flipCallback();
}

/**
* Return true if some button is focused
*/
public hasFocus(): boolean {
return !!this.iterator.currentItem;
}

/**
Expand Down Expand Up @@ -206,23 +206,7 @@ export default class Flipper {
* @returns {boolean}
*/
private isEventReadyForHandling(event: KeyboardEvent): boolean {
const handlingKeyCodeList = [
_.keyCodes.TAB,
_.keyCodes.ENTER,
];

const isCurrentItemIsFocusedInput = this.iterator.currentItem == document.activeElement;

if (this.allowArrows && !isCurrentItemIsFocusedInput) {
handlingKeyCodeList.push(
_.keyCodes.LEFT,
_.keyCodes.RIGHT,
_.keyCodes.UP,
_.keyCodes.DOWN
);
}

return this.activated && handlingKeyCodeList.indexOf(event.keyCode) !== -1;
return this.activated && this.allowedKeys.indexOf(event.keyCode) !== -1;
}

/**
Expand Down Expand Up @@ -266,4 +250,13 @@ export default class Flipper {
event.preventDefault();
event.stopPropagation();
}

/**
* Fired after flipping in any direction
*/
private flipCallback(): void {
if (this.iterator.currentItem) {
this.iterator.currentItem.scrollIntoViewIfNeeded();
}
}
}
4 changes: 3 additions & 1 deletion src/components/i18n/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
},
"toolbar": {
"toolbox": {
"Add": ""
"Add": "",
"Filter": "",
"Noting found": ""
}
}
},
Expand Down
4 changes: 4 additions & 0 deletions src/components/modules/blockManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,10 @@ export default class BlockManager extends Module {
});
}

/**
* @todo emit beforeInsert
*/

this._blocks.insert(newIndex, block, replace);

/**
Expand Down
88 changes: 57 additions & 31 deletions src/components/modules/toolbar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import Toolbox, { ToolboxEvent } from '../../ui/toolbox';
* @todo Tab on non-empty block should open Block Settings of the hoveredBlock (not where caret is set)
* - make Block Settings a standalone module
*
* @todo - Keyboard-only mode bug:
* press Tab, flip to the Checkbox. press Enter (block will be added), Press Tab
* (Block Tunes will be opened with Move up focused), press Enter, press Tab ———— both Block Tunes and Toolbox will be opened
*
* @todo TESTCASE - show toggler after opening and closing the Inline Toolbar
* @todo TESTCASE - Click outside Editor holder should close Toolbar and Clear Focused blocks
* @todo TESTCASE - Click inside Editor holder should close Toolbar and Clear Focused blocks
Expand All @@ -33,11 +37,7 @@ interface ToolbarNodes {
content: HTMLElement;
actions: HTMLElement;

// Content Zone
plusButton: HTMLElement;

// Actions Zone
blockActionsButtons: HTMLElement;
settingsToggler: HTMLElement;
}
/**
Expand Down Expand Up @@ -137,14 +137,11 @@ export default class Toolbar extends Module<ToolbarNodes> {
toolbarOpened: 'ce-toolbar--opened',
openedToolboxHolderModifier: 'codex-editor--toolbox-opened',

// Content Zone
plusButton: 'ce-toolbar__plus',
plusButtonShortcut: 'ce-toolbar__plus-shortcut',
plusButtonHidden: 'ce-toolbar__plus--hidden',

// Actions Zone
blockActionsButtons: 'ce-toolbar__actions-buttons',
settingsToggler: 'ce-toolbar__settings-btn',
settingsTogglerHidden: 'ce-toolbar__settings-btn--hidden',
};
}

Expand All @@ -159,8 +156,6 @@ export default class Toolbar extends Module<ToolbarNodes> {

/**
* Plus Button public methods
*
* @returns {{hide: function(): void, show: function(): void}}
*/
public get plusButton(): { hide: () => void; show: () => void } {
return {
Expand All @@ -182,11 +177,14 @@ export default class Toolbar extends Module<ToolbarNodes> {
close: () => void;
open: () => void;
toggle: () => void;
flipperHasFocus: boolean;
hasFocus: () => boolean;
} {
return {
opened: this.toolboxInstance.opened,
close: (): void => this.toolboxInstance.close(),
close: (): void => {
this.toolboxInstance.close();
this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock);
},
open: (): void => {
/**
* Set current block to cover the case when the Toolbar showed near hovered Block but caret is set to another Block.
Expand All @@ -196,14 +194,12 @@ export default class Toolbar extends Module<ToolbarNodes> {
this.toolboxInstance.open();
},
toggle: (): void => this.toolboxInstance.toggle(),
flipperHasFocus: this.toolboxInstance.flipperHasFocus,
hasFocus: (): boolean => this.toolboxInstance.hasFocus(),
};
}

/**
* Block actions appearance manipulations
*
* @returns {{hide: function(): void, show: function(): void}}
*/
private get blockActions(): { hide: () => void; show: () => void } {
return {
Expand All @@ -216,6 +212,16 @@ export default class Toolbar extends Module<ToolbarNodes> {
};
}

/**
* Methods for working with Block Tunes toggler
*/
private get blockTunesToggler(): { hide: () => void; show: () => void } {
return {
hide: (): void => this.nodes.settingsToggler.classList.add(this.CSS.settingsTogglerHidden),
show: (): void => this.nodes.settingsToggler.classList.remove(this.CSS.settingsTogglerHidden),
};
}

/**
* Toggles read-only mode
*
Expand Down Expand Up @@ -276,15 +282,26 @@ export default class Toolbar extends Module<ToolbarNodes> {
/**
* Move Toolbar to the Top coordinate of Block
*/
this.nodes.wrapper.style.transform = `translate3D(0, ${Math.floor(toolbarY)}px, 0)`;
this.nodes.wrapper.style.top = `${Math.floor(toolbarY)}px`;

/**
* Plus Button should be shown only for __empty__ __default__ block
*
* @todo remove methods for hiding/showing the Plus Button as well
*/
if (block.tool.isDefault && block.isEmpty) {
this.plusButton.show();
// if (block.tool.isDefault && block.isEmpty) {
// this.plusButton.show();
// } else {
// this.plusButton.hide();
// }

/**
* Do not show Block Tunes Toggler near single and empty block
*/
if (this.Editor.BlockManager.blocks.length === 1 && block.isEmpty) {
this.blockTunesToggler.hide();
} else {
this.plusButton.hide();
this.blockTunesToggler.show();
}

this.open();
Expand Down Expand Up @@ -381,13 +398,11 @@ export default class Toolbar extends Module<ToolbarNodes> {
* - Remove Block Button
* - Settings Panel
*/
this.nodes.blockActionsButtons = $.make('div', this.CSS.blockActionsButtons);
this.nodes.settingsToggler = $.make('span', this.CSS.settingsToggler);
const settingsIcon = $.svg('dots', 16, 16);

$.append(this.nodes.settingsToggler, settingsIcon);
$.append(this.nodes.blockActionsButtons, this.nodes.settingsToggler);
$.append(this.nodes.actions, this.nodes.blockActionsButtons);
$.append(this.nodes.actions, this.nodes.settingsToggler);

this.tooltip.onHover(
this.nodes.settingsToggler,
Expand All @@ -400,7 +415,7 @@ export default class Toolbar extends Module<ToolbarNodes> {
/**
* Appending Toolbar components to itself
*/
$.append(this.nodes.content, this.makeToolbox());
$.append(this.nodes.actions, this.makeToolbox());
$.append(this.nodes.actions, this.Editor.BlockSettings.nodes.wrapper);

/**
Expand All @@ -419,6 +434,10 @@ export default class Toolbar extends Module<ToolbarNodes> {
this.toolboxInstance = new Toolbox({
api: this.Editor.API.methods,
tools: this.Editor.Tools.blockTools,
i18nLabels: {
filter: I18n.ui(I18nInternalNS.ui.toolbar.toolbox, 'Filter'),
nothingFound: I18n.ui(I18nInternalNS.ui.toolbar.toolbox, 'Noting found'),
},
});

this.toolboxInstance.on(ToolboxEvent.Opened, () => {
Expand Down Expand Up @@ -487,18 +506,25 @@ export default class Toolbar extends Module<ToolbarNodes> {
}, true);

/**
* Subscribe to the 'block-hovered' event
* Subscribe to the 'block-hovered' event if currenct view is not mobile
*
* @see https://github.com/codex-team/editor.js/issues/1972
*/
this.eventsDispatcher.on(this.Editor.UI.events.blockHovered, (data: {block: Block}) => {
if (!_.isMobileScreen()) {
/**
* Do not move toolbar if Block Settings or Toolbox opened
* Subscribe to the 'block-hovered' event
*/
if (this.Editor.BlockSettings.opened || this.toolboxInstance.opened) {
return;
}
this.eventsDispatcher.on(this.Editor.UI.events.blockHovered, (data: {block: Block}) => {
/**
* Do not move toolbar if Block Settings or Toolbox opened
*/
if (this.Editor.BlockSettings.opened || this.toolboxInstance.opened) {
return;
}

this.moveAndOpen(data.block);
});
this.moveAndOpen(data.block);
});
}
}

/**
Expand Down
5 changes: 4 additions & 1 deletion src/components/modules/toolbar/inline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,10 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
private enableFlipper(): void {
this.flipper = new Flipper({
focusedItemClass: this.CSS.focusedButton,
allowArrows: false,
allowedKeys: [
_.keyCodes.ENTER,
_.keyCodes.TAB,
],
});
}
}
6 changes: 3 additions & 3 deletions src/components/modules/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,15 @@ export default class UI extends Module<UINodes> {
* Toolbar has internal module (Toolbox) that has own Flipper,
* so we check it manually
*/
if (this.Editor.Toolbar.toolbox.flipperHasFocus) {
if (this.Editor.Toolbar.toolbox.hasFocus()) {
return true;
}

return Object.entries(this.Editor).filter(([moduleName, moduleClass]) => {
return moduleClass.flipper instanceof Flipper;
})
.some(([moduleName, moduleClass]) => {
return moduleClass.flipper.currentItem;
return moduleClass.flipper.hasFocus();
});
}

Expand Down Expand Up @@ -385,7 +385,7 @@ export default class UI extends Module<UINodes> {
*/
private watchBlockHoveredEvents(): void {
/**
* Used to not to emit the same block multiple times to the 'block-hovered' event on every mousemove
* Used to not emit the same block multiple times to the 'block-hovered' event on every mousemove
*/
let blockHoveredEmitted;

Expand Down
Loading