This commit is contained in:
2025-09-11 13:55:36 +02:00
parent 141151bcec
commit f9c1e24abe
7 changed files with 360 additions and 17 deletions

193
css/animations.css Normal file
View File

@@ -0,0 +1,193 @@
/* Animation Styles for Homepage Components */
/* Base animation classes */
.animate-fade-in {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.8s ease-out, transform 0.8s ease-out;
}
.animate-fade-in.animate-visible {
opacity: 1;
transform: translateY(0);
}
/* Slide in from left */
.animate-slide-left {
opacity: 0;
transform: translateX(-50px);
transition: opacity 0.8s ease-out, transform 0.8s ease-out;
}
.animate-slide-left.animate-visible {
opacity: 1;
transform: translateX(0);
}
/* Slide in from right */
.animate-slide-right {
opacity: 0;
transform: translateX(50px);
transition: opacity 0.8s ease-out, transform 0.8s ease-out;
}
.animate-slide-right.animate-visible {
opacity: 1;
transform: translateX(0);
}
/* Scale up animation */
.animate-scale-up {
opacity: 0;
transform: scale(0.9);
transition: opacity 0.8s ease-out, transform 0.8s ease-out;
}
.animate-scale-up.animate-visible {
opacity: 1;
transform: scale(1);
}
/* Staggered animations for multiple elements */
.animate-stagger-1 {
transition-delay: 0.1s;
}
.animate-stagger-2 {
transition-delay: 0.2s;
}
.animate-stagger-3 {
transition-delay: 0.3s;
}
.animate-stagger-4 {
transition-delay: 0.4s;
}
.animate-stagger-5 {
transition-delay: 0.5s;
}
/* Hero section specific animations */
.hero-title {
opacity: 0;
transform: translateY(40px);
transition: opacity 1s ease-out, transform 1s ease-out;
}
.hero-title.animate-visible {
opacity: 1;
transform: translateY(0);
}
.hero-subtitle {
opacity: 0;
transform: translateY(30px);
transition: opacity 1s ease-out 0.3s, transform 1s ease-out 0.3s;
}
.hero-subtitle.animate-visible {
opacity: 1;
transform: translateY(0);
}
.hero-button {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.8s ease-out 0.6s, transform 0.8s ease-out 0.6s;
}
.hero-button.animate-visible {
opacity: 1;
transform: translateY(0);
}
/* Image animations */
.animate-image {
opacity: 0;
transform: scale(1.1);
transition: opacity 1s ease-out, transform 1s ease-out;
}
.animate-image.animate-visible {
opacity: 1;
transform: scale(1);
}
/* Text content animations */
.animate-text-content h1,
.animate-text-content h2,
.animate-text-content h3,
.animate-text-content h4 {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.8s ease-out, transform 0.8s ease-out;
}
.animate-text-content.animate-visible h1,
.animate-text-content.animate-visible h2,
.animate-text-content.animate-visible h3,
.animate-text-content.animate-visible h4 {
opacity: 1;
transform: translateY(0);
}
.animate-text-content p {
opacity: 0;
transform: translateY(15px);
transition: opacity 0.8s ease-out 0.2s, transform 0.8s ease-out 0.2s;
}
.animate-text-content.animate-visible p {
opacity: 1;
transform: translateY(0);
}
.animate-text-content button,
.animate-text-content a[href] {
opacity: 0;
transform: translateY(10px);
transition: opacity 0.8s ease-out 0.4s, transform 0.8s ease-out 0.4s;
}
.animate-text-content.animate-visible button,
.animate-text-content.animate-visible a[href] {
opacity: 1;
transform: translateY(0);
}
/* Reduced motion for accessibility */
@media (prefers-reduced-motion: reduce) {
.animate-fade-in,
.animate-slide-left,
.animate-slide-right,
.animate-scale-up,
.hero-title,
.hero-subtitle,
.hero-button,
.animate-image,
.animate-text-content h1,
.animate-text-content h2,
.animate-text-content h3,
.animate-text-content h4,
.animate-text-content p,
.animate-text-content button,
.animate-text-content a[href] {
transition: none;
opacity: 1;
transform: none;
}
}
/* Loading animation for initial page load */
.page-loading .animate-on-load {
opacity: 0;
transform: translateY(20px);
}
.page-loaded .animate-on-load {
opacity: 1;
transform: translateY(0);
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
}

