diff options
author | Marco <marcoambrosini@icloud.com> | 2023-11-10 13:36:26 +0900 |
---|---|---|
committer | fenn-cs <fenn25.fn@gmail.com> | 2023-11-10 11:27:32 +0100 |
commit | 8feacd03846169aa699f6b4630b5614eeabc9f36 (patch) | |
tree | 2907335c8f0a15475032d846a93e1452b89f8ab9 /core/src/components | |
parent | 13d03f45a3735dc44ccdbebf7bedb0825460a477 (diff) | |
download | nextcloud-server-8feacd03846169aa699f6b4630b5614eeabc9f36.tar.gz nextcloud-server-8feacd03846169aa699f6b4630b5614eeabc9f36.zip |
Create searchable list component
Signed-off-by: Marco <marcoambrosini@icloud.com>
Diffstat (limited to 'core/src/components')
-rw-r--r-- | core/src/components/GlobalSearch/SearchableList.vue | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/core/src/components/GlobalSearch/SearchableList.vue b/core/src/components/GlobalSearch/SearchableList.vue new file mode 100644 index 00000000000..356f2f7664a --- /dev/null +++ b/core/src/components/GlobalSearch/SearchableList.vue @@ -0,0 +1,149 @@ +<!-- + - @copyright 2023 Marco Ambrosini <marcoambrosini@proton.me> + - + - @author Marco Ambrosini <marcoambrosini@proton.me> + - + - @license AGPL-3.0-or-later + - + - This program is free software: you can redistribute it and/or modify + - it under the terms of the GNU Affero General Public License as + - published by the Free Software Foundation, either version 3 of the + - License, or (at your option) any later version. + - + - This program is distributed in the hope that it will be useful, + - but WITHOUT ANY WARRANTY; without even the implied warranty of + - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + - GNU Affero General Public License for more details. + - + - You should have received a copy of the GNU Affero General Public License + - along with this program. If not, see <http://www.gnu.org/licenses/>. + - +--> + +<template> + <NcPopover> + <template #trigger> + <slot name="trigger" /> + </template> + <div class="searchable-list__wrapper"> + <NcTextField :value.sync="searchTerm" + :label="labelText" + trailing-button-icon="close" + :show-trailing-button="searchTerm !== ''" + @trailing-button-click="clearSearch"> + <Magnify :size="20" /> + </NcTextField> + <ul v-if="filteredList.length > 0" class="searchable-list__list"> + <li v-for="element in filteredList" + :key="element" + :title="element" + role="button"> + <NcButton alignment="start" + type="tertiary" + :wide="true" + @click="$emit(element)"> + <template #icon> + <NcAvatar :display-name="element" :hide-favorite="false" /> + </template> + {{ element }} + </NcButton> + </li> + </ul> + <div v-else class="searchable-list__empty-content"> + <NcEmptyContent :name="emptyContentText"> + <template #icon> + <AlertCircleOutline /> + </template> + </NcEmptyContent> + </div> + </div> + </NcPopover> +</template> + +<script> +import { NcPopover, NcTextField, NcAvatar, NcEmptyContent, NcButton } from '@nextcloud/vue' + +import AlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline.vue' +import Magnify from 'vue-material-design-icons/Magnify.vue' + +export default { + name: 'SearchableList', + + components: { + NcPopover, + NcTextField, + Magnify, + AlertCircleOutline, + NcAvatar, + NcEmptyContent, + NcButton, + }, + + props: { + labelText: { + type: String, + default: 'this is a label', + }, + + searchList: { + type: Array, + required: true, + }, + + emptyContentText: { + type: String, + required: true, + }, + }, + + data() { + return { + error: false, + searchTerm: '', + } + }, + + computed: { + filteredList() { + return this.searchList.filter((element) => { + return element.toLowerCase().includes(this.searchTerm.toLowerCase()) + }) + }, + }, + + methods: { + clearSearch() { + this.searchTerm = '' + }, + }, +} +</script> + +<style lang="scss" scoped> + +.searchable-list { + &__wrapper { + padding: calc(var(--default-grid-baseline) * 3); + display: flex; + flex-direction: column; + align-items: center; + width: 250px; + } + + &__list { + width: 100%; + max-height: 284px; + overflow-y: auto; + margin-top: var(--default-grid-baseline); + padding: var(--default-grid-baseline); + + :deep(.button-vue) { + border-radius: var(--border-radius-large) !important; + } + } + + &__empty-content { + margin-top: calc(var(--default-grid-baseline) * 3); + } +} +</style> |