Implement image enlargement modal and enhance product detail functionality
- Replaced static quantity controls with a modal for image enlargement on product detail and catalog pages. - Added event listeners for image clicks to trigger modal display with enlarged images. - Updated product detail page to dynamically load images and descriptions, improving user experience. - Refactored JavaScript to streamline image handling and modal interactions. - Enhanced CSS for modal styling and transitions, ensuring a smooth user experience.
This commit is contained in:
parent
6caa3ee6c4
commit
18cf5c8ed3
7 changed files with 881 additions and 388 deletions
BIN
assets/images/prod-catalog.jpg
Normal file
BIN
assets/images/prod-catalog.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 417 KiB |
File diff suppressed because it is too large
Load diff
|
|
@ -164,7 +164,7 @@
|
|||
<!-- Background Image -->
|
||||
<div class="absolute inset-0 w-full h-full">
|
||||
<img
|
||||
src="assets/images/potty.jpg"
|
||||
src="assets/images/prod-catalog.jpg"
|
||||
alt="Product catalog background"
|
||||
class="w-full h-full object-cover object-center"
|
||||
style="filter: blur(3px)"
|
||||
|
|
|
|||
|
|
@ -249,31 +249,6 @@
|
|||
|
||||
<!-- Quantity and Action Buttons -->
|
||||
<div class="flex flex-col md:flex-row gap-4 md:gap-6 mb-8">
|
||||
<!-- Quantity Selector -->
|
||||
<div
|
||||
class="inline-flex items-center justify-between w-[180px] h-[64px] min-h-[64px] bg-white border border-quick-silver rounded-[15px] px-4 box-border shadow-sm hover:shadow-md transition-all duration-200"
|
||||
>
|
||||
<button
|
||||
id="qty-decr"
|
||||
aria-label="Decrease quantity"
|
||||
class="font-playfair font-light text-[20px] leading-none text-black w-8 h-8 flex items-center justify-center rounded-lg hover:bg-light-bg transition-colors cursor-pointer"
|
||||
>
|
||||
-
|
||||
</button>
|
||||
<span
|
||||
id="qty-value"
|
||||
class="font-playfair font-light text-[20px] leading-none text-black"
|
||||
>1</span
|
||||
>
|
||||
<button
|
||||
id="qty-incr"
|
||||
aria-label="Increase quantity"
|
||||
class="font-playfair font-light text-[20px] leading-none text-black w-8 h-8 flex items-center justify-center rounded-lg hover:bg-light-bg transition-colors cursor-pointer"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<a
|
||||
href="contact.html"
|
||||
|
|
@ -538,6 +513,45 @@
|
|||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Image Enlargement Modal -->
|
||||
<div
|
||||
id="image-modal"
|
||||
class="fixed inset-0 bg-black bg-opacity-90 z-50 hidden flex items-center justify-center p-4 transition-opacity duration-300"
|
||||
>
|
||||
<div
|
||||
class="relative max-w-7xl max-h-full w-full h-full flex items-center justify-center"
|
||||
>
|
||||
<!-- Close Button -->
|
||||
<button
|
||||
id="modal-close-btn"
|
||||
class="absolute top-4 right-4 z-10 bg-white bg-opacity-20 hover:bg-opacity-30 text-white rounded-full p-3 transition-all duration-200 backdrop-blur-sm"
|
||||
aria-label="Close modal"
|
||||
>
|
||||
<svg
|
||||
class="w-6 h-6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Enlarged Image -->
|
||||
<img
|
||||
id="modal-image"
|
||||
src=""
|
||||
alt=""
|
||||
class="w-[95vw] h-[95vh] object-contain rounded-lg shadow-2xl transform transition-transform duration-300 scale-95"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="scripts/main.js?v=3.5"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
212
scripts/main.js
212
scripts/main.js
|
|
@ -55,27 +55,6 @@ function initSite() {
|
|||
window.addEventListener("scroll", updateActiveLink);
|
||||
updateActiveLink();
|
||||
|
||||
// Quantity controls on product detail page
|
||||
(function initQuantityControls() {
|
||||
const decr = document.getElementById("qty-decr");
|
||||
const incr = document.getElementById("qty-incr");
|
||||
const valueEl = document.getElementById("qty-value");
|
||||
if (!decr || !incr || !valueEl) return; // Not on product detail page
|
||||
|
||||
function parseQty() {
|
||||
const n = parseInt(valueEl.textContent || "1", 10);
|
||||
return Number.isFinite(n) && n > 0 ? n : 1;
|
||||
}
|
||||
decr.addEventListener("click", () => {
|
||||
const next = Math.max(1, parseQty() - 1);
|
||||
valueEl.textContent = String(next);
|
||||
});
|
||||
incr.addEventListener("click", () => {
|
||||
const next = parseQty() + 1;
|
||||
valueEl.textContent = String(next);
|
||||
});
|
||||
})();
|
||||
|
||||
// Related products (dynamic)
|
||||
(async function initRelated() {
|
||||
const grid = document.getElementById("related-grid");
|
||||
|
|
@ -224,6 +203,137 @@ function initSite() {
|
|||
}
|
||||
}
|
||||
|
||||
// Image enlargement modal functionality (global)
|
||||
function addImageEnlargementListeners() {
|
||||
// Target both main product image AND gallery carousel images
|
||||
const mainProductImage = document.querySelector(
|
||||
".w-full.h-80.md\\:w-\\[500px\\].md\\:h-\\[500px\\] img[data-enlarge-src]"
|
||||
);
|
||||
const galleryImages = document.querySelectorAll(
|
||||
"#product-gallery-images img[data-enlarge-src]"
|
||||
);
|
||||
const modal = document.getElementById("image-modal");
|
||||
const modalImage = document.getElementById("modal-image");
|
||||
const modalCloseBtn = document.getElementById("modal-close-btn");
|
||||
|
||||
console.log("Adding image enlargement listeners...");
|
||||
console.log("Found main product image:", !!mainProductImage);
|
||||
console.log("Found gallery images:", galleryImages.length);
|
||||
console.log("Modal elements:", {
|
||||
modal: !!modal,
|
||||
modalImage: !!modalImage,
|
||||
modalCloseBtn: !!modalCloseBtn,
|
||||
});
|
||||
|
||||
if (!modal || !modalImage || !modalCloseBtn) {
|
||||
console.log("Modal elements not found, skipping image enlargement setup");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add click listener to main product image
|
||||
if (mainProductImage) {
|
||||
console.log(
|
||||
`Adding click listener to main product image:`,
|
||||
mainProductImage.src
|
||||
);
|
||||
mainProductImage.removeEventListener("click", handleImageClick);
|
||||
mainProductImage.addEventListener("click", handleImageClick);
|
||||
} else {
|
||||
console.log("Main product image not found");
|
||||
}
|
||||
|
||||
// Add click listeners to gallery carousel images
|
||||
galleryImages.forEach((img, index) => {
|
||||
console.log(
|
||||
`Adding click listener to gallery image ${index + 1}:`,
|
||||
img.src
|
||||
);
|
||||
img.removeEventListener("click", handleImageClick);
|
||||
img.addEventListener("click", handleImageClick);
|
||||
});
|
||||
|
||||
function handleImageClick(e) {
|
||||
console.log("Image clicked!", this.src);
|
||||
const imageSrc = this.getAttribute("data-enlarge-src");
|
||||
const imageAlt = this.getAttribute("alt");
|
||||
|
||||
console.log("Opening modal with image:", imageSrc);
|
||||
modalImage.src = imageSrc;
|
||||
modalImage.alt = imageAlt;
|
||||
|
||||
// Show modal with animation
|
||||
modal.classList.remove("hidden");
|
||||
document.body.style.overflow = "hidden"; // Prevent background scrolling
|
||||
|
||||
// Trigger animation after a brief delay
|
||||
setTimeout(() => {
|
||||
modalImage.classList.remove("scale-95");
|
||||
modalImage.classList.add("scale-100");
|
||||
}, 10);
|
||||
}
|
||||
|
||||
// Close modal functionality
|
||||
function closeModal() {
|
||||
// Animate out
|
||||
modalImage.classList.remove("scale-100");
|
||||
modalImage.classList.add("scale-95");
|
||||
|
||||
// Hide modal after animation
|
||||
setTimeout(() => {
|
||||
modal.classList.add("hidden");
|
||||
document.body.style.overflow = ""; // Restore scrolling
|
||||
}, 300);
|
||||
}
|
||||
|
||||
modalCloseBtn.addEventListener("click", closeModal);
|
||||
|
||||
// Close modal when clicking outside the image
|
||||
modal.addEventListener("click", function (e) {
|
||||
if (e.target === modal) {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
|
||||
// Close modal with Escape key
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Escape" && !modal.classList.contains("hidden")) {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Thumbnail click functionality (global)
|
||||
function addThumbnailClickListeners() {
|
||||
const thumbnails = document.querySelectorAll("[data-thumbnail-src]");
|
||||
const mainImageContainer = document.querySelector(
|
||||
".w-full.h-80.md\\:w-\\[500px\\].md\\:h-\\[500px\\]"
|
||||
);
|
||||
|
||||
console.log("Adding thumbnail click listeners...");
|
||||
console.log("Found thumbnails:", thumbnails.length);
|
||||
console.log("Main image container:", !!mainImageContainer);
|
||||
|
||||
if (!mainImageContainer) {
|
||||
console.log("Main image container not found");
|
||||
return;
|
||||
}
|
||||
|
||||
thumbnails.forEach((thumbnail, index) => {
|
||||
thumbnail.addEventListener("click", function () {
|
||||
const imageSrc = this.getAttribute("data-thumbnail-src");
|
||||
console.log(`Thumbnail ${index + 1} clicked, switching to:`, imageSrc);
|
||||
|
||||
// Update the main product image
|
||||
const mainImg = mainImageContainer.querySelector("img");
|
||||
if (mainImg) {
|
||||
mainImg.src = imageSrc;
|
||||
mainImg.setAttribute("data-enlarge-src", imageSrc);
|
||||
console.log("Main image updated to:", imageSrc);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Product detail page functionality
|
||||
async function initProductDetail() {
|
||||
console.log("Product detail script running...");
|
||||
|
|
@ -297,10 +407,16 @@ async function initProductDetail() {
|
|||
<img
|
||||
src="${product.image}"
|
||||
alt="${product.alt || product.name}"
|
||||
class="w-full h-full object-cover"
|
||||
class="w-full h-full object-cover cursor-pointer hover:opacity-90 transition-opacity"
|
||||
data-enlarge-src="${product.image}"
|
||||
/>
|
||||
`;
|
||||
console.log("Updated main image to:", product.image);
|
||||
|
||||
// Add image enlargement functionality to the main product image
|
||||
setTimeout(() => {
|
||||
addImageEnlargementListeners();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Update thumbnail images
|
||||
|
|
@ -313,7 +429,7 @@ async function initProductDetail() {
|
|||
.slice(0, 4)
|
||||
.map(
|
||||
(img, index) => `
|
||||
<div class="w-32 h-32 bg-floral-white rounded-lg overflow-hidden cursor-pointer">
|
||||
<div class="w-32 h-32 bg-floral-white rounded-lg overflow-hidden cursor-pointer hover:opacity-80 transition-opacity" data-thumbnail-src="${img}">
|
||||
<img
|
||||
src="${img}"
|
||||
alt="${product.name} ${index + 1}"
|
||||
|
|
@ -324,6 +440,9 @@ async function initProductDetail() {
|
|||
)
|
||||
.join("");
|
||||
console.log("Updated thumbnails with", product.images.length, "images");
|
||||
|
||||
// Add click event listeners to thumbnails
|
||||
addThumbnailClickListeners();
|
||||
}
|
||||
|
||||
// Update size options
|
||||
|
|
@ -399,17 +518,6 @@ async function initProductDetail() {
|
|||
}
|
||||
}
|
||||
|
||||
// Find and update Tags
|
||||
const tagsLabel = Array.from(allSpans).find(
|
||||
(span) => span.textContent === "Tags"
|
||||
);
|
||||
if (tagsLabel && product.tags) {
|
||||
const tagsValue =
|
||||
tagsLabel.parentElement.querySelector("span:last-child");
|
||||
if (tagsValue) {
|
||||
tagsValue.textContent = product.tags.join(", ");
|
||||
}
|
||||
}
|
||||
|
||||
// Find and update Dimensions
|
||||
const dimensionsLabel = Array.from(allSpans).find(
|
||||
|
|
@ -455,15 +563,18 @@ async function initProductDetail() {
|
|||
const galleryBackBtn = document.getElementById("gallery-back-btn");
|
||||
const galleryNextBtn = document.getElementById("gallery-next-btn");
|
||||
console.log("Gallery container:", galleryContainer);
|
||||
console.log("Product galleryPairs:", product.galleryPairs);
|
||||
|
||||
if (galleryContainer && product.galleryPairs) {
|
||||
// galleryPairs is now a simple array of image paths
|
||||
const allGalleryImages = product.galleryPairs;
|
||||
console.log("All gallery images:", allGalleryImages);
|
||||
|
||||
// Store gallery images for carousel
|
||||
window.currentGalleryImages = allGalleryImages;
|
||||
window.currentGalleryIndex = 0;
|
||||
|
||||
console.log("About to call renderGalleryCarousel...");
|
||||
// Render initial gallery view
|
||||
renderGalleryCarousel();
|
||||
|
||||
|
|
@ -484,18 +595,35 @@ async function initProductDetail() {
|
|||
}
|
||||
|
||||
function renderGalleryCarousel() {
|
||||
if (!window.currentGalleryImages || !galleryContainer) return;
|
||||
console.log("renderGalleryCarousel called");
|
||||
console.log("window.currentGalleryImages:", window.currentGalleryImages);
|
||||
console.log("galleryContainer:", galleryContainer);
|
||||
|
||||
if (!window.currentGalleryImages || !galleryContainer) {
|
||||
console.log(
|
||||
"Early return: missing currentGalleryImages or galleryContainer"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
"Rendering gallery carousel with",
|
||||
window.currentGalleryImages.length,
|
||||
"images"
|
||||
);
|
||||
|
||||
// Handle single image vs multiple images
|
||||
if (window.currentGalleryImages.length === 1) {
|
||||
// Single image - show only one image, hide arrows
|
||||
const image1 = window.currentGalleryImages[0];
|
||||
console.log("Rendering single image:", image1);
|
||||
galleryContainer.innerHTML = `
|
||||
<div class="rounded-[10px] bg-floral-white p-6 transition-all duration-1500 ease-out" id="gallery-image-1">
|
||||
<div class="rounded-[10px] bg-floral-white p-6 transition-all duration-1500 ease-out cursor-pointer hover:opacity-90" id="gallery-image-1">
|
||||
<img
|
||||
src="${image1}"
|
||||
alt="${product.name} gallery"
|
||||
class="w-full h-80 object-contain mx-auto"
|
||||
data-enlarge-src="${image1}"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
|
@ -510,19 +638,23 @@ async function initProductDetail() {
|
|||
(window.currentGalleryIndex + 1) % window.currentGalleryImages.length;
|
||||
const image2 = window.currentGalleryImages[image2Index];
|
||||
|
||||
console.log("Rendering multiple images:", image1, image2);
|
||||
|
||||
galleryContainer.innerHTML = `
|
||||
<div class="rounded-[10px] bg-floral-white p-6 transition-all duration-1500 ease-out" id="gallery-image-1">
|
||||
<div class="rounded-[10px] bg-floral-white p-6 transition-all duration-1500 ease-out cursor-pointer hover:opacity-90" id="gallery-image-1">
|
||||
<img
|
||||
src="${image1}"
|
||||
alt="${product.name} gallery"
|
||||
class="w-full h-80 object-contain mx-auto"
|
||||
data-enlarge-src="${image1}"
|
||||
/>
|
||||
</div>
|
||||
<div class="rounded-[10px] bg-floral-white p-6 transition-all duration-1500 ease-out" id="gallery-image-2">
|
||||
<div class="rounded-[10px] bg-floral-white p-6 transition-all duration-1500 ease-out cursor-pointer hover:opacity-90" id="gallery-image-2">
|
||||
<img
|
||||
src="${image2}"
|
||||
alt="${product.name} gallery"
|
||||
class="w-full h-80 object-contain mx-auto"
|
||||
data-enlarge-src="${image2}"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
|
@ -536,6 +668,10 @@ async function initProductDetail() {
|
|||
galleryNextBtn.style.opacity = "1";
|
||||
galleryNextBtn.style.pointerEvents = "auto";
|
||||
}
|
||||
|
||||
// Add click event listeners to gallery images for enlargement
|
||||
console.log("About to call addImageEnlargementListeners for gallery...");
|
||||
addImageEnlargementListeners();
|
||||
}
|
||||
|
||||
// Add click handlers for looped gallery carousel navigation
|
||||
|
|
|
|||
|
|
@ -123,6 +123,11 @@ class ProductManager {
|
|||
.join("");
|
||||
this.updateResultsCount();
|
||||
this.updatePagination();
|
||||
|
||||
// Re-add image enlargement listeners after products are rendered
|
||||
setTimeout(() => {
|
||||
addImageEnlargementListeners();
|
||||
}, 50);
|
||||
}
|
||||
|
||||
// Create individual product card HTML
|
||||
|
|
@ -140,7 +145,8 @@ class ProductManager {
|
|||
<img
|
||||
src="${product.image}"
|
||||
alt="${product.alt}"
|
||||
class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
|
||||
class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300 cursor-pointer"
|
||||
data-enlarge-src="${product.image}"
|
||||
/>
|
||||
<!-- Hover Overlay -->
|
||||
<div class="absolute inset-0 bg-dark-charcoal bg-opacity-70 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
|
||||
|
|
@ -454,7 +460,76 @@ class ProductManager {
|
|||
// Initialize product manager
|
||||
const productManager = new ProductManager();
|
||||
|
||||
// Image enlargement modal functionality
|
||||
function addImageEnlargementListeners() {
|
||||
const productImages = document.querySelectorAll(
|
||||
"#product-grid img[data-enlarge-src]"
|
||||
);
|
||||
const modal = document.getElementById("image-modal");
|
||||
const modalImage = document.getElementById("modal-image");
|
||||
const modalCloseBtn = document.getElementById("modal-close-btn");
|
||||
|
||||
if (!modal || !modalImage || !modalCloseBtn) return;
|
||||
|
||||
productImages.forEach((img) => {
|
||||
img.addEventListener("click", function (e) {
|
||||
e.preventDefault(); // Prevent any default behavior
|
||||
e.stopPropagation(); // Stop event bubbling to parent elements
|
||||
|
||||
const imageSrc = this.getAttribute("data-enlarge-src");
|
||||
const imageAlt = this.getAttribute("alt");
|
||||
|
||||
modalImage.src = imageSrc;
|
||||
modalImage.alt = imageAlt;
|
||||
|
||||
// Show modal with animation
|
||||
modal.classList.remove("hidden");
|
||||
document.body.style.overflow = "hidden"; // Prevent background scrolling
|
||||
|
||||
// Trigger animation after a brief delay
|
||||
setTimeout(() => {
|
||||
modalImage.classList.remove("scale-95");
|
||||
modalImage.classList.add("scale-100");
|
||||
}, 10);
|
||||
});
|
||||
});
|
||||
|
||||
// Close modal functionality
|
||||
function closeModal() {
|
||||
// Animate out
|
||||
modalImage.classList.remove("scale-100");
|
||||
modalImage.classList.add("scale-95");
|
||||
|
||||
// Hide modal after animation
|
||||
setTimeout(() => {
|
||||
modal.classList.add("hidden");
|
||||
document.body.style.overflow = ""; // Restore scrolling
|
||||
}, 300);
|
||||
}
|
||||
|
||||
modalCloseBtn.addEventListener("click", closeModal);
|
||||
|
||||
// Close modal when clicking outside the image
|
||||
modal.addEventListener("click", function (e) {
|
||||
if (e.target === modal) {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
|
||||
// Close modal with Escape key
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Escape" && !modal.classList.contains("hidden")) {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Load products when DOM is ready
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
productManager.loadProducts();
|
||||
|
||||
// Add image enlargement listeners after products are loaded
|
||||
setTimeout(() => {
|
||||
addImageEnlargementListeners();
|
||||
}, 100);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -673,6 +673,10 @@ video {
|
|||
top: 20rem;
|
||||
}
|
||||
|
||||
.top-4 {
|
||||
top: 1rem;
|
||||
}
|
||||
|
||||
.z-10 {
|
||||
z-index: 10;
|
||||
}
|
||||
|
|
@ -979,6 +983,14 @@ video {
|
|||
height: 32vh;
|
||||
}
|
||||
|
||||
.h-\[95vh\] {
|
||||
height: 95vh;
|
||||
}
|
||||
|
||||
.max-h-full {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.min-h-\[64px\] {
|
||||
min-height: 64px;
|
||||
}
|
||||
|
|
@ -1063,6 +1075,10 @@ video {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.w-\[95vw\] {
|
||||
width: 95vw;
|
||||
}
|
||||
|
||||
.max-w-2xl {
|
||||
max-width: 42rem;
|
||||
}
|
||||
|
|
@ -1099,6 +1115,10 @@ video {
|
|||
max-width: 56rem;
|
||||
}
|
||||
|
||||
.max-w-full {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1 1 0%;
|
||||
}
|
||||
|
|
@ -1122,6 +1142,18 @@ video {
|
|||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.scale-95 {
|
||||
--tw-scale-x: .95;
|
||||
--tw-scale-y: .95;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.scale-100 {
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.transform {
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
|
@ -1500,6 +1532,14 @@ video {
|
|||
--tw-bg-opacity: 0.7;
|
||||
}
|
||||
|
||||
.bg-opacity-20 {
|
||||
--tw-bg-opacity: 0.2;
|
||||
}
|
||||
|
||||
.bg-opacity-90 {
|
||||
--tw-bg-opacity: 0.9;
|
||||
}
|
||||
|
||||
.object-contain {
|
||||
-o-object-fit: contain;
|
||||
object-fit: contain;
|
||||
|
|
@ -1922,6 +1962,12 @@ video {
|
|||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-2xl {
|
||||
--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
|
||||
--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.blur {
|
||||
--tw-blur: blur(8px);
|
||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||
|
|
@ -1936,6 +1982,11 @@ video {
|
|||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||
}
|
||||
|
||||
.backdrop-blur-sm {
|
||||
--tw-backdrop-blur: blur(4px);
|
||||
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
|
||||
}
|
||||
|
||||
.transition {
|
||||
transition-property: color, background-color, border-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-text-decoration-color;
|
||||
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
||||
|
|
@ -2030,6 +2081,10 @@ video {
|
|||
--tw-bg-opacity: 0.9;
|
||||
}
|
||||
|
||||
.hover\:bg-opacity-30:hover {
|
||||
--tw-bg-opacity: 0.3;
|
||||
}
|
||||
|
||||
.hover\:text-black:hover {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(0 0 0 / var(--tw-text-opacity, 1));
|
||||
|
|
@ -2059,6 +2114,10 @@ video {
|
|||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.hover\:opacity-90:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.hover\:shadow-lg:hover {
|
||||
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue