mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
* icon interface first pass * icon test * readme lol * Fix top placement in attached mode * Finish icon interface * Add some padding * Finishing touches * Fix tests Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
133 lines
2.5 KiB
Vue
133 lines
2.5 KiB
Vue
<template>
|
|
<v-menu attached :disabled="disabled" close-on-content-click>
|
|
<template #activator="{ toggle, active }">
|
|
<v-input
|
|
:disabled="disabled"
|
|
:placeholder="value || $t('search_for_icon')"
|
|
v-model="searchQuery"
|
|
@focus="toggle(true)"
|
|
>
|
|
<template #prepend>
|
|
<v-icon :name="value" :class="{ active: value }" />
|
|
</template>
|
|
|
|
<template #append>
|
|
<v-icon name="expand_more" class="open-indicator" :class="{ open: active }" />
|
|
</template>
|
|
</v-input>
|
|
</template>
|
|
|
|
<div class="content" :class="width">
|
|
<template v-for="(group, index) in filteredIcons">
|
|
<div :key="'icon-group-' + group.name" class="icons" v-if="group.icons.length > 0">
|
|
<v-icon
|
|
v-for="icon in group.icons"
|
|
:key="icon"
|
|
:name="icon"
|
|
:class="{ active: icon === value }"
|
|
@click="setIcon(icon)"
|
|
/>
|
|
</div>
|
|
<v-divider
|
|
:key="'divider-' + group.name"
|
|
v-if="group.icons.length > 0 && index !== filteredIcons.length - 1"
|
|
/>
|
|
</template>
|
|
</div>
|
|
</v-menu>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import icons from './icons.json';
|
|
import { defineComponent, ref, computed } from '@vue/composition-api';
|
|
|
|
export default defineComponent({
|
|
props: {
|
|
value: {
|
|
type: String,
|
|
default: 'search',
|
|
},
|
|
disabled: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
width: {
|
|
type: String,
|
|
default: 'half',
|
|
},
|
|
},
|
|
setup(props, { emit }) {
|
|
const searchQuery = ref('');
|
|
|
|
const filteredIcons = computed(() => {
|
|
return icons.map((group) => {
|
|
if (searchQuery.value.length === 0) return group;
|
|
|
|
const icons = group.icons.filter((icon) =>
|
|
icon.includes(searchQuery.value.toLowerCase())
|
|
);
|
|
|
|
return {
|
|
...group,
|
|
icons: icons,
|
|
length: icons.length,
|
|
};
|
|
});
|
|
});
|
|
|
|
return {
|
|
icons,
|
|
setIcon,
|
|
searchQuery,
|
|
filteredIcons,
|
|
};
|
|
|
|
function setIcon(icon: string) {
|
|
emit('input', icon);
|
|
}
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.content {
|
|
padding: 8px;
|
|
|
|
.v-icon:hover {
|
|
color: var(--foreground-normal);
|
|
}
|
|
|
|
.v-icon.active {
|
|
color: var(--primary);
|
|
}
|
|
|
|
.v-divider {
|
|
--v-divider-color: var(--background-normal);
|
|
|
|
margin: 0 22px;
|
|
}
|
|
}
|
|
|
|
.icons {
|
|
display: grid;
|
|
grid-gap: 8px;
|
|
grid-template-columns: repeat(8, 1fr);
|
|
justify-content: center;
|
|
padding: 20px 0;
|
|
color: var(--foreground-subdued);
|
|
}
|
|
|
|
.full .icons {
|
|
grid-template-columns: repeat(18, 1fr);
|
|
}
|
|
|
|
.open-indicator {
|
|
transform: scaleY(1);
|
|
transition: transform var(--fast) var(--transition);
|
|
}
|
|
|
|
.open-indicator.open {
|
|
transform: scaleY(-1);
|
|
}
|
|
</style>
|