removed parallax, added flags to footer
This commit is contained in:
@@ -7,7 +7,7 @@ export interface Props {
|
||||
disableParallax?: boolean;
|
||||
}
|
||||
|
||||
const { isDark = false, showIcons = true, disableParallax = false } = Astro.props;
|
||||
const { isDark = false, showIcons = true, disableParallax = true } = Astro.props;
|
||||
|
||||
// Define color palettes for light and dark modes with higher contrast
|
||||
const lightModeColors = [
|
||||
@@ -22,14 +22,14 @@ const lightModeColors = [
|
||||
];
|
||||
|
||||
const darkModeColors = [
|
||||
'dark:text-blue-400/45',
|
||||
'dark:text-indigo-400/45',
|
||||
'dark:text-purple-400/45',
|
||||
'dark:text-cyan-400/45',
|
||||
'dark:text-teal-400/45',
|
||||
'dark:text-emerald-400/45',
|
||||
'dark:text-sky-400/45',
|
||||
'dark:text-violet-400/45',
|
||||
'dark:text-blue-500/65',
|
||||
'dark:text-indigo-500/65',
|
||||
'dark:text-purple-500/65',
|
||||
'dark:text-cyan-500/65',
|
||||
'dark:text-teal-500/65',
|
||||
'dark:text-emerald-500/65',
|
||||
'dark:text-sky-500/65',
|
||||
'dark:text-violet-500/65',
|
||||
];
|
||||
|
||||
// Define interfaces for our icon objects
|
||||
@@ -98,14 +98,20 @@ const getRandomRotation = (): string => {
|
||||
return `${getRandomInRange(-30, 30)}deg`;
|
||||
};
|
||||
|
||||
// Function to get a random size (restored to original dimensions)
|
||||
const getRandomSize = (): string => {
|
||||
return `${getRandomInRange(140, 180)}px`;
|
||||
// Function to get a random size
|
||||
const getRandomSize = (isDarkMode: boolean = false): string => {
|
||||
// Slightly larger size range for dark mode for better visibility
|
||||
return isDarkMode
|
||||
? `${getRandomInRange(160, 200)}px`
|
||||
: `${getRandomInRange(140, 180)}px`;
|
||||
};
|
||||
|
||||
// Function to get a random opacity
|
||||
const getRandomOpacity = (): string => {
|
||||
return getRandomInRange(0.32, 0.38).toFixed(2);
|
||||
const getRandomOpacity = (isDarkMode: boolean = false): string => {
|
||||
// Higher opacity range for dark mode for better visibility
|
||||
return isDarkMode
|
||||
? getRandomInRange(0.45, 0.55).toFixed(2)
|
||||
: getRandomInRange(0.32, 0.38).toFixed(2);
|
||||
};
|
||||
|
||||
// Create a spacious layout with well-separated icons
|
||||
@@ -172,8 +178,8 @@ const createSpacedIcons = (): BaseIconObject[] => {
|
||||
icon: iconNames[iconIndex],
|
||||
x: `${x}%`,
|
||||
y: `${y}%`,
|
||||
size: getRandomSize(),
|
||||
opacity: getRandomOpacity(),
|
||||
size: getRandomSize(isDark),
|
||||
opacity: getRandomOpacity(isDark),
|
||||
rotate: getRandomRotation(),
|
||||
});
|
||||
}
|
||||
@@ -200,15 +206,12 @@ const iconsWithColors: IconWithColors[] = icons.map(icon => ({
|
||||
<slot />
|
||||
|
||||
{showIcons && (
|
||||
/* Decorative background icons with parallax effect */
|
||||
<div id="parallax-background" class="absolute inset-0 overflow-hidden pointer-events-none z-[-5]">
|
||||
{iconsWithColors.map(({ icon, x, y, size, opacity, rotate, lightColor, darkColor }, index) => (
|
||||
/* Decorative background icons with random placement */
|
||||
<div id="background-icons" class="absolute inset-0 overflow-hidden pointer-events-none z-[-5]">
|
||||
{iconsWithColors.map(({ icon, x, y, size, opacity, rotate, lightColor, darkColor }) => (
|
||||
<div
|
||||
class={`absolute ${lightColor} ${darkColor} parallax-icon`}
|
||||
style={`left: ${x}; top: ${y}; opacity: ${opacity}; transform: rotate(${rotate}); will-change: transform; transition: transform 0.1s ease-out;`}
|
||||
data-depth={`${0.5 + (index % 3) * 0.2}`}
|
||||
data-initial-x={x}
|
||||
data-initial-y={y}
|
||||
class={`absolute ${lightColor} ${darkColor} background-icon`}
|
||||
style={`left: ${x}; top: ${y}; opacity: ${opacity}; transform: rotate(${rotate});`}
|
||||
>
|
||||
<Icon name={icon} style={`width: ${size}; height: ${size};`} />
|
||||
</div>
|
||||
|
@@ -20,14 +20,14 @@ const lightModeColors = [
|
||||
];
|
||||
|
||||
const darkModeColors = [
|
||||
'dark:text-blue-400/45',
|
||||
'dark:text-indigo-400/45',
|
||||
'dark:text-purple-400/45',
|
||||
'dark:text-cyan-400/45',
|
||||
'dark:text-teal-400/45',
|
||||
'dark:text-emerald-400/45',
|
||||
'dark:text-sky-400/45',
|
||||
'dark:text-violet-400/45',
|
||||
'dark:text-blue-500/65',
|
||||
'dark:text-indigo-500/65',
|
||||
'dark:text-purple-500/65',
|
||||
'dark:text-cyan-500/65',
|
||||
'dark:text-teal-500/65',
|
||||
'dark:text-emerald-500/65',
|
||||
'dark:text-sky-500/65',
|
||||
'dark:text-violet-500/65',
|
||||
];
|
||||
|
||||
// Define interfaces for our icon objects
|
||||
@@ -99,13 +99,19 @@ const getRandomRotation = (): string => {
|
||||
};
|
||||
|
||||
// Function to get a random size
|
||||
const getRandomSize = (): string => {
|
||||
return `${getRandomInRange(140, 180)}px`;
|
||||
const getRandomSize = (isDarkMode: boolean = false): string => {
|
||||
// Slightly larger size range for dark mode for better visibility
|
||||
return isDarkMode
|
||||
? `${getRandomInRange(160, 200)}px`
|
||||
: `${getRandomInRange(140, 180)}px`;
|
||||
};
|
||||
|
||||
// Function to get a random opacity
|
||||
const getRandomOpacity = (): string => {
|
||||
return getRandomInRange(0.32, 0.38).toFixed(2);
|
||||
const getRandomOpacity = (isDarkMode: boolean = false): string => {
|
||||
// Higher opacity range for dark mode for better visibility
|
||||
return isDarkMode
|
||||
? getRandomInRange(0.45, 0.55).toFixed(2)
|
||||
: getRandomInRange(0.32, 0.38).toFixed(2);
|
||||
};
|
||||
|
||||
// Create a spacious layout with well-separated icons
|
||||
@@ -188,8 +194,8 @@ const createSpacedIcons = (): BaseIconObject[] => {
|
||||
icon: iconNames[iconIndex],
|
||||
x: `${x}%`,
|
||||
y: `${y}%`,
|
||||
size: getRandomSize(),
|
||||
opacity: getRandomOpacity(),
|
||||
size: getRandomSize(isDark),
|
||||
opacity: getRandomOpacity(isDark),
|
||||
rotate: getRandomRotation(),
|
||||
visibilityClass, // Add the visibility class to the icon object
|
||||
});
|
||||
@@ -219,15 +225,12 @@ const iconsWithColors: IconWithColors[] = icons.map(icon => ({
|
||||
<div class="fixed inset-0 overflow-hidden pointer-events-none z-[-5]" aria-hidden="true">
|
||||
<div class:list={['absolute inset-0', { 'backdrop-blur-sm bg-white/5 dark:bg-gray-900/10': isDark }]}></div>
|
||||
|
||||
{/* Decorative background icons with parallax effect */}
|
||||
<div id="parallax-background" class="absolute inset-0 overflow-hidden">
|
||||
{iconsWithColors.map(({ icon, x, y, size, opacity, rotate, lightColor, darkColor, visibilityClass }, index) => (
|
||||
{/* Decorative background icons with random placement */}
|
||||
<div id="background-icons" class="absolute inset-0 overflow-hidden">
|
||||
{iconsWithColors.map(({ icon, x, y, size, opacity, rotate, lightColor, darkColor, visibilityClass }) => (
|
||||
<div
|
||||
class={`absolute ${lightColor} ${darkColor} parallax-icon ${visibilityClass}`}
|
||||
style={`left: ${x}; top: ${y}; opacity: ${opacity}; transform: rotate(${rotate}); will-change: transform; transition: transform 0.1s ease-out;`}
|
||||
data-depth={`${0.5 + (index % 3) * 0.2}`}
|
||||
data-initial-x={x}
|
||||
data-initial-y={y}
|
||||
class={`absolute ${lightColor} ${darkColor} ${visibilityClass}`}
|
||||
style={`left: ${x}; top: ${y}; opacity: ${opacity}; transform: rotate(${rotate});`}
|
||||
>
|
||||
<Icon name={icon} style={`width: ${size}; height: ${size};`} />
|
||||
</div>
|
||||
@@ -235,82 +238,4 @@ const iconsWithColors: IconWithColors[] = icons.map(icon => ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Parallax scrolling effect for background icons
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Get all parallax icons
|
||||
const parallaxIcons = document.querySelectorAll<HTMLElement>('.parallax-icon');
|
||||
|
||||
// Skip parallax on mobile devices for better performance
|
||||
const isMobile = window.matchMedia('(max-width: 768px)').matches;
|
||||
if (isMobile) return;
|
||||
|
||||
// Variables to track scroll position
|
||||
let lastScrollY = window.scrollY;
|
||||
let ticking = false;
|
||||
|
||||
// Function to update icon positions based on scroll
|
||||
const updateParallax = () => {
|
||||
parallaxIcons.forEach((icon) => {
|
||||
const depth = parseFloat(icon.getAttribute('data-depth') || '0.5');
|
||||
|
||||
// Calculate parallax offset based on scroll position and depth
|
||||
// Lower depth value means the icon moves slower (appears further away)
|
||||
const yOffset = (lastScrollY * depth * 0.15);
|
||||
|
||||
// Get the original rotation
|
||||
const transformValue = icon.style.transform;
|
||||
const rotateMatch = transformValue.match(/rotate\([^)]+\)/);
|
||||
const rotateValue = rotateMatch ? rotateMatch[0] : 'rotate(0deg)';
|
||||
|
||||
// Apply transform with the original rotation plus the parallax offset
|
||||
icon.style.transform = `${rotateValue} translate3d(0, ${yOffset}px, 0)`;
|
||||
});
|
||||
|
||||
ticking = false;
|
||||
};
|
||||
|
||||
// Throttle scroll events for better performance
|
||||
const onScroll = () => {
|
||||
lastScrollY = window.scrollY;
|
||||
|
||||
if (!ticking) {
|
||||
window.requestAnimationFrame(() => {
|
||||
updateParallax();
|
||||
ticking = false;
|
||||
});
|
||||
|
||||
ticking = true;
|
||||
}
|
||||
};
|
||||
|
||||
// Add scroll event listener
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
|
||||
// Update on resize (debounced)
|
||||
let resizeTimer: number;
|
||||
window.addEventListener('resize', () => {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(() => {
|
||||
// Check if device is now mobile and disable parallax if needed
|
||||
const isMobileNow = window.matchMedia('(max-width: 768px)').matches;
|
||||
|
||||
if (isMobileNow) {
|
||||
// Reset positions on mobile
|
||||
parallaxIcons.forEach((icon) => {
|
||||
const transformValue = icon.style.transform;
|
||||
const rotateMatch = transformValue.match(/rotate\([^)]+\)/);
|
||||
const rotateValue = rotateMatch ? rotateMatch[0] : 'rotate(0deg)';
|
||||
icon.style.transform = rotateValue;
|
||||
});
|
||||
} else {
|
||||
// Update parallax on desktop
|
||||
updateParallax();
|
||||
}
|
||||
}, 200) as unknown as number;
|
||||
}, { passive: true });
|
||||
|
||||
// Initial update
|
||||
updateParallax();
|
||||
});
|
||||
</script>
|
||||
<!-- Parallax effect removed while maintaining random icon placement -->
|
@@ -76,8 +76,13 @@ const {
|
||||
<!-- Left Section: Company Name and Business Details -->
|
||||
<div class="flex flex-col items-start space-y-2">
|
||||
<!-- Site Title -->
|
||||
<a class="inline-block font-bold text-xl" href={getHomePermalink(currentLang)}>
|
||||
<a class="inline-block font-bold text-2xl" href={getHomePermalink(currentLang)}>
|
||||
{SITE?.name}
|
||||
<span class="inline-flex items-center ml-2">
|
||||
<Icon name="circle-flags:nl" class="h-5 w-auto flag-square" />
|
||||
<span class="mx-1 text-gray-600 text-xl">🤝</span>
|
||||
<Icon name="circle-flags:eu" class="h-5 w-auto flag-square" />
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<!-- Business Information (Dutch Law Requirements) -->
|
||||
@@ -120,4 +125,11 @@ const {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
.flag-square {
|
||||
border-radius: 0 !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
@@ -7,8 +7,8 @@ export const getHeaderData = (lang = 'en') => {
|
||||
// For hash links on the homepage, we need special handling
|
||||
const homeHashLink = (hash) => {
|
||||
// Create an absolute path to the homepage with the language prefix
|
||||
// and then append the hash
|
||||
return getPermalink('/', 'page', lang) + hash;
|
||||
// and include the hash in the permalink generation
|
||||
return getPermalink('/' + hash, 'page', lang);
|
||||
};
|
||||
|
||||
return {
|
||||
|
@@ -57,7 +57,6 @@ const metadata = {
|
||||
<!-- Hero Widget -->
|
||||
<Hero
|
||||
id="hero"
|
||||
title="About Me"
|
||||
isDark={false}
|
||||
>
|
||||
<Fragment slot="subtitle">
|
||||
|
@@ -85,7 +85,7 @@ const tocItems = [
|
||||
</div>
|
||||
|
||||
<!-- Privacy Policy Content -->
|
||||
<div class="prose prose-lg max-w-4xl dark:prose-invert dark:prose-headings:text-slate-300 prose-md prose-headings:font-heading prose-headings:leading-tighter prose-headings:tracking-tighter prose-headings:font-bold prose-a:text-blue-600 dark:prose-a:text-blue-400 prose-img:rounded-md prose-img:shadow-lg">
|
||||
<div class="prose prose-lg max-w-4xl dark:prose-invert dark:prose-headings:text-slate-300 prose-md prose-headings:font-heading prose-headings:leading-tighter prose-headings:tracking-tighter prose-headings:font-bold prose-a:text-blue-600 dark:prose-a:text-blue-400 prose-img:rounded-md prose-img:shadow-lg backdrop-blur-sm bg-white/15 dark:bg-slate-900/30 p-6 rounded-lg border border-gray-200 dark:border-slate-800">
|
||||
<h2 id="introduction" class="text-2xl font-bold mt-8 mb-4">1. Introduction</h2>
|
||||
<p>
|
||||
This Privacy Policy explains how we handle information when you visit our website. We are committed to protecting your privacy and complying with applicable data protection laws, including the General Data Protection Regulation (GDPR).
|
||||
|
@@ -83,7 +83,7 @@ const tocItems = [
|
||||
</div>
|
||||
|
||||
<!-- Terms Content -->
|
||||
<div class="prose prose-lg max-w-4xl dark:prose-invert dark:prose-headings:text-slate-300 prose-md prose-headings:font-heading prose-headings:leading-tighter prose-headings:tracking-tighter prose-headings:font-bold prose-a:text-blue-600 dark:prose-a:text-blue-400 prose-img:rounded-md prose-img:shadow-lg">
|
||||
<div class="prose prose-lg max-w-4xl dark:prose-invert dark:prose-headings:text-slate-300 prose-md prose-headings:font-heading prose-headings:leading-tighter prose-headings:tracking-tighter prose-headings:font-bold prose-a:text-blue-600 dark:prose-a:text-blue-400 prose-img:rounded-md prose-img:shadow-lg backdrop-blur-sm bg-white/15 dark:bg-slate-900/30 p-6 rounded-lg border border-gray-200 dark:border-slate-800">
|
||||
<p>
|
||||
Please read these terms and conditions carefully before using our website. By accessing or using our website, you agree to be bound by these terms and conditions.
|
||||
</p>
|
||||
|
Reference in New Issue
Block a user