Merge pull request #41638 from nextcloud/fix/41625-Replace_contacts-menu_search_and_unified-search_with_NcTextField

Replace input form with `NcTextField`
This commit is contained in:
Pytal 2023-11-22 09:39:16 -08:00 committed by GitHub
commit ca91eda240
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 76 additions and 70 deletions

View file

@ -29,13 +29,19 @@
<Contacts :size="20" />
</template>
<div class="contactsmenu__menu">
<label for="contactsmenu__menu__search">{{ t('core', 'Search contacts') }}</label>
<input id="contactsmenu__menu__search"
v-model="searchTerm"
class="contactsmenu__menu__search"
type="search"
:placeholder="t('core', 'Search contacts …')"
@input="onInputDebounced">
<div class="contactsmenu__menu__input-wrapper">
<NcTextField :value.sync="searchTerm"
trailing-button-icon="close"
ref="contactsMenuInput"
:label="t('core', 'Search contacts')"
:trailing-button-label="t('core','Reset search')"
:show-trailing-button="searchTerm !== ''"
:placeholder="t('core', 'Search contacts …')"
id="contactsmenu__menu__search"
class="contactsmenu__menu__search"
@input="onInputDebounced"
@trailing-button-click="onReset" />
</div>
<NcEmptyContent v-if="error" :name="t('core', 'Could not load your contacts')">
<template #icon>
<Magnify />
@ -88,6 +94,7 @@ import { translate as t } from '@nextcloud/l10n'
import Contact from '../components/ContactsMenu/Contact.vue'
import logger from '../logger.js'
import Nextcloud from '../mixins/Nextcloud.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
export default {
name: 'ContactsMenu',
@ -100,6 +107,7 @@ export default {
NcEmptyContent,
NcHeaderMenu,
NcLoadingIcon,
NcTextField,
},
mixins: [Nextcloud],
@ -152,17 +160,40 @@ export default {
onInputDebounced: debounce(function() {
this.getContacts(this.searchTerm)
}, 500),
/**
* Reset the search state
*/
onReset() {
this.searchTerm = ''
this.contacts = []
this.focusInput()
},
/**
* Focus the search input on next tick
*/
focusInput() {
this.$nextTick(() => {
this.$refs.contactsMenuInput.focus()
this.$refs.contactsMenuInput.select()
})
},
},
}
</script>
<style lang="scss" scoped>
.contactsmenu {
overflow-y: hidden;
&__menu {
/* show 2.5 to 4.5 entries depending on the screen height */
height: calc(100vh - 50px * 3);
max-height: calc(50px * 6 + 2px + 26px);
min-height: calc(50px * 3.5);
display: flex;
flex-direction: column;
overflow: hidden;
height: calc(50px * 6 + 2px + 26px);
max-height: inherit;
label[for="contactsmenu__menu__search"] {
font-weight: bold;
@ -170,25 +201,22 @@ export default {
margin-left: 13px;
}
&__input-wrapper {
padding: 10px;
z-index: 2;
top: 0;
}
&__search {
width: 100%;
height: 34px;
margin: 8px 0;
&:focus,
&:focus-visible,
&:active {
border-color: 2px solid var(--color-main-text) !important;
box-shadow: 0 0 0 2px var(--color-main-background) !important;
}
margin-top: 0!important;
}
&__content {
/* fixed max height of the parent container without the search input */
height: calc(100vh - 50px * 3 - 60px);
max-height: calc(50px * 5);
min-height: calc(50px * 3.5 - 50px);
overflow-y: auto;
margin-top: 10px;
flex: 1 1 auto;
&__footer {
display: flex;

View file

@ -35,41 +35,22 @@
<!-- Search form & filters wrapper -->
<div class="unified-search__input-wrapper">
<label for="unified-search__input">{{ ariaLabel }}</label>
<div class="unified-search__input-row">
<form class="unified-search__form"
role="search"
:class="{'icon-loading-small': isLoading}"
@submit.prevent.stop="onInputEnter"
@reset.prevent.stop="onReset">
<!-- Search input -->
<input id="unified-search__input"
ref="input"
v-model="query"
class="unified-search__form-input"
type="search"
:class="{'unified-search__form-input--with-reset': !!query}"
:placeholder="t('core', 'Search {types} …', { types: typesNames.join(', ') })"
aria-describedby="unified-search-desc"
@input="onInputDebounced"
@keypress.enter.prevent.stop="onInputEnter">
<p id="unified-search-desc" class="hidden-visually">
{{ t('core', 'Search starts once you start typing and results may be reached with the arrow keys') }}
</p>
<!-- Reset search button -->
<input v-if="!!query && !isLoading"
type="reset"
class="unified-search__form-reset icon-close"
:aria-label="t('core','Reset search')"
value="">
<input v-if="!!query && !isLoading && !enableLiveSearch"
type="submit"
class="unified-search__form-submit icon-confirm"
:aria-label="t('core','Start search')"
value="">
</form>
<NcTextField :value.sync="query"
trailing-button-icon="close"
:label="ariaLabel"
ref="input"
:trailing-button-label="t('core','Reset search')"
:show-trailing-button="query !== ''"
aria-describedby="unified-search-desc"
class="unified-search__form-input"
:class="{'unified-search__form-input--with-reset': !!query}"
:placeholder="t('core', 'Search {types} …', { types: typesNames.join(', ') })"
@trailing-button-click="onReset"
@input="onInputDebounced" />
<p id="unified-search-desc" class="hidden-visually">
{{ t('core', 'Search starts once you start typing and results may be reached with the arrow keys') }}
</p>
<!-- Search filters -->
<NcActions v-if="availableFilters.length > 1"
@ -152,6 +133,7 @@ import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
import NcHeaderMenu from '@nextcloud/vue/dist/Components/NcHeaderMenu.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
import Magnify from 'vue-material-design-icons/Magnify.vue'
@ -175,6 +157,7 @@ export default {
NcHeaderMenu,
SearchResult,
SearchResultPlaceholders,
NcTextField,
},
data() {
@ -738,7 +721,7 @@ export default {
$margin: 10px;
$input-height: 34px;
$input-padding: 6px;
$input-padding: 10px;
.unified-search {
&__input-wrapper {
@ -778,6 +761,7 @@ $input-padding: 6px;
&__filters {
margin: $margin 0 $margin math.div($margin, 2);
padding-top: 5px;
ul {
display: inline-flex;
justify-content: space-between;
@ -820,12 +804,6 @@ $input-padding: 6px;
&::-webkit-search-results-decoration {
-webkit-appearance: none;
}
// Ellipsis earlier if reset button is here
.icon-loading-small &,
&--with-reset {
padding-right: $input-height;
}
}
&-reset, &-submit {

4
dist/core-main.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long