Skip to content

Commit

Permalink
fix: regression with focus on keyboard menu interaction
Browse files Browse the repository at this point in the history
  • Loading branch information
sibiraj-s committed May 14, 2024
1 parent 65a95ff commit 89cca24
Show file tree
Hide file tree
Showing 13 changed files with 151 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
'NgxBubbleMenu__Icon--Active': this.activeItems.includes(item),
'NgxEditor--Disabled': !this.execulableItems.includes(item)
}"
(click)="onClick($event, item)"
(mousedown)="onClick($event, item)"
[title]="getTitle(item) | async"
[innerHTML]="getIcon(item)"
></button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
[class.NgxEditor--Disabled]="!canExecute"
[disabled]="!canExecute"
[innerHTML]="icon | sanitizeHtml"
(click)="togglePopup($event)"
(mousedown)="onTogglePopupMouseClick($event)"
(keydown.enter)="onTogglePopupKeydown()"
(keydown.space)="onTogglePopupKeydown()"
[title]="title | async"
[ariaLabel]="title | async"
></button>
Expand All @@ -17,12 +19,20 @@
*ngFor="let color of colorGroup; trackBy: trackByIndex"
[ngStyle]="{ backgroundColor: color, color: getContrastYIQ(color) }"
[title]="color"
(click)="onColorSelect($event, color)"
(mousedown)="onColorSelectMouseClick($event, color)"
(keydown.enter)="onColorSelectKeydown(color)"
(keydown.space)="onColorSelectKeydown(color)"
[ngClass]="{ 'NgxEditor__Color--Active': activeColors.includes(color) }"
></button>
</div>

<button class="NgxEditor__MenuItem--Button" (click)="remove($event)" [disabled]="!isActive">
<button
class="NgxEditor__MenuItem--Button"
(mousedown)="onRemoveMouseClick($event)"
(keydown.enter)="onRemoveKeydown()"
(keydown.space)="onRemoveKeydown()"
[disabled]="!isActive"
>
{{ getLabel('remove') | async }}
</button>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -65,35 +65,50 @@ export class ColorPickerComponent implements OnInit, OnDestroy {
this.showPopup = false;
}

