Compare commits

..

3 commits

5 changed files with 210 additions and 2514 deletions

View file

@ -3,11 +3,16 @@ type: docker
name: deploy name: deploy
steps: steps:
- name: build - name: install
image: node:18-alpine image: node:18-alpine
commands: commands:
- npm ci || npm install - npm install -D tailwindcss@^3.4.0
- npm run build || npm build
- name: build-css
image: node:18-alpine
commands:
# Generate optimized CSS from src/input.css styles/main.css
- npx tailwindcss -i ./src/input.css -o ./styles/main.css --minify
- name: sync-files - name: sync-files
image: alpine:latest image: alpine:latest
@ -16,10 +21,9 @@ steps:
path: /host-target path: /host-target
commands: commands:
- cp -a . /host-target - cp -a . /host-target
- chmod -R 755 /host-target
- chmod -R 777 /host-target
volumes: volumes:
- name: website-data - name: website-data
host: host:
path: /root/khywebsite/data/html path: /root/khy/data/html

View file

@ -68,6 +68,62 @@
cursor: pointer; cursor: pointer;
} }
/* Attention animation for projects button */
.attention-animation {
animation: attention-pulse 3s ease-in-out infinite;
position: relative;
overflow: hidden;
}
.attention-animation::before {
content: "";
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.2),
transparent
);
animation: shimmer 4s ease-in-out infinite;
}
@keyframes attention-pulse {
0%,
100% {
transform: scale(1);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
50% {
transform: scale(1.02);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
}
@keyframes shimmer {
0% {
left: -100%;
}
50% {
left: 100%;
}
100% {
left: 100%;
}
}
.attention-animation:hover {
animation: none;
transform: scale(1.05);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),
0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.product-card:hover { .product-card:hover {
transform: translateY(-8px) scale(1.02); transform: translateY(-8px) scale(1.02);
box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.15); box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.15);
@ -334,11 +390,11 @@
<!-- Main Content --> <!-- Main Content -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-28 items-center"> <div class="grid grid-cols-1 lg:grid-cols-2 gap-28 items-center">
<!-- Left Side - Image --> <!-- Left Side - Image -->
<div class="relative"> <div id="hero-image" class="relative">
<img <img
src="assets/images/our_story.jpg" src="assets/images/our_story.jpg"
alt="Modern office interior" alt="Modern office interior"
class="w-full h-auto rounded-lg" class="w-full h-auto rounded-lg transition-opacity duration-300"
/> />
<!-- Navigation Arrow --> <!-- Navigation Arrow -->
<div class="absolute top-1/2 right-4 transform -translate-y-1/2"> <div class="absolute top-1/2 right-4 transform -translate-y-1/2">
@ -361,6 +417,32 @@
</svg> </svg>
</button> </button>
</div> </div>
<!-- Carousel Indicators -->
<div
class="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex space-x-2"
>
<div
id="carousel-indicator-0"
class="w-3 h-3 bg-white rounded-full opacity-100 transition-opacity duration-300 cursor-pointer"
></div>
<div
id="carousel-indicator-1"
class="w-3 h-3 bg-white rounded-full opacity-50 transition-opacity duration-300 cursor-pointer"
></div>
<div
id="carousel-indicator-2"
class="w-3 h-3 bg-white rounded-full opacity-50 transition-opacity duration-300 cursor-pointer"
></div>
<div
id="carousel-indicator-3"
class="w-3 h-3 bg-white rounded-full opacity-50 transition-opacity duration-300 cursor-pointer"
></div>
<div
id="carousel-indicator-4"
class="w-3 h-3 bg-white rounded-full opacity-50 transition-opacity duration-300 cursor-pointer"
></div>
</div>
</div> </div>
<!-- Right Side - Text Content --> <!-- Right Side - Text Content -->
@ -386,7 +468,7 @@
<button <button
id="projects-button" id="projects-button"
class="bg-black bg-opacity-70 text-white font-playfair font-normal text-xl md:text-2xl lg:text-3xl leading-tight tracking-wider px-8 py-4 rounded-lg hover:bg-opacity-80 transition-all text-center max-w-sm" class="bg-black bg-opacity-70 text-white font-playfair font-normal text-xl md:text-2xl lg:text-3xl leading-tight tracking-wider px-8 py-4 rounded-lg hover:bg-opacity-80 transition-all text-center max-w-sm attention-animation"
> >
Explore past projects Explore past projects
</button> </button>
@ -985,6 +1067,6 @@
</div> </div>
</footer> </footer>
<script src="scripts/main.js?v=1.1"></script> <script src="scripts/main.js?v=4.7"></script>
</body> </body>
</html> </html>

View file

@ -1,4 +1,11 @@
{ {
"name": "khy-website",
"version": "1.0.0",
"description": "KHY Furniture Website",
"scripts": {
"build": "npx tailwindcss -i ./src/input.css -o ./styles/main.css --minify",
"dev": "npx tailwindcss -i ./src/input.css -o ./styles/main.css --watch"
},
"devDependencies": { "devDependencies": {
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"tailwindcss-textshadow": "^2.1.3" "tailwindcss-textshadow": "^2.1.3"

View file

@ -661,23 +661,6 @@ function initSite() {
}); });
}); });
} }
// Story arrow button functionality
const storyArrowButton = document.getElementById("story-arrow-button");
if (storyArrowButton) {
storyArrowButton.addEventListener("click", function () {
// You can customize this action - for now, let's scroll to the products section
const productsSection = document.getElementById("products");
if (productsSection) {
const headerHeight = 112;
const targetPosition = productsSection.offsetTop - headerHeight;
window.scrollTo({
top: targetPosition,
behavior: "smooth",
});
}
});
}
// Product detail page functionality // Product detail page functionality
(async function initProductDetail() { (async function initProductDetail() {
@ -1737,6 +1720,111 @@ if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
initQuoteBadge(); initQuoteBadge();
initAddToQuote(); initAddToQuote();
initHeroCarousel();
}); });
// Version: 4.2 - Moved Show Less button to end of blog post content // Hero Carousel Functionality
function initHeroCarousel() {
const arrowButton = document.getElementById("story-arrow-button");
const heroImage = document.querySelector("#hero-image img");
if (!arrowButton || !heroImage) return;
// Carousel images array
const carouselImages = [
"assets/images/our_story.jpg",
"assets/images/first_homepage.jpg",
"assets/images/conference_room.jpg",
"assets/images/lounge_chair.jpg",
"assets/images/kitchen.JPG",
];
let currentImageIndex = 0;
let originalHeight = null;
// Function to capture original image height on first load
function captureOriginalHeight() {
if (!originalHeight) {
originalHeight = heroImage.offsetHeight;
console.log("Original image height captured:", originalHeight + "px");
}
}
// Function to update image with fade transition
function updateImage(newIndex) {
const newImage = new Image();
newImage.onload = function () {
// Fade out current image
heroImage.style.opacity = "0";
setTimeout(() => {
// Change image source
heroImage.src = carouselImages[newIndex];
heroImage.alt = `Carousel image ${newIndex + 1}`;
// Apply original height to maintain uniformity
if (originalHeight && newIndex !== 0) {
heroImage.style.height = originalHeight + "px";
heroImage.style.objectFit = "cover";
} else if (newIndex === 0) {
// Reset to original for the first image
heroImage.style.height = "auto";
heroImage.style.objectFit = "initial";
}
// Fade in new image
heroImage.style.opacity = "1";
// Update indicators
updateIndicators(newIndex);
}, 300);
};
newImage.src = carouselImages[newIndex];
}
// Function to update carousel indicators
function updateIndicators(activeIndex) {
for (let i = 0; i < 5; i++) {
const indicator = document.getElementById(`carousel-indicator-${i}`);
if (indicator) {
indicator.style.opacity = i === activeIndex ? "1" : "0.5";
}
}
}
// Arrow button click handler
arrowButton.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
currentImageIndex = (currentImageIndex + 1) % carouselImages.length;
updateImage(currentImageIndex);
});
// Indicator click handlers
for (let i = 0; i < 5; i++) {
const indicator = document.getElementById(`carousel-indicator-${i}`);
if (indicator) {
indicator.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
currentImageIndex = i;
updateImage(currentImageIndex);
});
}
}
// Capture original height after image loads
if (heroImage.complete) {
captureOriginalHeight();
} else {
heroImage.addEventListener("load", captureOriginalHeight);
}
// Auto-advance carousel every 5 seconds
setInterval(() => {
currentImageIndex = (currentImageIndex + 1) % carouselImages.length;
updateImage(currentImageIndex);
}, 5000);
}
// Version: 4.7 - Use original image height as standard for carousel uniformity

File diff suppressed because one or more lines are too long