Add icon detail page

This commit is contained in:
Eric Fennis
2023-04-17 23:23:54 +02:00
parent 9e9f11321c
commit 813108100d
6 changed files with 203 additions and 66 deletions
@@ -0,0 +1,57 @@
<template>
<button v-bind="$listeners" class="icon-button">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</template>
<style scoped>
.icon-button {
display: inline-block;
border: 1px solid transparent;
text-align: center;
font-weight: 600;
padding: 6px;
border-radius: 8px;
white-space: nowrap;
transition: color 0.25s, border-color 0.25s, background-color 0.25s;
border-radius: 6px;
background-color: var(--vp-c-bg-alt);
display: inline-flex;
/* width: 56px;
height: 56px; */
font-size: 24px;
transition: color 0.1s, border-color 0.1s, background-color 0.1s;
}
.icon-button:hover {
border-color: var(--vp-button-alt-hover-border);
color: var(--vp-button-alt-hover-text);
background-color: var(--vp-button-alt-hover-bg);
}
.icon-button:active {
border-color: var(--vp-button-alt-active-border);
color: var(--vp-button-alt-active-text);
background-color: var(--vp-button-alt-active-bg);
}
.icon-button.active {
border-color: var(--vp-c-brand);
/* color: var(--vp-button-alt-active-text);
background-color: var(--vp-button-alt-active-bg); */
}
</style>
@@ -1,13 +1,9 @@
<script setup lang="ts">
import type { IconEntity } from '../types'
import { ref, computed } from 'vue'
import {
Dialog,
DialogPanel,
DialogTitle,
DialogDescription,
} from '@headlessui/vue'
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
import CloseButton from './CloseButton.vue';
import IconPreview from './IconPreview.vue';
const props = defineProps<{
icon: IconEntity
@@ -29,27 +25,30 @@ import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
if (!props.icon) return null
return createLucideIcon(props.icon.name, props.icon.iconNode)
})
const tags = computed(() => {
if (!props.icon) return []
return props.icon.tags.join(' • ')
})
</script>
<template >
<div class="overlay-container" v-if="props.icon">
<div class="overlay-panel">
<div class="icon-container">
<component :is="iconComponent" class="icon-component" />
<svg class="icon-grid" :viewBox="`0 0 ${size} ${size}`" fill="none" stroke-width="0.1" xmlns="http://www.w3.org/2000/svg">
<g :key="`grid-${i}`" v-for="(_, i) in gridLines">
<line :key="`horizontal-${i}`" :x1="0" :y1="i + 1" :x2="size" :y2="i + 1" />
<line :key="`vertical-${i}`" :x1="i + 1" y1="0" :x2="i + 1" :y2="size" />
</g>
</svg>
</div>
<div class="icon-info">
<h1 class="icon-name">
{{ props.icon.name }}
</h1>
<template>
<Transition name="drawer">
<div class="overlay-container" v-if="props.icon">
<div class="overlay-panel">
<CloseButton class="close-button" @click="onClose" />
<IconPreview :name="props.icon.name" :iconNode="props.icon.iconNode"/>
<div class="icon-info">
<h1 class="icon-name">
{{ props.icon.name }}
</h1>
<p class="icon-tags">
{{ tags }}
</p>
</div>
</div>
</div>
</div>
</Transition>
</template>
<style scoped>
@@ -98,30 +97,6 @@ import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
box-shadow: var(--vp-shadow-5);
}
.icon-container {
height: 100%;
aspect-ratio: 1/1;
position: relative;
background: var(--vp-c-bg-alt);
border-radius: 8px;
}
.icon-grid {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
stroke: var(--vp-c-divider);
}
.icon-component {
width: 100%;
height: 100%;
position: relative;
z-index: 1;
}
.icon-info {
padding: 0 24px;
}
@@ -130,8 +105,33 @@ import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
font-size: 24px;
font-weight: 500;
line-height: 32px;
margin-bottom: 12px;
}
.icon-tags {
font-size: 16px;
color: var(--vp-c-text-2);
font-weight: 500;
}
.close-button {
position: absolute;
top: 24px;
right: 24px;
}
.drawer-enter-active {
transition: all 0.2s cubic-bezier(.21,.8,.46,.9);
}
.drawer-leave-active {
transition: all 0.4s cubic-bezier(1, 0.5, 0.8, 1);
}
.drawer-enter-from,
.drawer-leave-to {
transform: translateY(100%);
opacity: 0;
}
</style>
@@ -0,0 +1,60 @@
<script setup lang="ts">
import type { IconEntity } from '../types'
import { computed } from 'vue'
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
import CloseButton from './CloseButton.vue';
const props = defineProps<{
name: IconEntity['name']
iconNode: IconEntity['iconNode']
}>()
const size = 24
const gridLines = computed(() => Array.from({ length:(size - 1) }))
const iconComponent = computed(() => {
if (!props.name || !props.iconNode) return null
return createLucideIcon(props.name, props.iconNode)
})
</script>
<template>
<div class="icon-container">
<component :is="iconComponent" class="icon-component" />
<svg class="icon-grid" :viewBox="`0 0 ${size} ${size}`" fill="none" stroke-width="0.1" xmlns="http://www.w3.org/2000/svg">
<g :key="`grid-${i}`" v-for="(_, i) in gridLines">
<line :key="`horizontal-${i}`" :x1="0" :y1="i + 1" :x2="size" :y2="i + 1" />
<line :key="`vertical-${i}`" :x1="i + 1" y1="0" :x2="i + 1" :y2="size" />
</g>
</svg>
</div>
</template>
<style scoped>
.icon-grid {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
stroke: var(--vp-c-divider);
}
.icon-container {
height: 100%;
aspect-ratio: 1/1;
position: relative;
background: var(--vp-c-bg-alt);
border-radius: 8px;
}
.icon-component {
width: 100%;
height: 100%;
position: relative;
z-index: 1;
color: #fff;
opacity: 0.8;
}
</style>
-16
View File
@@ -1,16 +0,0 @@
---
layout: page
---
<script setup>
import { onMounted } from 'vue'
import { data } from './index.data.ts'
import IconsOverview from '../.vitepress/components/IconsOverview.vue'
const { categories, icons } = data
onMounted(() => {
console.log(data)
})
</script>
<IconsOverview :icons="icons" />
+33
View File
@@ -0,0 +1,33 @@
---
layout: doc
footer: false
editLink: false
next: false
prev: false
---
<script setup>
import { onMounted, computed } from 'vue'
import { useData } from 'vitepress'
// import { data } from './index.data.ts'
import IconPreview from '../.vitepress/components/IconPreview.vue'
const { params } = useData()
onMounted(() => {
console.log(params, 'data')
})
const tags = computed(() => {
if (!params.tags) return []
return params.tags.join(' • ')
})
</script>
# {{ $params.name }} {#name}
<IconPreview :name="$params.name" :iconNode="$params.iconNode" />
@@ -15,8 +15,11 @@ export function getAllNames() {
export default {
paths: async () => {
const icons = await getAllData()
return icons.map(({ name: iconName }) => ({
params: { iconName }
}))
return icons.map((iconData) => {
return {
params: iconData,
}
})
}
}