togglePopup(e: MouseEvent): void {
togglePopup(): void {
this.showPopup = !this.showPopup;
}

onTogglePopupMouseClick(e: MouseEvent): void {
e.preventDefault();

if (e.button !== 0) {
return;
}

this.showPopup = !this.showPopup;
this.togglePopup();
}

remove(e: MouseEvent): void {
e.preventDefault();
onTogglePopupKeydown(): void {
this.togglePopup();
}

remove(): void {
const { state, dispatch } = this.editorView;

this.command.remove()(state, dispatch);
this.hidePopup();
}

trackByIndex(index: number): number {
return index;
}

onColorSelect(e: MouseEvent, color: string): void {
onRemoveMouseClick(e: MouseEvent): void {
e.preventDefault();

if (e.button !== 0) {
return;
}

e.preventDefault();
}

onRemoveKeydown(): void {
this.remove();
}

trackByIndex(index: number): number {
return index;
}

selectColor(color:string):void {
const { state, dispatch } = this.editorView;

if (this.type === 'text_color') {
Expand All @@ -111,6 +126,20 @@ export class ColorPickerComponent implements OnInit, OnDestroy {
this.hidePopup();
}

onColorSelectMouseClick(e: MouseEvent, color: string): void {
e.preventDefault();

if (e.button !== 0) {
return;
}

this.selectColor(color);
}

onColorSelectKeydown(color: string): void {
this.selectColor(color);
}

private update = (view: EditorView) => {
const { state } = view;
this.canExecute = this.command.canExecute(state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
[class.NgxEditor__Dropdown--Selected]="isSelected"
[disabled]="isDropdownDisabled"
[class.NgxEditor--Disabled]="isDropdownDisabled"
(click)="toggleDropdown($event)"
(mousedown)="onToggleDropdownMouseClick($event)"
(keydown.enter)="onToggleDropdownKeydown()"
(keydown.space)="onToggleDropdownKeydown()"
[ariaLabel]="getName(activeItem || group) | async"
aria-haspopup="listbox"
[ariaExpanded]="isDropdownOpen"
Expand All @@ -17,7 +19,9 @@
type="button"
class="NgxEditor__Dropdown--Item"
*ngFor="let item of items; trackBy: trackByIndex"
(click)="onClick($event, item)"
(mousedown)="onDropdownItemMouseClick($event, item)"
(keydown.enter)="onDropdownItemKeydown($event, item)"
(keydown.space)="onDropdownItemKeydown($event, item)"
[ngClass]="{
'NgxEditor__Dropdown--Active': item === activeItem,
'NgxEditor--Disabled': disabledItems.includes(item)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,31 +51,54 @@ export class DropdownComponent implements OnInit, OnDestroy {
return this.ngxeService.locals.get(key);
}

getIsDropdownActive(item:string): boolean {
getIsDropdownActive(item: string): boolean {
return this.activeItem === item;
}

toggleDropdown(e: MouseEvent): void {
e.preventDefault();
toggleDropdown(): void {
this.isDropdownOpen = !this.isDropdownOpen;
}

onToggleDropdownMouseClick(e: MouseEvent): void {
e.preventDefault();

if (e.button !== 0) {
return;
}

this.toggleDropdown();
}

onToggleDropdownKeydown(): void {
this.toggleDropdown();
}

trackByIndex(index: number): number {
return index;
}

onClick(e: MouseEvent, item: TBHeadingItems): void {
selectItem(item: TBHeadingItems): void {
const command = ToggleCommands[item];
const { state, dispatch } = this.editorView;
command.toggle()(state, dispatch);
this.isDropdownOpen = false;
}

onDropdownItemMouseClick(e: MouseEvent, item: TBHeadingItems): void {
e.preventDefault();

// consider only left click
if (e.button !== 0) {
return;
}

const command = ToggleCommands[item];
const { state, dispatch } = this.editorView;
command.toggle()(state, dispatch);
this.isDropdownOpen = false;
this.selectItem(item);
}

onDropdownItemKeydown(event: Event, item: TBHeadingItems): void {
const e = event as KeyboardEvent;
e.preventDefault();
this.selectItem(item);
}

private update = (view: EditorView) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
class="NgxEditor__MenuItem--Icon"
[class.NgxEditor__MenuItem--Active]="isActive || showPopup"
[innerHTML]="icon | sanitizeHtml"
(click)="onMouseDown($event)"
(mousedown)="onTogglePopupMouseClick($event)"
(keydown.enter)="onTogglePopupKeydown()"
(keydown.space)="onTogglePopupKeydown()"
[title]="getLabel('insertImage') | async"
[ariaLabel]="getLabel('insertImage') | async"
aria-haspopup="dialog"
Expand Down
18 changes: 13 additions & 5 deletions projects/ngx-editor/src/lib/modules/menu/image/image.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,26 @@ export class ImageComponent implements OnInit, OnDestroy {
});
}

onMouseDown(e: MouseEvent): void {
if (e.button !== 0) {
return;
}

togglePopup(): void {
this.showPopup = !this.showPopup;

if (this.showPopup) {
this.fillForm();
}
}

onTogglePopupMouseClick(e:MouseEvent): void {
if (e.button !== 0) {
return;
}

this.togglePopup();
}

onTogglePopupKeydown(): void {
this.togglePopup();
}

private fillForm(): void {
const { state } = this.editorView;
const { selection } = state;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
[disabled]="disabled"
[class.NgxEditor--Disabled]="disabled"
[innerHTML]="html | sanitizeHtml"
(click)="insert($event)"
(mousedown)="onMouseClick($event)"
(keydown.enter)="onKeydown()"
(keydown.space)="onKeydown()"
[title]="getTitle(name) | async"
[ariaLabel]="getTitle(name) | async"
></button>
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,21 @@ export class InsertCommandComponent implements OnInit, OnDestroy {
private menuService: MenuService,
) { }

insert(e: MouseEvent): void {
onMouseClick(e: MouseEvent): void {
e.preventDefault();

if (e.button !== 0) {
return;
}

this.insert();
}

onKeydown(): void {
this.insert();
}

insert(): void {
const { state, dispatch } = this.editorView;
const command = InsertCommands[this.name];
command.insert()(state, dispatch);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
[class.NgxEditor--Disabled]="!canExecute"
[disabled]="!canExecute"
[innerHTML]="icon | sanitizeHtml"
(click)="onMouseDown($event)"
(mousedown)="onTogglePopupMouseClick($event)"
(keydown.enter)="onTogglePopupKeydown()"
(keydown.space)="onTogglePopupKeydown()"
[title]="title | async"
[ariaLabel]="title | async"
aria-haspopup="dialog"
Expand Down
24 changes: 16 additions & 8 deletions projects/ngx-editor/src/lib/modules/menu/link/link.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class LinkComponent implements OnInit, OnDestroy {

@HostListener('document:mousedown', ['$event']) onDocumentClick(e: MouseEvent): void {
if (!this.el.nativeElement.contains(e.target) && this.showPopup) {
this.hideForm();
this.hidePopup();
}
}

Expand All @@ -76,7 +76,7 @@ export class LinkComponent implements OnInit, OnDestroy {
return this.ngxeService.locals.get(key);
}

private hideForm(): void {
private hidePopup(): void {
this.showPopup = false;
this.form.reset({
href: '',
Expand All @@ -86,11 +86,7 @@ export class LinkComponent implements OnInit, OnDestroy {
this.text.enable();
}

onMouseDown(e: MouseEvent): void {
if (e.button !== 0) {
return;
}

togglePopup(): void {
const { state, dispatch } = this.editorView;

if (this.isActive) {
Expand All @@ -104,6 +100,18 @@ export class LinkComponent implements OnInit, OnDestroy {
}
}

onTogglePopupMouseClick(e:MouseEvent): void {
if (e.button !== 0) {
return;
}

this.togglePopup();
}

onTogglePopupKeydown(): void {
this.togglePopup();
}

private setText = () => {
const { state: { selection, doc } } = this.editorView;
const { empty, from, to } = selection;
Expand Down Expand Up @@ -145,7 +153,7 @@ export class LinkComponent implements OnInit, OnDestroy {
} else {
LinkCommand.update(attrs)(state, dispatch);
}
this.hideForm();
this.hidePopup();
}

ngOnInit(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
[class.NgxEditor--Disabled]="disabled"
[disabled]="disabled"
[innerHTML]="html | sanitizeHtml"
(click)="toggle($event)"
(mousedown)="onMouseClick($event)"
(keydown.enter)="onKeydown()"
(keydown.space)="onKeydown()"
[title]="getTitle(name) | async"
[ariaLabel]="getTitle(name) | async"
></button>
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,24 @@ export class ToggleCommandComponent implements OnInit, OnDestroy {
private menuService: MenuService,
) { }

toggle(e: MouseEvent): void {
toggle(): void {
const { state, dispatch } = this.editorView;
const command = ToggleCommands[this.name];
command.toggle()(state, dispatch);
}

onMouseClick(e: MouseEvent): void {
e.preventDefault();

if (e.button !== 0) {
return;
}

const { state, dispatch } = this.editorView;
const command = ToggleCommands[this.name];
command.toggle()(state, dispatch);
this.toggle();
}

onKeydown(): void {
this.toggle();
}

update = (view: EditorView): void => {
Expand Down

0 comments on commit 89cca24

Please sign in to comment.