adding key handling in forms and dialogs for submit and cancel clean up some code

This commit is contained in:
Jamie V 2025-01-06 12:31:17 -08:00
parent f665c5e71b
commit 3ecb9d4355
5 changed files with 62 additions and 7 deletions

View File

@ -129,6 +129,7 @@ export default {
}
},
mounted() {
document.addEventListener('keydown', this.handleKeyDown);
this.formSections = this.model.sections.map((section) => {
section.id = uuid();
@ -141,6 +142,9 @@ export default {
return section;
});
},
unmounted() {
document.removeEventListener('keydown', this.handleKeyDown);
},
methods: {
onChange(data) {
this.invalidProperties[data.model.key] = data.invalid;
@ -152,6 +156,13 @@ export default {
},
onSave() {
this.$emit('on-save');
},
handleKeyDown({ key }) {
if (key === 'Enter') {
this.onSave();
} else if (key === 'Escape') {
this.onCancel();
}
}
}
};

View File

@ -27,13 +27,15 @@
:style="styleObject"
>
<div class="c-super-menu__left-col">
<div v-if="options.filterable" class="c-menu__search">
<div v-if="options.filterable" class="c-super-menu__filter">
<input
ref="filterInput"
v-model="searchTerm"
type="text"
placeholder="Filter..."
class="c-menu__search-input"
class="c-super-menu__filter-input"
@input="filterItems"
@keydown.stop="handleKeyDown"
@click.stop
/>
</div>
@ -101,7 +103,7 @@
import popupMenuMixin from '../mixins/popupMenuMixin.js';
export default {
mixins: [popupMenuMixin],
inject: ['options'],
inject: ['options', 'dismiss'],
data() {
return {
hoveredItem: null,
@ -128,8 +130,14 @@ export default {
return this.hoveredItem?.description ?? '';
}
},
created() {
mounted() {
this.filteredActions = this.options.actions;
if (this.options.filterable) {
this.$nextTick(() => {
this.$refs.filterInput.focus();
});
}
},
methods: {
toggleItemDescription(action = null) {
@ -143,8 +151,10 @@ export default {
},
filterItems() {
const term = this.searchTerm.toLowerCase();
if (!term) {
this.filteredActions = this.options.actions;
return;
}
@ -167,6 +177,22 @@ export default {
(action.description && action.description.toLowerCase().includes(term))
);
}
},
handleKeyDown({ key }) {
console.log('keydown supermenu', key);
if (key === 'Enter') {
// if there is only one action, select it immediately on enter
const flattenedActions = Array.isArray(this.filteredActions[0])
? this.filteredActions.flat()
: this.filteredActions;
if (flattenedActions.length === 1) {
flattenedActions[0].onItemClicked();
this.dismiss();
}
} else if (key === 'Escape') {
this.dismiss();
}
}
}
};

View File

@ -114,7 +114,8 @@ class Menu extends EventEmitter {
return h(SuperMenuComponent);
},
provide: {
options: this.options
options: this.options,
dismiss: this.dismiss
}
});

View File

@ -64,15 +64,18 @@ export default {
};
},
mounted() {
document.addEventListener('keydown', this.handleKeyDown);
const element = this.$refs.element;
element.appendChild(this.element);
const elementForFocus = this.getElementForFocus() || element;
this.$nextTick(() => {
console.log('buttons', this.buttons);
elementForFocus.focus();
});
},
methods: {
destroy() {
document.removeEventListener('keydown', this.handleKeyDown);
if (this.dismissible) {
this.dismiss();
}
@ -100,6 +103,20 @@ export default {
}
return focusButton[0];
},
handleKeyDown({ key }) {
if (key === 'Enter') {
if (this.focusIndex >= 0 && this.focusIndex < this.buttons.length) {
this.buttonClickHandler(this.buttons[this.focusIndex].callback);
} else {
const okButton = this.buttons?.find((button) => button.label.toLowerCase() === 'ok');
if (okButton) {
this.buttonClickHandler(okButton.callback);
}
}
} else if (key === 'Escape') {
this.destroy();
}
}
}
};

View File

@ -670,12 +670,12 @@ select {
margin-right: $m;
}
&__search {
&__filter {
flex: 0 0 auto;
width: 100%;
margin-bottom: $interiorMarginLg;
.c-menu__search-input {
.c-super-menu__filter-input {
@include nice-input();
width: 100%;
padding: $interiorMargin;