View File

@@ -144,6 +144,8 @@ window.onload = function () {
'www.ourworld.tf', 'www.ourworld.tf',
'ourworld.tf', 'ourworld.tf',
'www2.ourworld.tf', 'www2.ourworld.tf',
'www2.freezone.ourworld.tf',
'freezone.ourworld.tf',
'localhost', 'localhost',
'127.0.0.1' '127.0.0.1'
] ]
@@ -169,3 +171,160 @@ window.onload = function () {
function openInNewTab(url) { function openInNewTab(url) {
window.open(url, '_blank').focus() window.open(url, '_blank').focus()
} }
// Animation System for Homepage Components
class AnimationController {
constructor() {
this.observer = null;
this.isPageLoaded = false;
this.init();
}
init() {
// Set up intersection observer for scroll animations
this.setupIntersectionObserver();
// Handle initial page load animations
this.handlePageLoad();
// Initialize animations when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => this.initializeAnimations());
} else {
this.initializeAnimations();
}
}
setupIntersectionObserver() {
const options = {
root: null,
rootMargin: '0px 0px -10% 0px', // Trigger when element is 10% visible
threshold: 0.1
};
this.observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.animateElement(entry.target);
}
});
}, options);
}
animateElement(element) {
// Add visible class to trigger CSS animations
element.classList.add('animate-visible');
// Animate child elements with stagger effect
const children = element.querySelectorAll('.animate-stagger-1, .animate-stagger-2, .animate-stagger-3, .animate-stagger-4, .animate-stagger-5');
children.forEach((child, index) => {
setTimeout(() => {
child.classList.add('animate-visible');
}, index * 100);
});
// Stop observing this element once animated
this.observer.unobserve(element);
}
handlePageLoad() {
// Add loading class initially
document.body.classList.add('page-loading');
window.addEventListener('load', () => {
this.isPageLoaded = true;
document.body.classList.remove('page-loading');
document.body.classList.add('page-loaded');
// Animate hero section immediately on load
this.animateHeroSection();
});
}
animateHeroSection() {
const heroElements = document.querySelectorAll('.hero-title, .hero-subtitle, .hero-button');
heroElements.forEach(element => {
element.classList.add('animate-visible');
});
}
initializeAnimations() {
// Find all elements that should be animated
const animatedElements = document.querySelectorAll(
'.animate-fade-in, .animate-slide-left, .animate-slide-right, .animate-scale-up, .animate-text-content, .animate-image'
);
// Start observing each element
animatedElements.forEach(element => {
this.observer.observe(element);
});
// Add animation classes to row containers
this.addAnimationClassesToRows();
}
addAnimationClassesToRows() {
// Get all row containers from the homepage
const rows = document.querySelectorAll('[id*="row"], .relative.justify-center.flex.overflow-hidden');
rows.forEach((row, index) => {
// Add different animation types based on position
const animationType = this.getAnimationTypeForRow(index);
row.classList.add(animationType);
// Add text content animation to text columns
const textColumns = row.querySelectorAll('div[class*="flex-1"]');
textColumns.forEach(column => {
if (this.hasTextContent(column)) {
column.classList.add('animate-text-content');
}
// Add image animation to image containers
const images = column.querySelectorAll('img');
images.forEach(img => {
img.parentElement.classList.add('animate-image');
});
});
});
}
getAnimationTypeForRow(index) {
const animations = ['animate-fade-in', 'animate-slide-left', 'animate-slide-right', 'animate-scale-up'];
return animations[index % animations.length];
}
hasTextContent(element) {
const textElements = element.querySelectorAll('h1, h2, h3, h4, p, button, a');
return textElements.length > 0;
}
// Method to trigger animations on scroll direction change
handleScrollDirection() {
let lastScrollTop = 0;
window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const scrollDirection = scrollTop > lastScrollTop ? 'down' : 'up';
// You can add specific animations based on scroll direction here
document.body.setAttribute('data-scroll-direction', scrollDirection);
lastScrollTop = scrollTop <= 0 ? 0 : scrollTop;
}, false);
}
}
// Initialize animation system
let animationController;
// Enhanced window.onload to include animations
const originalWindowOnload = window.onload;
window.onload = function() {
// Call original onload function
if (originalWindowOnload) {
originalWindowOnload();
}
// Initialize animation controller
animationController = new AnimationController();
}

