add portfolio section; implement carousel for project showcase and improve layout
This commit is contained in:
30
.pugrc
30
.pugrc
@@ -82,6 +82,36 @@
|
|||||||
"href": "https://www.stollvongati.com/"
|
"href": "https://www.stollvongati.com/"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"portfolio": [
|
||||||
|
{
|
||||||
|
"type": "image",
|
||||||
|
"src": "./src/assets/screenshot-codecrispies.png",
|
||||||
|
"alt": "",
|
||||||
|
"href": "https://codecrispi.es",
|
||||||
|
"caption": "Code Crispi.es"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "image",
|
||||||
|
"src": "./src/assets/screenshot-codecrispies.png",
|
||||||
|
"alt": "",
|
||||||
|
"href": "https://codecrispi.es",
|
||||||
|
"caption": "Code Crispi.es"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "image",
|
||||||
|
"src": "./src/assets/screenshot-codecrispies.png",
|
||||||
|
"alt": "",
|
||||||
|
"href": "https://codecrispi.es",
|
||||||
|
"caption": "Code Crispi.es"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "image",
|
||||||
|
"src": "./src/assets/screenshot-codecrispies.png",
|
||||||
|
"alt": "",
|
||||||
|
"href": "https://codecrispi.es",
|
||||||
|
"caption": "Code Crispi.es"
|
||||||
|
}
|
||||||
|
],
|
||||||
"intro": {
|
"intro": {
|
||||||
"heading": "After $1"
|
"heading": "After $1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ html.scroll-smooth(lang=head.lang)
|
|||||||
include src/components/Landingpage
|
include src/components/Landingpage
|
||||||
include src/components/Brands
|
include src/components/Brands
|
||||||
include src/components/Academia
|
include src/components/Academia
|
||||||
|
include src/components/Portfolio
|
||||||
include src/components/Professional
|
include src/components/Professional
|
||||||
include src/components/Footer
|
include src/components/Footer
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
mixin Carousel(items, options)
|
mixin Carousel(items, options)
|
||||||
|
// Set options with fallbacks for defaults
|
||||||
- const id = options.id || "carousel";
|
- const id = options.id || "carousel";
|
||||||
- const color = options.color || "white";
|
- const color = options.color || "white";
|
||||||
- const category = options.category || "portfolio";
|
- const category = options.category || "portfolio";
|
||||||
|
- const slideClasses = options.slideClasses || "sm:w-1/2 lg:w-1/3 xl:w-1/4";
|
||||||
|
// Pass through options even if not used
|
||||||
|
- const autoScroll = options.autoScroll ?? 4_800;
|
||||||
|
|
||||||
.carousel-container.relative.w-full.overflow-hidden(id=id)
|
.carousel-container.relative.w-full.overflow-hidden(id=id)
|
||||||
//- Navigation buttons
|
//- Navigation buttons
|
||||||
@@ -22,21 +26,21 @@ mixin Carousel(items, options)
|
|||||||
path(stroke-linecap="round", stroke-linejoin="round", stroke-width="2", d="M9 5l7 7-7 7")
|
path(stroke-linecap="round", stroke-linejoin="round", stroke-width="2", d="M9 5l7 7-7 7")
|
||||||
|
|
||||||
//- Carousel track
|
//- Carousel track
|
||||||
.carousel-track.flex.overflow-x-auto.scroll-smooth.scrollbar-hide(style="scroll-snap-type: x mandatory", role="region", aria-label="Image carousel")
|
.carousel-track.flex.overflow-x-auto.rounded-lg.scroll-smooth.scrollbar-hide(style="scroll-snap-type: x mandatory", role="region", aria-label="Image carousel")
|
||||||
each item, index in items
|
each item, index in items
|
||||||
- const href = item?.href || "#";
|
- const href = item?.href || "#";
|
||||||
|
|
||||||
.carousel-slide.flex-none.w-full.relative(class="sm:w-1/2 lg:w-1/3 xl:w-1/4", style="scroll-snap-align: start")
|
.carousel-slide.flex-none.w-full.relative(class=slideClasses, style="scroll-snap-align: start")
|
||||||
if item.type === "image"
|
if item.type === "image"
|
||||||
.aspect-video.relative.overflow-hidden.rounded-lg.mx-2.mb-4
|
.flex.flex-col.aspect-video.relative.overflow-hidden.rounded-lg.mx-2.mb-4(class="sm:flex-row sm:gap-6")
|
||||||
img.w-full.h-full.object-cover.transition-transform.duration-300(class="hover:scale-105", src=item.src, alt=item.alt, loading=index < 3 ? "eager" : "lazy")
|
img.w-full.h-full.object-cover.transition-transform.rounded-lg.duration-300(class="hover:scale-105 sm:w-1/2", src=item.src, alt=item.alt, loading=index < 3 ? "eager" : "lazy")
|
||||||
if item.caption
|
if item.caption
|
||||||
.absolute.bottom-0.left-0.right-0.bg-gradient-to-t.p-4(class="from-black/70")
|
.absolute.bottom-0.left-0.right-0.bg-gradient-to-t.p-4(class="sm:static sm:bg-gradient-unset from-black/70 sm:text-nls-white dark:sm:text-nls-black")
|
||||||
p.text-white.text-sm.font-medium= item.caption
|
p.text-white.text-xl.font-large= item.caption
|
||||||
else if item.type === "brand"
|
else if item.type === "brand"
|
||||||
.aspect-square.flex.items-center.justify-center.mx-2.mb-4
|
.aspect-square.flex.items-center.justify-center.mx-2.mb-4
|
||||||
img.max-w-full.max-h-full.object-contain.p-4(src=item.logo, alt=item.name, loading=index < 6 ? "eager" : "lazy")
|
img.max-w-full.max-h-full.object-contain.p-4(src=item.logo, alt=item.name, loading=index < 6 ? "eager" : "lazy")
|
||||||
|
if autoScroll
|
||||||
script.
|
script.
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
@@ -46,5 +50,5 @@ mixin Carousel(items, options)
|
|||||||
} else {
|
} else {
|
||||||
carouselNext("#{id}");
|
carouselNext("#{id}");
|
||||||
}
|
}
|
||||||
}, 4700);
|
}, #{autoScroll});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -164,30 +164,30 @@ head
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive breakpoints - fewer items on smaller screens */
|
/*!* Responsive breakpoints - fewer items on smaller screens *!*/
|
||||||
@media (max-width: 640px) {
|
/*@media (max-width: 640px) {*/
|
||||||
.carousel-slide {
|
/* .carousel-slide {*/
|
||||||
width: 100%;
|
/* width: 100%;*/
|
||||||
}
|
/* }*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
@media (min-width: 641px) and (max-width: 1024px) {
|
/*@media (min-width: 641px) and (max-width: 1024px) {*/
|
||||||
.carousel-slide {
|
/* .carousel-slide {*/
|
||||||
width: 33.333333%;
|
/* width: 33.333333%;*/
|
||||||
}
|
/* }*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
@media (min-width: 1025px) and (max-width: 1280px) {
|
/*@media (min-width: 1025px) and (max-width: 1280px) {*/
|
||||||
.carousel-slide {
|
/* .carousel-slide {*/
|
||||||
width: 25%;
|
/* width: 25%;*/
|
||||||
}
|
/* }*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
@media (min-width: 1281px) {
|
/*@media (min-width: 1281px) {*/
|
||||||
.carousel-slide {
|
/* .carousel-slide {*/
|
||||||
width: 20%;
|
/* width: 20%;*/
|
||||||
}
|
/* }*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
/* Smooth button hover states */
|
/* Smooth button hover states */
|
||||||
.carousel-btn {
|
.carousel-btn {
|
||||||
|
|||||||
18
src/components/Portfolio.pug
Normal file
18
src/components/Portfolio.pug
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
include Carousel
|
||||||
|
include Container
|
||||||
|
|
||||||
|
section#portfolio
|
||||||
|
.p-8.bg-nls-black.text-nls-white(class="sm:py-2")
|
||||||
|
+Container
|
||||||
|
+Title("h2", true)
|
||||||
|
| Portfolio
|
||||||
|
p.text-center.pb-12
|
||||||
|
| Free and Open Source Software, Customer Projects and other useful Applications
|
||||||
|
.max-w-screen.mx-auto(class="sm:max-w-80vw")
|
||||||
|
+Carousel([...portfolio, ...portfolio, ...portfolio], {
|
||||||
|
id: "portfolio-carousel",
|
||||||
|
color: "black",
|
||||||
|
category: "portfolio",
|
||||||
|
slideClasses: "w-full",
|
||||||
|
autoScroll: false
|
||||||
|
})
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
mixin Title(tag)
|
mixin Title(tag, isCentered)
|
||||||
|
- const width = isCentered ? "w-full text-center" : "w-3/4";
|
||||||
|
|
||||||
case tag
|
case tag
|
||||||
when "h2"
|
when "h2"
|
||||||
h2.font-bold.font-serif.text-xl.mb-2(class="sm:text-2xl w-3/4")
|
h2.font-bold.font-serif.text-xl.mb-2(class=`sm:text-2xl ${width}`)
|
||||||
block
|
block
|
||||||
when "h3"
|
when "h3"
|
||||||
h3.font-bold.font-serif.text-xl.mb-4(class="sm:text-2xl w-3/4")
|
h3.font-bold.font-serif.text-xl.mb-4(class=`sm:text-2xl ${width}`)
|
||||||
block
|
block
|
||||||
default
|
default
|
||||||
h1.font-bold.font-serif.text-xl.mb-4(class="sm:text-2xl w-3/4")
|
h1.font-bold.font-serif.text-xl.mb-4(class=`sm:text-2xl ${width}`)
|
||||||
block
|
block
|
||||||
|
|||||||
Reference in New Issue
Block a user