Docs Cleanup

This commit is contained in:
David Haz
2025-07-12 15:28:52 +03:00
parent 62cdbc2dba
commit 056d2c0330
21 changed files with 365 additions and 588 deletions

View File

@@ -13,12 +13,10 @@ import DisplayHeader from '@/components/landing/DisplayHeader/DisplayHeader.vue'
const route = useRoute(); const route = useRoute();
const isCategoryPage = computed(() => /^\/[^/]+\/[^/]+$/.test(route.path));
const activeItem = computed(() => { const activeItem = computed(() => {
if (route.path === '/') return 'home'; if (route.path === '/') return 'home';
return null; return null;
}); });
const isCategoryPage = computed(() => {
return /^\/[^/]+\/[^/]+$/.test(route.path);
});
</script> </script>

View File

@@ -28,10 +28,9 @@
</div> </div>
</div> </div>
<div v-if="!snippet" class="no-code"> <div v-else class="no-code">
<span>Nothing here yet!</span> <span>Nothing here yet!</span>
<i class="pi pi-face-sad" />
<i class="pi pi-face-sad"></i>
</div> </div>
</div> </div>
</div> </div>
@@ -47,7 +46,6 @@ const props = defineProps<{
}>(); }>();
const skipKeys = ['cli']; const skipKeys = ['cli'];
const expandedSections = ref<Set<string>>(new Set()); const expandedSections = ref<Set<string>>(new Set());
const codeEntries = computed(() => { const codeEntries = computed(() => {
@@ -72,102 +70,29 @@ const toggleExpanded = (name: string) => {
}; };
const getDisplayName = (name: string) => { const getDisplayName = (name: string) => {
if (name === 'code') return 'Code'; const displayNames: Record<string, string> = {
if (name === 'cli') return 'CLI Command'; code: 'Code',
if (name === 'utility') return 'Utility'; cli: 'CLI Command',
if (name === 'usage') return 'Usage'; utility: 'Utility',
if (name === 'installation') return 'Installation'; usage: 'Usage',
return name.charAt(0).toUpperCase() + name.slice(1); installation: 'Installation'
};
return displayNames[name] || name.charAt(0).toUpperCase() + name.slice(1);
}; };
const getLanguage = (name: string) => { const getLanguage = (name: string) => {
if (name === 'cli') return 'bash'; const languageMap: Record<string, string> = {
if (name === 'code') return 'html'; cli: 'bash',
if (name === 'usage') return 'html'; code: 'html',
if (name === 'installation') return 'bash'; utility: 'typescript',
return 'javascript'; usage: 'html',
installation: 'bash'
};
return languageMap[name] || 'typescript';
}; };
</script> </script>
<style scoped> <style scoped>
.code-example {
margin: 1.2rem 0;
}
.code-section {
margin-bottom: 2rem;
}
.code-container {
position: relative;
margin-bottom: 1.2rem;
}
.code-wrapper {
position: relative;
overflow: hidden;
border: 1px solid #142216;
border-radius: 15px;
}
.code-wrapper.collapsed {
max-height: 600px;
}
.code-block {
overflow: hidden;
border: none;
border-radius: 15px;
}
.fade-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 60%;
background: linear-gradient(to bottom, transparent, #0b0b0b);
pointer-events: none;
z-index: 1;
}
.expand-button {
position: absolute;
bottom: 0.75rem;
right: 0.75rem;
padding: 0.5rem 1rem;
border-radius: 12px;
height: 2.5rem;
font-size: 14px;
font-weight: 500;
background-color: #0b0b0b;
border: 1px solid #142216;
color: white;
cursor: pointer;
z-index: 2;
transition: background-color 0.3s ease;
}
.expand-button:hover {
background-color: #111;
}
.expand-button:active {
background-color: #111;
}
.no-code {
display: flex;
align-items: center;
gap: 0.5rem;
color: #a1a1aa;
font-style: italic;
padding: 2rem;
background: #0b0b0b;
border: 1px solid #142216;
border-radius: 15px;
}
:deep(.v-code-block) { :deep(.v-code-block) {
background: #0b0b0b; background: #0b0b0b;
border-radius: 15px; border-radius: 15px;

View File

@@ -1,30 +1,12 @@
<template> <template>
<Button <button :class="['back-to-top', { visible }]" @click="visible && scrollToTop()">
:style="{
fontWeight: 500,
borderRadius: '0.75rem',
border: '1px solid #142216',
padding: '1rem',
position: 'fixed',
right: '2.3em',
zIndex: 98,
boxShadow: '10px 0 25px rgba(0, 0, 0, 0.2)',
transition: '0.3s ease',
opacity: visible ? 1 : 0,
bottom: visible ? '2.5em' : '1em',
cursor: visible ? 'pointer' : 'default'
}"
class="back-to-top"
@click="visible && scrollToTop()"
>
<i class="pi pi-arrow-up" style="color: #fff; font-size: 1rem"></i> <i class="pi pi-arrow-up" style="color: #fff; font-size: 1rem"></i>
</Button> </button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'; import { ref, onMounted, onUnmounted } from 'vue';
import { useToast } from 'primevue/usetoast'; import { useToast } from 'primevue/usetoast';
import Button from 'primevue/button';
const toast = useToast(); const toast = useToast();
const visible = ref(false); const visible = ref(false);

View File

@@ -5,7 +5,6 @@
<div class="contribute-buttons"> <div class="contribute-buttons">
<a :href="bugReportUrl" target="_blank" rel="noreferrer" class="contribute-button"> <a :href="bugReportUrl" target="_blank" rel="noreferrer" class="contribute-button">
<i class="pi pi-exclamation-triangle"></i> <i class="pi pi-exclamation-triangle"></i>
<span>Report an issue</span> <span>Report an issue</span>
</a> </a>
@@ -13,7 +12,6 @@
<a :href="featureRequestUrl" target="_blank" rel="noreferrer" class="contribute-button"> <a :href="featureRequestUrl" target="_blank" rel="noreferrer" class="contribute-button">
<i class="pi pi-lightbulb"></i> <i class="pi pi-lightbulb"></i>
<span>Request a feature</span> <span>Request a feature</span>
</a> </a>
</div> </div>

View File

@@ -1,7 +1,6 @@
<template> <template>
<div> <div>
<h2 class="demo-title">Customize</h2> <h2 class="demo-title">Customize</h2>
<slot /> <slot />
</div> </div>
</template> </template>

View File

@@ -1,7 +1,6 @@
<template> <template>
<div class="preview-color"> <div class="preview-color">
<span class="color-label">{{ title }}</span> <span class="color-label">{{ title }}</span>
<input :value="modelValue" @input="handleColorChange" type="color" :disabled="disabled" class="color-input" /> <input :value="modelValue" @input="handleColorChange" type="color" :disabled="disabled" class="color-input" />
</div> </div>
</template> </template>

View File

@@ -66,28 +66,6 @@ import ContributionSection from './ContributionSection.vue';
</script> </script>
<style scoped> <style scoped>
.tabbed-layout {
width: 100%;
}
.tab-header {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
border: 1px solid #142216;
border-radius: 10px;
font-size: 14px;
height: 36px;
color: #ffffff;
background: transparent;
transition: all 0.3s ease;
}
.tab-header:hover {
background: #142216;
}
:deep(.p-tablist), :deep(.p-tablist),
:deep(.p-tablist-tab-list) { :deep(.p-tablist-tab-list) {
display: flex; display: flex;

View File

@@ -116,7 +116,6 @@
border: none; border: none;
border-radius: 50px; border-radius: 50px;
cursor: pointer; cursor: pointer;
display: flex; display: flex;
align-items: center; align-items: center;
white-space: nowrap; white-space: nowrap;
@@ -133,7 +132,6 @@
border-radius: 50px; border-radius: 50px;
width: 100px; width: 100px;
font-weight: 600; font-weight: 600;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -146,15 +144,24 @@
transition: 0.3s ease; transition: 0.3s ease;
} }
.cta-button:hover {
transition: 0.3s ease;
}
.cta-button:hover span img { .cta-button:hover span img {
transform: scale(1.2); transform: scale(1.2);
transition: 0.3s ease; transition: 0.3s ease;
} }
@media (min-width: 900px) {
.landing-nav-items {
display: flex;
align-items: center;
justify-content: space-between;
gap: 2rem;
}
.nav-cta-group {
gap: 2rem;
}
}
@media (max-width: 900px) { @media (max-width: 900px) {
.header { .header {
padding: 0 2em; padding: 0 2em;
@@ -295,16 +302,3 @@
margin-right: 1px; margin-right: 1px;
} }
} }
@media (min-width: 900px) {
.landing-nav-items {
display: flex;
align-items: center;
justify-content: space-between;
gap: 2rem;
}
.nav-cta-group {
gap: 2rem;
}
}

View File

@@ -67,30 +67,6 @@
text-align: center; text-align: center;
} }
@media (max-width: 768px) {
.features-title {
font-size: 2.5rem;
}
.features-subtitle {
font-size: 1.1rem;
}
.features-header {
margin-bottom: 3rem;
}
}
@media (max-width: 480px) {
.features-title {
font-size: 2rem;
}
.features-subtitle {
font-size: 1rem;
}
}
.bento-grid { .bento-grid {
max-width: 1200px; max-width: 1200px;
display: grid; display: grid;
@@ -99,73 +75,6 @@
grid-auto-rows: auto; grid-auto-rows: auto;
} }
@media (min-width: 480px) and (max-width: 767px) {
.bento-grid {
grid-template-columns: repeat(2, 1fr);
gap: 1.25em;
}
.card1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
.card2 {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
.card4 {
grid-column: 2 / 3;
grid-row: 2 / 3;
}
}
@media (min-width: 50rem) {
.bento-grid {
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, auto);
gap: 1.5em;
}
.card1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
.card2 {
grid-column: 3 / 5;
grid-row: 1 / 3;
}
.card4 {
grid-column: 1 / 3;
grid-row: 2 / 3;
}
}
@media (min-width: 768px) and (max-width: 49.99rem) {
.bento-grid {
grid-template-columns: repeat(3, 1fr);
gap: 1.25em;
}
.card1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
.card2 {
grid-column: 3 / 4;
grid-row: 1 / 3;
}
.card4 {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
}
.feature-card { .feature-card {
user-select: none; user-select: none;
background: #0b0b0b; background: #0b0b0b;
@@ -324,136 +233,24 @@
pointer-events: none; pointer-events: none;
} }
.components-gif-wrapper { .components-gif-wrapper,
position: absolute; .messages-gif-wrapper,
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 1;
overflow: hidden;
opacity: 0;
transition: opacity 0.3s ease;
}
.feature-card:hover .components-gif-wrapper {
opacity: 1;
}
.components-gif {
width: 100%;
height: auto;
opacity: 0.2;
mix-blend-mode: lighten;
display: block;
filter: grayscale(100%);
}
.components-gif-wrapper::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 20%;
background: linear-gradient(to top, #0b0b0b 0%, transparent 100%);
border-radius: 0 0 8px 8px;
pointer-events: none;
z-index: 2;
}
.components-gif-wrapper::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 20%;
background: linear-gradient(to bottom, #0b0b0b 0%, transparent 100%);
border-radius: 8px 8px 0 0;
pointer-events: none;
z-index: 2;
}
.messages-gif-wrapper {
position: absolute;
mix-blend-mode: lighten;
top: 0.5rem;
right: 1rem;
bottom: 1rem;
width: 50%;
border-radius: 8px;
z-index: 1;
overflow: hidden;
opacity: 0;
transition: opacity 0.3s ease;
}
.feature-card:hover .messages-gif-wrapper {
opacity: 1;
}
.messages-gif {
width: 100%;
height: 100%;
object-fit: contain;
border-radius: 0;
opacity: 0.3;
display: block;
}
.messages-gif-wrapper::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 20%;
background: linear-gradient(to top, #0b0b0b 0%, transparent 100%);
border-radius: 0 0 8px 8px;
pointer-events: none;
z-index: 2;
}
.messages-gif-wrapper::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 20%;
background: linear-gradient(to bottom, #0b0b0b 0%, transparent 100%);
border-radius: 8px 8px 0 0;
pointer-events: none;
z-index: 2;
}
.switch-gif-wrapper { .switch-gif-wrapper {
position: absolute; position: absolute;
top: 0;
right: 1rem;
width: 40%;
mix-blend-mode: lighten;
border-radius: 8px;
z-index: 1; z-index: 1;
overflow: hidden; overflow: hidden;
opacity: 0; opacity: 0;
transition: opacity 0.3s ease; transition: opacity 0.3s ease;
} }
.feature-card:hover .components-gif-wrapper,
.feature-card:hover .messages-gif-wrapper,
.feature-card:hover .switch-gif-wrapper { .feature-card:hover .switch-gif-wrapper {
opacity: 1; opacity: 1;
} }
.switch-gif { .components-gif-wrapper::after,
width: 100%; .messages-gif-wrapper::after,
height: 100%;
object-fit: contain;
border-radius: 0;
opacity: 0.3;
display: block;
}
.switch-gif-wrapper::after { .switch-gif-wrapper::after {
content: ''; content: '';
position: absolute; position: absolute;
@@ -467,6 +264,8 @@
z-index: 2; z-index: 2;
} }
.components-gif-wrapper::before,
.messages-gif-wrapper::before,
.switch-gif-wrapper::before { .switch-gif-wrapper::before {
content: ''; content: '';
position: absolute; position: absolute;
@@ -480,43 +279,50 @@
z-index: 2; z-index: 2;
} }
@media (max-width: 479px) { .components-gif-wrapper {
.features-section { width: 100%;
padding: 4rem 1rem 2rem; height: 100%;
padding-bottom: 0; left: 0;
margin-top: 4em; top: 0;
} }
.bento-grid { .messages-gif-wrapper {
gap: 1rem; mix-blend-mode: lighten;
max-width: 100%; top: 0.5rem;
right: 1rem;
bottom: 1rem;
width: 50%;
border-radius: 8px;
} }
.feature-card { .switch-gif-wrapper {
min-height: 160px; top: 0;
padding: 1.25rem; right: 1rem;
border-radius: 12px; width: 40%;
mix-blend-mode: lighten;
border-radius: 8px;
} }
.feature-icon { .components-gif,
font-size: 1.75rem; .messages-gif,
margin-bottom: 0.75rem; .switch-gif {
width: 100%;
height: auto;
opacity: 0.2;
mix-blend-mode: lighten;
display: block;
filter: grayscale(100%);
border-radius: 0;
} }
.feature-card h2 { .messages-gif,
font-size: 4rem; .switch-gif {
} height: 100%;
object-fit: contain;
.feature-card h3 { opacity: 0.3;
font-size: 1rem;
margin-bottom: 0.5rem;
}
.feature-card p {
font-size: 0.85rem;
line-height: 1.6;
} }
@media (max-width: 49.99rem) {
.components-gif-wrapper, .components-gif-wrapper,
.messages-gif-wrapper, .messages-gif-wrapper,
.switch-gif-wrapper { .switch-gif-wrapper {
@@ -557,11 +363,87 @@
font-size: 0.8rem; font-size: 0.8rem;
line-height: 1.7; line-height: 1.7;
} }
}
.components-gif-wrapper, @media (max-width: 479px) {
.messages-gif-wrapper, .features-section {
.switch-gif-wrapper { padding: 4rem 1rem 2rem;
display: none !important; padding-bottom: 0;
margin-top: 4em;
}
.features-title {
font-size: 2rem;
}
.features-subtitle {
font-size: 1rem;
}
.bento-grid {
gap: 1rem;
max-width: 100%;
}
.feature-card {
min-height: 160px;
padding: 1.25rem;
border-radius: 12px;
}
.feature-icon {
font-size: 1.75rem;
margin-bottom: 0.75rem;
}
.feature-card h2 {
font-size: 4rem;
}
.feature-card h3 {
font-size: 1rem;
margin-bottom: 0.5rem;
}
.feature-card p {
font-size: 0.85rem;
line-height: 1.6;
}
}
@media (min-width: 480px) and (max-width: 767px) {
.bento-grid {
grid-template-columns: repeat(2, 1fr);
gap: 1.25em;
}
.card1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
.card2 {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
.card4 {
grid-column: 2 / 3;
grid-row: 2 / 3;
}
}
@media (max-width: 768px) {
.features-title {
font-size: 2.5rem;
}
.features-subtitle {
font-size: 1.1rem;
}
.features-header {
margin-bottom: 3rem;
} }
} }
@@ -588,11 +470,27 @@
.feature-card p { .feature-card p {
font-size: 0.92rem; font-size: 0.92rem;
} }
}
.components-gif-wrapper, @media (min-width: 768px) and (max-width: 49.99rem) {
.messages-gif-wrapper, .bento-grid {
.switch-gif-wrapper { grid-template-columns: repeat(3, 1fr);
display: none !important; gap: 1.25em;
}
.card1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
.card2 {
grid-column: 3 / 4;
grid-row: 1 / 3;
}
.card4 {
grid-column: 1 / 2;
grid-row: 2 / 3;
} }
} }
@@ -603,6 +501,27 @@
margin-top: 8em; margin-top: 8em;
} }
.bento-grid {
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, auto);
gap: 1.5em;
}
.card1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
.card2 {
grid-column: 3 / 5;
grid-row: 1 / 3;
}
.card4 {
grid-column: 1 / 3;
grid-row: 2 / 3;
}
.feature-card { .feature-card {
min-height: 220px; min-height: 220px;
padding: 2rem; padding: 2rem;
@@ -620,12 +539,6 @@
.feature-card p { .feature-card p {
font-size: 0.95rem; font-size: 0.95rem;
} }
.components-gif-wrapper,
.messages-gif-wrapper,
.switch-gif-wrapper {
display: block !important;
}
} }
@media (max-height: 500px) and (orientation: landscape) { @media (max-height: 500px) and (orientation: landscape) {

View File

@@ -3,52 +3,39 @@
<div class="features-container"> <div class="features-container">
<div class="features-header"> <div class="features-header">
<h3 class="features-title">Zero cost, all the cool.</h3> <h3 class="features-title">Zero cost, all the cool.</h3>
<p class="features-subtitle">Everything you need to add flair to your websites</p> <p class="features-subtitle">Everything you need to add flair to your websites</p>
</div> </div>
<GlobalSpotlight v-if="gridRef" :grid-ref="gridRef" :disable-animations="isMobile" />
<div class="bento-grid" ref="gridRef"> <div class="bento-grid" ref="gridRef">
<ParticleCard class="feature-card card1" :disable-animations="isMobile"> <ParticleCard class="feature-card card1" :disable-animations="isMobile">
<div className="messages-gif-wrapper"> <div class="messages-gif-wrapper">
<img src="/assets/messages.gif" alt="Messages animation" className="messages-gif" /> <img src="/assets/messages.gif" alt="Messages animation" class="messages-gif" />
</div> </div>
<h2> <h2>
<template v-if="isMobile">100</template> <template v-if="isMobile">100</template>
<CountUp v-else :to="100" /> <CountUp v-else :to="100" />
% %
</h2> </h2>
<h3>Free &amp; Open Source</h3> <h3>Free &amp; Open Source</h3>
<p>Loved by developers around the world</p> <p>Loved by developers around the world</p>
</ParticleCard> </ParticleCard>
<ParticleCard class="feature-card card2" :disable-animations="isMobile"> <ParticleCard class="feature-card card2" :disable-animations="isMobile">
<div className="components-gif-wrapper"> <div class="components-gif-wrapper">
<img src="/assets/components.gif" alt="Components animation" className="components-gif" /> <img src="/assets/components.gif" alt="Components animation" class="components-gif" />
</div> </div>
<h2> <h2>
<template v-if="isMobile">40</template> <template v-if="isMobile">40</template>
<CountUp v-else :to="40" /> <CountUp v-else :to="40" />
+ +
</h2> </h2>
<h3>Curated Components</h3> <h3>Curated Components</h3>
<p>Growing weekly &amp; only getting better</p> <p>Growing weekly &amp; only getting better</p>
</ParticleCard> </ParticleCard>
<ParticleCard class="feature-card card4" :disable-animations="isMobile"> <ParticleCard class="feature-card card4" :disable-animations="isMobile">
<h2>Modern</h2> <h2>Modern</h2>
<h3>Technologies</h3> <h3>Technologies</h3>
<p>TypeScript + Tailwind, ready to ship</p> <p>TypeScript + Tailwind, ready to ship</p>
</ParticleCard> </ParticleCard>
</div> </div>
@@ -200,102 +187,4 @@ const ParticleCard = defineComponent({
); );
} }
}); });
const GlobalSpotlight = defineComponent({
name: 'GlobalSpotlight',
props: {
gridRef: {
type: Object,
required: true
},
disableAnimations: {
type: Boolean,
default: false
}
},
setup(props) {
const spotlightRef = ref<HTMLDivElement | null>(null);
const isInsideSectionRef = ref(false);
const handleMouseMove = (e: MouseEvent) => {
if (!spotlightRef.value || !props.gridRef.value) return;
const section = props.gridRef.value.closest('.features-section');
const rect = section?.getBoundingClientRect();
const inside =
rect && e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
isInsideSectionRef.value = inside;
const cards = props.gridRef.value.querySelectorAll('.feature-card');
if (!inside) {
gsap.to(spotlightRef.value, { opacity: 0, duration: 0.3, ease: 'power2.out' });
cards.forEach((card: HTMLElement) => card.style.setProperty('--glow-intensity', '0'));
return;
}
let minDist = Infinity;
const prox = 100,
fade = 150;
cards.forEach((card: HTMLElement) => {
const r = card.getBoundingClientRect();
const cx = r.left + r.width / 2;
const cy = r.top + r.height / 2;
const d = Math.hypot(e.clientX - cx, e.clientY - cy) - Math.max(r.width, r.height) / 2;
const ed = Math.max(0, d);
minDist = Math.min(minDist, ed);
const rx = ((e.clientX - r.left) / r.width) * 100;
const ry = ((e.clientY - r.top) / r.height) * 100;
let glow = 0;
if (ed <= prox) glow = 1;
else if (ed <= fade) glow = (fade - ed) / (fade - prox);
card.style.setProperty('--glow-x', `${rx}%`);
card.style.setProperty('--glow-y', `${ry}%`);
card.style.setProperty('--glow-intensity', String(glow));
});
gsap.to(spotlightRef.value, { left: e.clientX, top: e.clientY, duration: 0.1, ease: 'power2.out' });
const target = minDist <= prox ? 0.8 : minDist <= fade ? ((fade - minDist) / (fade - prox)) * 0.8 : 0;
gsap.to(spotlightRef.value, { opacity: target, duration: target > 0 ? 0.2 : 0.5, ease: 'power2.out' });
};
const handleMouseLeave = () => {
isInsideSectionRef.value = false;
props.gridRef.value
?.querySelectorAll('.feature-card')
.forEach((card: HTMLElement) => card.style.setProperty('--glow-intensity', '0'));
if (spotlightRef.value) {
gsap.to(spotlightRef.value, { opacity: 0, duration: 0.3, ease: 'power2.out' });
}
};
onMounted(() => {
if (props.disableAnimations || !props.gridRef?.value) return;
const spotlight = document.createElement('div');
spotlight.className = 'global-spotlight';
spotlight.style.cssText = `
position:fixed;width:800px;height:800px;border-radius:50%;pointer-events:none;
background:radial-gradient(circle,rgba(132,0,255,.15) 0%,rgba(132,0,255,.08) 15%,
rgba(132,0,255,.04) 25%,rgba(132,0,255,.02) 40%,rgba(132,0,255,.01) 65%,transparent 70%);
z-index:200;opacity:0;transform:translate(-50%,-50%);mix-blend-mode:screen;
`;
document.body.appendChild(spotlight);
spotlightRef.value = spotlight;
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseleave', handleMouseLeave);
});
onUnmounted(() => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseleave', handleMouseLeave);
if (spotlightRef.value?.parentNode) {
spotlightRef.value.parentNode.removeChild(spotlightRef.value);
}
});
return () => null;
}
});
</script> </script>