View File

@@ -5,13 +5,8 @@
<footer> <footer>
<div class="max-w-screen-2xl mx-auto lg:py-5 py-2 sm:px-6 lg:px-8"> <div class="max-w-screen-2xl mx-auto lg:py-5 py-2 sm:px-6 lg:px-8">
<div class="flex flex-col xl:flex-row xl:gap-4 items-center"> <div class="flex flex-col xl:flex-row xl:gap-4 items-center">
<div class="space-y-8 lg:max-w-sm xl:max-w-sm lg:mr-8 mb-4 xl:col-span-1 text-center xl:text-left">
<a href="/">
<img class="lg:w-60 h-auto w-20 mx-auto" src="./images/zdfz.svg" alt="logo" />
</a>
</div>
<p data-v-14efe4a7="" class="text-base leading-6 text-gray-400 mb-4"> <p data-v-14efe4a7="" class="text-base leading-6 text-gray-400 mb-4">
© 2024 OurWorld Holdings, All rights reserved. © 2025 OurWorld Holdings, All rights reserved.
<a target="_blank" href="https://docs.threefold.io/docs/legal/terms_and_conditions" class="leading-6 text-gray-500 hover:text-gray-900">Terms &amp; Conditions | <a target="_blank" href="https://docs.threefold.io/docs/legal/terms_and_conditions" class="leading-6 text-gray-500 hover:text-gray-900">Terms &amp; Conditions |
</a><a target="_blank" href="https://docs.threefold.io/docs/legal/privacy_policy" class="leading-6 text-gray-500 hover:text-gray-900">Privacy Policy </a><a target="_blank" href="https://docs.threefold.io/docs/legal/privacy_policy" class="leading-6 text-gray-500 hover:text-gray-900">Privacy Policy
</a> </a>

View File

