Add related icons

This commit is contained in:
Eric Fennis
2023-05-10 23:02:45 +02:00
parent cc7545fcb8
commit 1eb7e4f579
8 changed files with 86 additions and 26 deletions
@@ -7,6 +7,7 @@ const emit = defineEmits(['setActiveIcon'])
const props = defineProps<{
icons: IconEntity[]
activeIcon?: string
overlayMode?: boolean
}>()
function setActiveIcon(name: string) {
@@ -23,6 +24,7 @@ function setActiveIcon(name: string) {
@setActiveIcon="setActiveIcon(icon.name)"
:active="activeIcon === icon.name"
customizable
:overlayMode="overlayMode"
/>
</div>
</div>
@@ -14,6 +14,7 @@ const props = defineProps<{
iconNode: IconNode;
active: boolean;
customizable?: boolean;
overlayMode?: boolean
}>()
const emit = defineEmits(['setActiveIcon'])
@@ -24,7 +25,7 @@ const showOverlay = useMediaQuery('(min-width: 860px)');
const icon = createLucideIcon(props.name, props.iconNode)
function navigateToIcon() {
if(showOverlay.value) {
if(props.overlayMode && showOverlay.value) {
window.history.pushState({}, '', `/icons/${props.name}`)
emit('setActiveIcon', props.name)
}
@@ -41,6 +42,7 @@ function navigateToIcon() {
:class="{ 'active' : active }"
:data-title="name"
:aria-label="name"
:href="`/icons/${props.name}`"
>
<KeepAlive>
<component :is="icon" class="lucide-icon" :class="{ customizable }" />
@@ -63,6 +65,7 @@ function navigateToIcon() {
width: 56px;
height: 56px;
font-size: 24px;
color: var(--vp-c-text-1);
}
.icon-button:hover:before {
@@ -68,19 +68,13 @@ const activeIcon = computed(() =>
:activeIcon="activeIconName"
:icons="category.icons"
@setActiveIcon="setActiveIconName"
overlayMode
/>
</section>
<IconDetailOverlay :icon="activeIcon" @close="setActiveIconName('')"/>
</template>
<style scoped>
.icons {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
gap: 8px;
width: 100%;
}
.icon {
aspect-ratio: 1/1;
}
@@ -88,6 +82,7 @@ const activeIcon = computed(() =>
.title {
margin-bottom: 24px;
font-size: 19px;
font-weight: 500;
}
.category {
@@ -95,16 +90,6 @@ const activeIcon = computed(() =>
}
.input-wrapper {
margin-bottom: 16px;
}
.hidden-category {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
margin-bottom: 32px;
}
</style>
@@ -40,8 +40,9 @@ const pageSize = computed(() => {
const { searchInput, searchQuery, searchQueryThrottled } = useSearchInput()
const searchResults = useSearch(searchQueryThrottled, props.icons, [
{ name: 'name', weight: 2 },
{ name: 'tags', weight: 1 },
{ name: 'name', weight: 3 },
{ name: 'tags', weight: 2 },
{ name: 'categories', weight: 1 },
])
const { next, currentPage } = useOffsetPagination( { pageSize })
@@ -73,7 +74,12 @@ watch(searchQueryThrottled, (searchString) => {
class="input-wrapper"
ref="searchInput"
/>
<IconGrid :activeIcon="activeIconName" :icons="paginatedIcons" @setActiveIcon="setActiveIconName"/>
<IconGrid
overlayMode
:activeIcon="activeIconName"
:icons="paginatedIcons"
@setActiveIcon="setActiveIconName"
/>
<EndOfPage @end-of-page="next" class="bottom-page"/>
<IconDetailOverlay :icon="activeIcon" @close="setActiveIconName('')"/>
</template>
@@ -91,7 +97,7 @@ watch(searchQueryThrottled, (searchString) => {
}
.input-wrapper {
margin-bottom: 8px;
margin-bottom: 16px;
}
.bottom-page {
@@ -0,0 +1,34 @@
<script setup lang="ts">
import type { IconEntity } from '../../types'
import IconGrid from './IconGrid.vue'
defineProps<{
icons: IconEntity[]
}>()
</script>
<template>
<section class="category">
<h2 class="title">
Related Icons
</h2>
<IconGrid
:icons="icons"
/>
</section>
</template>
<style scoped>
.icon {
aspect-ratio: 1/1;
}
.title {
margin-bottom: 24px;
font-size: 19px;
font-weight: 500;
}
.category {
margin-bottom: 32px;
}
</style>
+3 -2
View File
@@ -13,6 +13,7 @@ import { useData } from 'vitepress'
import IconPreview from '../.vitepress/theme/components/icons/IconPreview.vue'
import IconInfo from '../.vitepress/theme/components/icons/IconInfo.vue'
import IconContributors from '../.vitepress/theme/components/icons/IconContributors.vue'
import RelatedIcons from '../.vitepress/theme/components/icons/RelatedIcons.vue'
import CodeGroup from '../.vitepress/theme/components/base/CodeGroup.vue'
import Badge from '../.vitepress/theme/components/base/Badge.vue'
import Label from '../.vitepress/theme/components/base/Label.vue'
@@ -64,10 +65,10 @@ const codeExample = computed(() => data.codeExamples?.map(
/>
</CodeGroup>
</div>
</div>
<RelatedIcons :icons="$params.relatedIcons" />
<style module>
.preview {
grid-area: preview;
+29 -1
View File
@@ -1,10 +1,38 @@
import Fuse from "fuse.js";
import { getAllData } from "../.vitepress/lib/icons";
import { IconEntity } from "../.vitepress/theme/types";
const getRelatedIcons = (name:string, icons: IconEntity[]) => {
const index = new Fuse(icons, {
threshold: 1,
keys: [
{ name: 'name', weight: 3 },
{ name: 'tags', weight: 2 },
{ name: 'categories', weight: 1 },
],
});
return index
.search(name)
.map((result) => result.item)
.slice(0, 85)
.map(({ name, iconNode }: IconEntity) => ({
name,
iconNode
}))
}
export default {
paths: async () => {
const icons = await getAllData()
return icons.map((params) => {
return icons.map((iconEntity) => {
const relatedIcons = getRelatedIcons(iconEntity.name, icons)
const params = {
...iconEntity,
relatedIcons
}
return {
params,
}
+1
View File
@@ -1,5 +1,6 @@
import { getAllData } from '../.vitepress/lib/icons'
import { getAllCategoryFiles } from '../.vitepress/lib/categories'
import { IconEntity } from '../.vitepress/theme/types'
export default {
async load() {