View File

@@ -12,7 +12,7 @@
<a href="https://davidhaz.com/" target="_blank" class="footer-creator-link">this guy</a> <a href="https://davidhaz.com/" target="_blank" class="footer-creator-link">this guy</a>
</p> </p>
<p class="footer-copyright">© {{ currentYear }} Vue Bits</p> <p class="footer-copyright">© {{ new Date().getFullYear() }} Vue Bits</p>
</div> </div>
<div class="footer-links"> <div class="footer-links">
@@ -21,9 +21,7 @@
</a> </a>
<router-link to="/text-animations/split-text" class="footer-link">Docs</router-link> <router-link to="/text-animations/split-text" class="footer-link">Docs</router-link>
<a href="https://www.jsrepo.com/" target="_blank" class="footer-link">CLI</a> <a href="https://www.jsrepo.com/" target="_blank" class="footer-link">CLI</a>
<a href="https://reactbits.dev/" target="_blank" class="footer-link">React Bits</a> <a href="https://reactbits.dev/" target="_blank" class="footer-link">React Bits</a>
</div> </div>
</div> </div>
@@ -32,10 +30,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue';
import vueBitsLogo from '../../../assets/logos/vue-bits-logo.svg'; import vueBitsLogo from '../../../assets/logos/vue-bits-logo.svg';
import FadeContent from '@/content/Animations/FadeContent/FadeContent.vue'; import FadeContent from '@/content/Animations/FadeContent/FadeContent.vue';
import './Footer.css'; import './Footer.css';
const currentYear = computed(() => new Date().getFullYear());
</script> </script>

View File

@@ -3,7 +3,6 @@
<div class="start-building-container"> <div class="start-building-container">
<div class="start-building-card"> <div class="start-building-card">
<h2 class="start-building-title">Start exploring Vue Bits</h2> <h2 class="start-building-title">Start exploring Vue Bits</h2>
<p class="start-building-subtitle">Animations, components, backgrounds - it's all here</p> <p class="start-building-subtitle">Animations, components, backgrounds - it's all here</p>
<router-link to="/text-animations/split-text" class="start-building-button">Browse Components</router-link> <router-link to="/text-animations/split-text" class="start-building-button">Browse Components</router-link>

View File

@@ -12,31 +12,14 @@
<Toast <Toast
position="bottom-right" position="bottom-right"
:closeButtonProps="{ style: { right: '0', margin: '0', outline: 'none', border: 'none' } }" :closeButtonProps="customToastStyles.customToastCloseButton"
:pt="{ :pt="customToastStyles"
message: {
style: {
borderRadius: '10px',
border: '1px solid #142216',
backgroundColor: '#0b0b0b'
}
},
messageContent: {
style: {
alignItems: 'center'
}
},
messageIcon: {
style: {
display: 'none'
}
}
}"
/> />
</main> </main>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { customToastStyles } from '@/utils/utils';
import Header from '../navs/Header.vue'; import Header from '../navs/Header.vue';
import Sidebar from '../navs/Sidebar.vue'; import Sidebar from '../navs/Sidebar.vue';
</script> </script>

View File

@@ -35,8 +35,6 @@
</div> </div>
<div class="drawer-body"> <div class="drawer-body">
<!-- Navigation Categories -->
<div class="drawer-navigation"> <div class="drawer-navigation">
<div class="categories-container"> <div class="categories-container">
<Category <Category

View File

@@ -1,6 +1,4 @@
<template> <template>
<!-- Mobile Drawer -->
<div v-if="isDrawerOpen" class="drawer-overlay" @click="closeDrawer"> <div v-if="isDrawerOpen" class="drawer-overlay" @click="closeDrawer">
<div class="drawer-content" :class="{ 'drawer-open': isDrawerOpen }" @click.stop> <div class="drawer-content" :class="{ 'drawer-open': isDrawerOpen }" @click.stop>
<div class="drawer-header sidebar-logo"> <div class="drawer-header sidebar-logo">
@@ -60,8 +58,6 @@
</div> </div>
</div> </div>
<!-- Desktop Sidebar -->
<nav <nav
ref="sidebarContainerRef" ref="sidebarContainerRef"
class="sidebar" class="sidebar"
@@ -69,8 +65,6 @@
@scroll="handleScroll" @scroll="handleScroll"
> >
<div ref="sidebarRef" class="sidebar-content"> <div ref="sidebarRef" class="sidebar-content">
<!-- Active line indicator -->
<div <div
class="active-line" class="active-line"
:style="{ :style="{
@@ -80,8 +74,6 @@
}" }"
></div> ></div>
<!-- Hover line indicator -->
<div <div
class="hover-line" class="hover-line"
:style="{ :style="{

View File

@@ -25,8 +25,28 @@ body {
} }
.back-to-top { .back-to-top {
background: #0b0b0b !important; background: #0b0b0b;
aspect-ratio: 1;
font-weight: 500;
border-radius: 0.75rem;
border: 1px solid #142216; border: 1px solid #142216;
width: 50px;
position: fixed;
right: 2.3em;
z-index: 98;
box-shadow: 10px 0 25px rgba(0, 0, 0, 0.2);
transition:
opacity 0.3s ease,
bottom 0.3s ease;
opacity: 0;
bottom: 1em;
cursor: default;
}
.back-to-top.visible {
opacity: 1;
bottom: 2.5em;
cursor: pointer;
} }
@media (max-width: 640px) { @media (max-width: 640px) {

View File

@@ -212,6 +212,106 @@ div:has(> .props-table) {
background-color: #222; background-color: #222;
} }
.tabbed-layout {
width: 100%;
}
.tab-header {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
border: 1px solid #142216;
border-radius: 10px;
font-size: 14px;
height: 36px;
color: #ffffff;
background: transparent;
transition: all 0.3s ease;
}
.tab-header:hover {
background: #142216;
}
.code-example {
margin: 1.2rem 0;
}
.code-section {
margin-bottom: 2rem;
}
.code-container {
position: relative;
margin-bottom: 1.2rem;
}
.code-wrapper {
position: relative;
overflow: hidden;
border: 1px solid #142216;
border-radius: 15px;
}
.code-wrapper.collapsed {
max-height: 600px;
}
.code-block {
overflow: hidden;
border: none;
border-radius: 15px;
}
.fade-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 60%;
background: linear-gradient(to bottom, transparent, #0b0b0b);
pointer-events: none;
z-index: 1;
}
.expand-button {
position: absolute;
bottom: 0.75rem;
right: 0.75rem;
padding: 0.5rem 1rem;
border-radius: 12px;
height: 2.5rem;
font-size: 14px;
font-weight: 500;
background-color: #0b0b0b;
border: 1px solid #142216;
color: white;
cursor: pointer;
z-index: 2;
transition: background-color 0.3s ease;
}
.expand-button:hover {
background-color: #111;
}
.expand-button:active {
background-color: #111;
}
.no-code {
display: flex;
align-items: center;
gap: 0.5rem;
color: #a1a1aa;
font-style: italic;
padding: 2rem;
background: #0b0b0b;
border: 1px solid #142216;
border-radius: 15px;
}
.demo-title { .demo-title {
font-weight: 900; font-weight: 900;
font-size: 1.6rem; font-size: 1.6rem;

View File

@@ -8,21 +8,17 @@ import { createApp } from 'vue';
import App from './App.vue'; import App from './App.vue';
import router from './router'; import router from './router';
import PrimeVue from 'primevue/config';
import Aura from '@primeuix/themes/aura';
import Button from 'primevue/button';
import Toast from 'primevue/toast';
import Select from 'primevue/select';
import ToastService from 'primevue/toastservice'; import ToastService from 'primevue/toastservice';
import Aura from '@primeuix/themes/aura';
import PrimeVue from 'primevue/config';
import Button from 'primevue/button';
import Select from 'primevue/select';
import Toast from 'primevue/toast';
const app = createApp(App); const app = createApp(App);
app.use(router); app.use(router);
app.use(PrimeVue, { app.use(PrimeVue, { theme: { preset: Aura } });
theme: {
preset: Aura
}
});
app.use(ToastService); app.use(ToastService);
app.component('Button', Button); app.component('Button', Button);

View File

@@ -24,7 +24,6 @@ import { useRoute } from 'vue-router';
import { componentMap } from '../constants/Components'; import { componentMap } from '../constants/Components';
import { decodeLabel } from '../utils/utils'; import { decodeLabel } from '../utils/utils';
import BackToTopButton from '@/components/common/BackToTopButton.vue'; import BackToTopButton from '@/components/common/BackToTopButton.vue';
import '../css/category.css';
const route = useRoute(); const route = useRoute();
const scrollRef = ref<HTMLDivElement | null>(null); const scrollRef = ref<HTMLDivElement | null>(null);
@@ -48,9 +47,9 @@ const SubcategoryComponent = computed(() => {
watch( watch(
decodedLabel, decodedLabel,
newLabel => { label => {
if (newLabel) { if (label) {
document.title = `Vue Bits - ${newLabel}`; document.title = `Vue Bits - ${label}`;
} }
}, },
{ immediate: true } { immediate: true }

View File

@@ -10,13 +10,9 @@
</div> </div>
<PlasmaWave :y-offset="-300" :x-offset="100" :rotation-deg="-30" /> <PlasmaWave :y-offset="-300" :x-offset="100" :rotation-deg="-30" />
<Hero /> <Hero />
<FeatureCards /> <FeatureCards />
<StartBuilding /> <StartBuilding />
<Footer /> <Footer />
</section> </section>
</template> </template>

View File

@@ -32,3 +32,27 @@ export const decodeLabel = (label: string): string => {
.map(word => word.charAt(0).toUpperCase() + word.slice(1)) .map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' '); .join(' ');
}; };
/**
* Custom styles for PrimeVue Toast component
*/
export const customToastStyles = {
message: {
style: {
borderRadius: '10px',
border: '1px solid #142216',
backgroundColor: '#0b0b0b'
}
},
messageContent: {
style: {
alignItems: 'center'
}
},
messageIcon: {
style: {
display: 'none'
}
},
customToastCloseButton: { style: { right: '0', margin: '0', outline: 'none', border: 'none' } }
};