@@ -66,6 +66,7 @@
<!-- CSS/SCSS --> <!-- CSS/SCSS -->
<link rel="stylesheet" href="{{ get_url(path="css/index.css", trailing_slash=false, cachebust=true) | safe }}" /> <link rel="stylesheet" href="{{ get_url(path="css/index.css", trailing_slash=false, cachebust=true) | safe }}" />
<link rel="stylesheet" href="{{ get_url(path="css/animations.css", trailing_slash=false, cachebust=true) | safe }}" />
<style> <style>
.space-x-10>:not([hidden])~:not([hidden]){ .space-x-10>:not([hidden])~:not([hidden]){
margin-left: calc(1.5rem*calc(1 - var(--tw-space-x-reverse)))!important; margin-left: calc(1.5rem*calc(1 - var(--tw-space-x-reverse)))!important;

View File

@@ -13,11 +13,6 @@
<div class="{{'z-10 bg-white fixed w-screen ' ~ header_class}}"> <div class="{{'z-10 bg-white fixed w-screen ' ~ header_class}}">
<div class="relative z-50 shadow"> <div class="relative z-50 shadow">
<div class="mx-auto flex z-50 shadow justify-between items-center pl-6 pr-2 md:pr-0 lg:py-5 md:px-12 py-2 lg:px-20 lg:justify-start lg:space-x-20"> <div class="mx-auto flex z-50 shadow justify-between items-center pl-6 pr-2 md:pr-0 lg:py-5 md:px-12 py-2 lg:px-20 lg:justify-start lg:space-x-20">
<div>
<a href="/" class="flex">
<img class="w-56 h-auto sm:w-15" src="{{logo_path}}" alt="FreeFlow Logo" />
</a>
</div>
<div class="-mr-2 -my-2 lg:hidden"> <div class="-mr-2 -my-2 lg:hidden">
<button id="hamburger-btn" class="menu-mobile inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out my-2"> <button id="hamburger-btn" class="menu-mobile inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out my-2">
<!-- Heroicon name: menu --> <!-- Heroicon name: menu -->

View File

@@ -5,15 +5,15 @@
alt="Hero Image" alt="Hero Image"
width="210" width="210"
height="210" height="210"
class="mx-auto rounded-md"> class="mx-auto rounded-md animate-scale-up">
<p class="text-base font-semibold leading-7 text-blue-600">WELCOME TO</p> <p class="text-base font-semibold leading-7 text-blue-600 hero-subtitle">WELCOME TO</p>
<div class="max-w-4xl"> <div class="max-w-4xl">
<h1 class="mt-4 text-3xl lg:text-5xl font-bold leading-8 tracking-tight text-black mb-4">Zanzibar Digital Free Zone</h1> <h1 class="mt-4 text-3xl lg:text-5xl font-bold leading-8 tracking-tight text-black mb-4 hero-title">Zanzibar Digital Free Zone</h1>
</div> </div>
<p class="mt-6 text-lg sm:text-xl leading-7 sm:leading-8 text-gray-600 font-light mx-4 sm:mx-0">Zanzibar Digital Free Zone is a collaboration between the Government of Zanzibar and OurWorld Venture Creator. We are the world's first 100% digital free zone, accessible and affordable for all. Removing complexity from doing business.</p> <p class="mt-6 text-lg sm:text-xl leading-7 sm:leading-8 text-gray-600 font-light mx-4 sm:mx-0 hero-subtitle">Zanzibar Digital Free Zone is a collaboration between the Government of Zanzibar and OurWorld Venture Creator. We are the world's first 100% digital free zone, accessible and affordable for all. Removing complexity from doing business.</p>
<div class="mt-10 flex items-center justify-center"> <div class="mt-10 flex items-center justify-center">
<a href="#contact" class="rounded-xl bg-blue-700 px-4 py-2.5 font-semibold text-white shadow-sm hover:bg-blue-800 hover:text-blue-200 transition-colors duration-300"> <a href="#contact" class="rounded-xl bg-blue-700 px-4 py-2.5 font-semibold text-white shadow-sm hover:bg-blue-800 hover:text-blue-200 transition-colors duration-300 hero-button">
Get Started Get Started
</a> </a>
</div> </div>

View File

@@ -228,7 +228,7 @@ Parameters:
{% set no_margins = " -mx-8 md:-mx-12 lg:-mx-16 xl:-mx-20" %} {% set no_margins = " -mx-8 md:-mx-12 lg:-mx-16 xl:-mx-20" %}
<div id="{{anchor_link}}" class="{{'relative justify-center flex overflow-hidden ' ~ div_class }}" style="{{styles}}"> <div id="{{anchor_link}}" class="{{'relative justify-center flex overflow-hidden animate-fade-in ' ~ div_class }}" style="{{styles}}">
<div id="{{row_id}}" class="{{row_class}}" style="min-width: -webkit-fill-available; min-width: -moz-available"> <div id="{{row_id}}" class="{{row_class}}" style="min-width: -webkit-fill-available; min-width: -moz-available">
{% for column in columns%} {% for column in columns%}