Utility Components
Utility components provide specialized functionality like animations, background effects, and complex content sections.
Animate
Animation wrapper component using AOS (Animate On Scroll) library for scroll-triggered animations.
Source: components/misc/Animate.vue
Props
Whether the component should take full width (w-full)
Animation type. Available values: fade, zoom, flip, slide
Animation direction. Available values: up, down, left, right, in, out
Animation duration in milliseconds
Usage
<script setup>
import Animate from '~/components/misc/Animate.vue'
</script>
<template>
<!-- Fade up animation (default) -->
<Animate>
<div>This will fade up on scroll</div>
</Animate>
<!-- Zoom in animation -->
<Animate type="zoom" to="in">
<div>This will zoom in on scroll</div>
</Animate>
<!-- Slide from right -->
<Animate type="fade" to="right" :duration="800">
<div>This will slide from right with 800ms duration</div>
</Animate>
<!-- Non-full width -->
<Animate :full="false" to="left">
<span>Inline animated element</span>
</Animate>
</template>
Implementation Details
The component combines the type and to props to create AOS data attributes:
components/misc/Animate.vue:23-28
<div
:class="{ 'w-full': full }"
:data-aos="`${type}-${to}`"
:data-aos-duration="duration"
data-aos-once="true"
>
Animations only trigger once (data-aos-once="true").
BlobBackground
Decorative animated background component for hero and section areas.
Source: components/misc/BlobBackground.vue
Props
Whether this is a hero background (uses different image and sizing)
Whether to flip the background horizontally using Y-axis rotation
Usage
<script setup>
import BlobBackground from '~/components/misc/BlobBackground.vue'
import Section from '~/components/layout/Section.vue'
</script>
<template>
<!-- Hero background -->
<Section class="relative">
<BlobBackground hero />
<div class="relative z-10">
<!-- Hero content here -->
</div>
</Section>
<!-- Section background (normal) -->
<Section class="relative">
<BlobBackground />
<div class="relative z-10">
<!-- Section content here -->
</div>
</Section>
<!-- Section background (inverted) -->
<Section class="relative">
<BlobBackground :invert="true" />
<div class="relative z-10">
<!-- Section content here -->
</div>
</Section>
</template>
Styling
- Uses absolute positioning with
inset-0 to cover the entire parent
- Has
z-0 to stay behind content
- Opacity is set to 25% (
opacity-25)
- Different background images in dark mode:
- Hero:
hero-dark.webp
- Section:
section-dark.webp
The parent container must have position: relative and content should have a higher z-index (e.g., z-10) to appear above the background.
Projects
Complete project showcase component with filtering by category.
Source: components/misc/Projects.vue
Props
Optional pre-selected category filter
Project Interface
components/misc/Projects.vue:16-24
interface Project {
image: string
title: string
description: string
technologies: string[]
github?: string
url?: string
category: string
}
Category Interface
components/misc/Projects.vue:26-29
interface Category {
label: string
value: string
}
Available Categories
- all - All projects (default)
- website - Website projects
- web-application - Web application projects
- resources - Resource projects
Usage
<script setup>
import Projects from '~/components/misc/Projects.vue'
import Section from '~/components/layout/Section.vue'
</script>
<template>
<Section title="My Projects">
<!-- Shows all projects with filtering -->
<Projects />
</Section>
<!-- Pre-filter to show only websites -->
<Section title="Websites">
<Projects category="website" />
</Section>
</template>
Features
- Category Filtering - Filter buttons with project counts
- Project Display - Alternating left/right image layout
- Animations - Projects animate in from alternating directions
- Technologies - Badge display of technologies used
- Links - External links to project URL and GitHub repository
- Responsive - Mobile-friendly column layout, desktop row layout
Customization
To add or modify projects, edit the projects array in components/misc/Projects.vue:31-114:
const projects: Project[] = [
{
image: 'project-screenshot',
title: 'Project Name',
description: 'Project description',
technologies: ['Vue.js', 'TailwindCSS', 'Laravel'],
github: 'repo-name',
url: 'https://example.com',
category: 'website',
},
// ... more projects
]
Place project screenshots in /public/images/projects/ directory with .webp format for optimal performance.
References
Company references/logos gallery component.
Source: components/misc/References.vue
Reference Interface
components/misc/References.vue:4-7
interface Reference {
name: string
image: string
}
Usage
<script setup>
import References from '~/components/misc/References.vue'
import Section from '~/components/layout/Section.vue'
</script>
<template>
<Section title="Trusted By">
<References />
</Section>
</template>
Features
- Responsive Grid - 2 columns on mobile, 3 on tablet, flexible wrap on desktop
- Animations - All logos animate up on scroll
- Image Optimization - Uses Nuxt Image component for optimized loading
Customization
To add or modify references, edit the references array in components/misc/References.vue:9-34:
const references: Reference[] = [
{
name: 'Company Name',
image: 'company-logo',
},
// ... more references
]
Place company logos in /public/images/references/ directory with .webp format. Logos should be around 128px width for consistency.
Import Pattern
All utility components follow the same import pattern:
<script setup>
import Animate from '~/components/misc/Animate.vue'
import BlobBackground from '~/components/misc/BlobBackground.vue'
import Projects from '~/components/misc/Projects.vue'
import References from '~/components/misc/References.vue'
</script>
Common Use Cases
Animated Section with Background
<Section class="relative" title="About Me">
<BlobBackground />
<div class="relative z-10">
<Animate type="fade" to="up">
<p>Your content here</p>
</Animate>
</div>
</Section>
Staggered Animations
<Stack>
<Animate to="left">
<Card title="First" />
</Animate>
<Animate to="right">
<Card title="Second" />
</Animate>
<Animate to="left">
<Card title="Third" />
</Animate>
</Stack>