mirror of
https://github.com/lucide-icons/lucide.git
synced 2026-11-14 13:58:21 +00:00
Add icon detail page
This commit is contained in:
@@ -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>
|
||||
@@ -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" />
|
||||
@@ -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,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user