Skip to content
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

feat(inline-tools): Inline tools rendered as popover #2718

Open
wants to merge 75 commits into
base: next
Choose a base branch
from

Conversation

TatianaFomina
Copy link
Contributor

@TatianaFomina TatianaFomina commented May 11, 2024

New Inline Tools

Inline tools now use popover as well as Toolbox and Block Tunes 💪

image

What's done

  • PopoverInline class added. It extends PopoverDesktop but makes it horizontal (and adds few features)
  • Popover styles are updated
  • Removed redundant styles

ToDo

  • Tests
  • Rewrite built-in inline tools to new api

Copy link
Member

@neSpecc neSpecc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • link icon is bigger that others
  • in header block, Link tool goes after Marker. Why?
  • "Conver to" tooltip is missed
  • Current state of buttons is highlighted differently

image

  • Bold tool is not working in Safari. Nothing happened on clicks.
  • All icons have different size on Mobile version
    image

/**
* Handle 'mousedown' instead of 'click' event to prevent unwanted focus loss in safari
*/
this.listeners.on(this.nodes.popoverContainer, 'mousedown', (event: Event) => this.handleClick(event));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it work on touch devices?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checked, works

const totalLeftOffset = this.offsetLeft + itemOffsetLeft;

nestedPopoverEl.style.setProperty(
'--trigger-item-left',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it would be better to put all the properties into some constants or enum?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added enum with variables

@TatianaFomina
Copy link
Contributor Author

TatianaFomina commented Jun 8, 2024

@neSpecc

  • in header block, Link tool goes after Marker. Why?

it's hardcoded in index.html

Changed

src/components/modules/api/selection.ts Outdated Show resolved Hide resolved
src/components/modules/api/tools.ts Outdated Show resolved Hide resolved
src/components/utils/blocks.ts Outdated Show resolved Hide resolved
src/components/utils/blocks.ts Outdated Show resolved Hide resolved
Copy link
Member

@neSpecc neSpecc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I can't change a link url. Input is not focusable on clicks.
image

@@ -69,7 +69,6 @@ export default class DragNDrop extends Module {
private async processDrop(dropEvent: DragEvent): Promise<void> {
const {
BlockManager,
Caret,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caret is used below. Probably, you should import the new caret position enum

import Block from '../../block';
import { isEmpty } from '../../utils';
import { isSameBlockData } from '../../utils/blocks';
import { PopoverItemDefaultParams } from '../../utils/popover';

/**
* Block Converter
*
* @todo Make the Conversion Toolbar no-module but a standalone class, like Toolbox
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this todo is not actual now

Comment on lines -82 to +31
*/
this.addTools();
conversionEntries.forEach(([toolName, tool]) => {
const conversionConfig = tool.conversionConfig;

/**
* Prepare Flipper to be able to leaf tools by arrows/tab
*/
this.enableFlipper();

$.append(this.nodes.wrapper, label);
$.append(this.nodes.wrapper, this.nodes.tools);

return this.nodes.wrapper;
}

/**
* Deactivates flipper and removes all nodes
*/
public destroy(): void {
/**
* Sometimes (in read-only mode) there is no Flipper
*/
if (this.flipper) {
this.flipper.deactivate();
this.flipper = null;
}

this.removeAllNodes();
}

/**
* Toggle conversion dropdown visibility
*
* @param {Function} [togglingCallback] — callback that will accept opening state
*/
public toggle(togglingCallback?: (openedState: boolean) => void): void {
if (!this.opened) {
this.open();
} else {
this.close();
}

if (_.isFunction(togglingCallback)) {
this.togglingCallback = togglingCallback;
}
}

/**
* Shows Conversion Toolbar
*/
public open(): void {
this.filterTools();

this.opened = true;
this.nodes.wrapper.classList.add(ConversionToolbar.CSS.conversionToolbarShowed);

/**
* We use RAF to prevent bubbling Enter keydown on first dropdown item
* Conversion flipper will be activated after dropdown will open
*/
window.requestAnimationFrame(() => {
this.flipper.activate(this.tools.map(tool => tool.button).filter((button) => {
return !button.classList.contains(ConversionToolbar.CSS.conversionToolHidden);
}));
this.flipper.focusFirst();
if (_.isFunction(this.togglingCallback)) {
this.togglingCallback(true);
/**
* Skip tools without «import» rule specified
*/
if (!conversionConfig || !conversionConfig.import) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its better to use the isBlockConvertable() util

/**
* Skip tools without «import» rule specified
* Skip tools that don't pass 'toolbox' property
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like the comment is not actual because you're iterating not over tools, but over toolbox items inside a tool

}

/**
* Shows Inline Toolbar
*/
private open(): void {
private async open(): Promise<void> {
Copy link
Member

@neSpecc neSpecc Jun 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, but seems like somewhere can be a memory leak. Try to open/close it many times in a row and take a look on the profiler. Nodes and listeners are growing in time

image

items: item.children,
nestingLevel: this.nestingLevel + 1,
});

this.emit(PopoverEvent.OpenNestedPopover, {
/** Inputs potentially can be auto focused */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

example would be helpful here


nestedPopoverEl.style.setProperty('--trigger-item-top', topOffset + 'px');
nestedPopoverEl.style.setProperty('--nesting-level', this.nestedPopover.nestingLevel.toString());
this.setTriggerItemPositionProperty(nestedPopoverEl, item);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe simpler?

Suggested change
this.setTriggerItemPositionProperty(nestedPopoverEl, item);
this.setTriggerItemPosition(nestedPopoverEl, item);

nestedPopoverEl.style.setProperty('--nesting-level', this.nestedPopover.nestingLevel.toString());
this.setTriggerItemPositionProperty(nestedPopoverEl, item);

nestedPopoverEl.style.setProperty(CSSVariables.NestingLevel, this.nestedPopover.nestingLevel.toString());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add doc please, why CSS should know about nesting level

this.setTriggerItemPositionProperty(nestedPopoverEl, item);

nestedPopoverEl.style.setProperty(CSSVariables.NestingLevel, this.nestedPopover.nestingLevel.toString());
nestedPopoverEl.classList.add(css.getPopoverNestedClass(this.nestedPopover.nestingLevel));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is also not clear why we need this class. docs would be helpful

private handleHover(event: Event): void {
const item = this.getTargetItem(event);
private addSearch(): void {
this.search = new SearchInput({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any destroy() call for search?


/**
* Sets CSS variable with position of item near which nested popover should be displayed.
* Is used for correct positioning of the nested popover
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is used for correct positioning of the nested popover

describe what is the "correct positioning". And describe why we need to this.offsetLeft + itemOffsetLeft

}

/**
* Overrides default item click handling to handle nested popover closing correctly
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

describe what does it mean "closing correctly"

/**
* When nested popover should opens
*/
OpenNestedPopover = 'open-nested-popover',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its better to name events in a past form

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are many unused styles that should be removed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants