Add first cusotmizer

This commit is contained in:
Eric Fennis
2023-04-25 21:55:08 +02:00
parent 43bd810de0
commit b15a2dc707
18 changed files with 213 additions and 26 deletions
+30 -16
View File
@@ -2,12 +2,26 @@
import { ref, computed } from 'vue'
import { useData } from 'vitepress'
import VPDocOutlineItem from 'vitepress/dist/client/theme-default/components/VPDocOutlineItem.vue'
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
import { isActive } from 'vitepress/dist/client/theme-default/support/utils'
import { onContentUpdated } from 'vitepress'
import { useActiveAnchor } from '../composables/useActiveAnchor'
import { data } from './CategoriesList.data'
import { useRouter } from 'vitepress';
const { go } = useRouter()
const { frontmatter, theme, params, page } = useData()
const categoriesIsActive = computed(() => {
return isActive(page.value.relativePath, '/icons/categories');
});
const overviewIsActive = computed(() => {
return isActive(page.value.relativePath, '/icons/');
});
interface Header {
level: number
title: string
@@ -19,16 +33,6 @@ type MenuItem = Omit<Header, 'slug' | 'children'> & {
children?: MenuItem[]
}
// const headers = shallowRef<MenuItem[]>([])
// onContentUpdated(() => {
// headers.value = data.categories.map(({ name, title }) => ({
// level: 2,
// link: `#${name}`,
// title,
// }))
// })
const headers = computed(() => {
const linkPrefix = page.value.relativePath.startsWith('icons/categories')
? '' : '/icons/categories'
@@ -48,9 +52,12 @@ useActiveAnchor(container, marker)
<template>
<div class="category-list" ref="container">
<h2 class="sidebar-title">
<VPLink class="sidebar-title" href="/icons/" :class="{ 'active': overviewIsActive } ">
All
</VPLink>
<VPLink class="sidebar-title" href="/icons/categories" :class="{ 'active': categoriesIsActive } ">
Categories
</h2>
</VPLink>
<div class="content">
<div class="outline-marker" ref="marker" />
<nav aria-labelledby="doc-outline-aria-label">
@@ -62,16 +69,23 @@ useActiveAnchor(container, marker)
<style scoped>
.category-list {
margin-top: -16px;
/* margin-top: -24px; */
}
.sidebar-title {
font-weight: 700;
color: var(--vp-c-text-1);
margin-bottom: 12px;
font-weight: 500;
color: var(--vp-c-text-2);
margin-bottom: 6px;
line-height: 24px;
font-size: 14px;
display: block;
transition: color 0.25s;
}
.sidebar-title:hover, .sidebar-title.active {
color: var(--vp-c-brand);
}
.content {
margin-top: 12px;
position: relative;
border-left: 1px solid var(--vp-c-divider);
padding-left: 16px;
@@ -0,0 +1,139 @@
<script setup>
import { useCssVar } from '@vueuse/core'
const color = useCssVar(
'--customize-color',
document.documentElement,
{
initialValue: 'currentColor'
}
)
const strokeWidth = useCssVar(
'--customize-strokeWidth',
document.documentElement,
{
initialValue: '2'
}
)
const size = useCssVar(
'--customize-size',
document.documentElement,
{
initialValue: '24'
}
)
</script>
<template>
<div class="card">
<label for="icon-color" class="customize-label">
Color
</label>
<div class="color-picker">
<div class="color-input-wrapper">
<input
type="color"
id="icon-color"
name="icon-color"
class="color-input"
v-model="color"
/>
</div>
<input
type="text"
id="icon-color-input"
name="icon-color-input"
class="color-input-text"
v-model="color"
/>
</div>
<label for="stroke" class="customize-label">
Stroke width
</label>
<input
type="number"
id="stroke"
name="stroke"
v-model="strokeWidth"
/>
<label for="size" class="customize-label">
Size
</label>
<input
type="number"
id="size"
name="size"
v-model="size"
/>
</div>
</template>
<style scoped>
.customize-label {
padding-bottom: 8px;
line-height: 20px;
font-size: 13px;
font-weight: 600;
color: var(--vt-c-text-1);
transition: color .5s;
display: block;
}
.card {
background: var(--vp-c-bg);
padding: 24px;
border-radius: 12px;
margin-bottom: 24px;
}
.color-input {
width: 34px;
height: 34px;
position: absolute;
top: -5px;
left: -5px;
}
.color-input-wrapper {
height: 24px;
width: 24px;
overflow: hidden;
position: relative;
border-radius: 12px;
flex-shrink: 0;
}
.color-picker {
background: var(--vp-c-bg-soft);
border-radius: 8px;
color: var(--vp-c-text-2);
padding: 8px 12px;
height: auto;
font-size: 14px;
text-align: left;
border: 1px solid transparent;
cursor: text;
display: flex;
align-items: center;
gap: 4px;
}
.color-input-text {
width: 100%;
height: 100%;
padding: 0 8px;
border: none;
background: transparent;
color: var(--vp-c-text-2);
font-size: 14px;
text-align: left;
border-radius: 8px;
cursor: text;
}
.color-picker:hover, .color-picker:focus {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg-alt);
}
</style>
+6 -1
View File
@@ -19,7 +19,12 @@ const tags = computed(() => {
<template>
<!-- <PageContainer class="overview"> -->
<IconPreview :name="$params.name" :iconNode="$params.iconNode" class="preview" />
<IconPreview
:name="$params.name"
:iconNode="$params.iconNode"
class="preview"
customizable
/>
<div class="details">
<h1 class="title">
{{ $params.name }}
@@ -52,7 +52,11 @@
<component :is="CloseIcon" />
</IconButton>
</nav>
<IconPreview :name="props.icon.name" :iconNode="props.icon.iconNode"/>
<IconPreview
:name="props.icon.name"
:iconNode="props.icon.iconNode"
customizable
/>
<div class="icon-info">
<IconDetailName class="icon-name">
{{ props.icon.name }}
+1
View File
@@ -22,6 +22,7 @@ function setActiveIcon(name: string) {
v-bind="icon"
@setActiveIcon="setActiveIcon(icon.name)"
:active="activeIcon === icon.name"
customizable
/>
</div>
</div>
+14 -3
View File
@@ -14,6 +14,7 @@ const props = defineProps<{
// contributors: Contributor[];
iconNode: IconNode;
active: boolean;
customizable?: boolean;
}>()
const emit = defineEmits(['setActiveIcon'])
@@ -43,7 +44,7 @@ function navigateToIcon() {
:aria-label="name"
>
<KeepAlive>
<component :is="icon" />
<component :is="icon" class="lucide-icon" :class="{ customizable }" size="auto"/>
</KeepAlive>
</button>
</template>
@@ -54,7 +55,6 @@ function navigateToIcon() {
border: 1px solid transparent;
text-align: center;
font-weight: 600;
padding: 15px;
border-radius: 4px;
white-space: nowrap;
transition: color 0.25s, border-color 0.25s, background-color 0.25s;
@@ -76,7 +76,7 @@ function navigateToIcon() {
display: block;
font-size: 12px;
line-height: 20px;
margin-left: 12px;
margin-left: 24px;
transform: translate(-50%, 48px) scale(0.9);
font-weight: 400;
position: absolute;
@@ -135,4 +135,15 @@ function navigateToIcon() {
/* color: var(--vp-button-alt-active-text);
background-color: var(--vp-button-alt-active-bg); */
}
.lucide-icon {
margin: auto;
}
.lucide-icon.customizable {
will-change: width, height, stroke-width, stroke;
color: var(--customize-color, currentColor);
stroke-width: var(--customize-strokeWidth, 2);
width: calc(var(--customize-size, 24) * 1px);
height: calc(var(--customize-size, 24) * 1px);
}
</style>
+10 -1
View File
@@ -7,6 +7,7 @@ import CloseButton from './CloseButton.vue';
const props = defineProps<{
name: IconEntity['name']
iconNode: IconEntity['iconNode']
customizable?: boolean
}>()
const size = 24
@@ -22,7 +23,7 @@ const iconComponent = computed(() => {
<template>
<div class="icon-container">
<component :is="iconComponent" class="icon-component" />
<component :is="iconComponent" class="icon-component" :class="{ customizable }"/>
<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" />
@@ -57,4 +58,12 @@ const iconComponent = computed(() => {
color: var(--vp-c-neutral);
opacity: 0.8;
}
.icon-component.customizable {
will-change: width, height, stroke-width, stroke;
color: var(--customize-color, currentColor);
stroke-width: var(--customize-strokeWidth, 2);
width: calc(var(--customize-size, 24) * 1px);
height: calc(var(--customize-size, 24) * 1px);
}
</style>
+1 -1
View File
@@ -86,7 +86,7 @@ export default defineConfig({
}
],
'icons': [
{ text: 'All', link: '/icons/' },
{ text: '', link: '/' },
// { text: 'Categorized', link: '/icons/categorized' },
// {
// text: 'Categories',
+2 -2
View File
@@ -2,14 +2,14 @@ import { h } from 'vue'
import DefaultTheme from 'vitepress/theme'
import './style.css'
import { Theme } from 'vitepress'
import IconsLayout from './layouts/IconsLayout.vue'
import IconsSidebarNavAfter from './layouts/IconsSidebarNavAfter.vue'
import HomeHeroIconsCard from '../components/HomeHeroIconsCard.vue'
const theme: Partial<Theme> = {
extends: DefaultTheme,
Layout() {
return h(DefaultTheme.Layout, null, {
'sidebar-nav-after': () => h(IconsLayout),
'sidebar-nav-after': () => h(IconsSidebarNavAfter),
'home-hero-image': () => h(HomeHeroIconsCard)
})
},
@@ -4,6 +4,7 @@ import { useData } from 'vitepress'
import { useSidebar } from 'vitepress/dist/client/theme-default/composables/sidebar.js'
import CategoriesList from '../../components/CategoriesList.vue'
import IconCustomizer from '../../components/IconCustomizer.vue'
const { frontmatter, page } = useData()
const { isOpen, isSidebarEnabled } = useSidebar()
@@ -17,6 +18,7 @@ onMounted(() => {
<template>
<div>
<IconCustomizer/>
<CategoriesList v-if="page?.relativePath?.startsWith?.('icons')"/>
</div>
</template>
+1
View File
@@ -5,6 +5,7 @@ aside: false
editLink: false
next: false
prev: false
sidebar: true
---
<script setup>
import IconPreview from '../.vitepress/components/IconPreview.vue'
+1
View File
@@ -2,6 +2,7 @@
layout: page
outline: 2
outlineTitle: Categories
sidebar: true
---
<script setup>
-1
View File
@@ -14,7 +14,6 @@ export function getAllCategoryFiles() {
}));
}
export default {
async load() {
const icons = await getAllData()
+1
View File
@@ -2,6 +2,7 @@
layout: page
outline: 2
outlineTitle: Categories
sidebar: true
---
<script setup>