add brand logos and carousel component; update professional section layout
This commit is contained in:
34
.pugrc
34
.pugrc
@@ -50,11 +50,43 @@
|
||||
"emojiSvg": "./src/assets/waving-hand.svg",
|
||||
"jobTitle": ["Expert in Web Technologies", "dedicated Software Engineering Lecturer"]
|
||||
},
|
||||
"brands": [
|
||||
{
|
||||
"name": "BOSCH",
|
||||
"type": "brand",
|
||||
"logo": "./src/assets/brands/logo.png",
|
||||
"href": "https://www.google.com"
|
||||
},
|
||||
{
|
||||
"name": "Universität Stuttgart",
|
||||
"type": "brand",
|
||||
"logo": "./src/assets/brands/uni-stuttgart.png",
|
||||
"href": "https://www.uni-stuttgart.de/"
|
||||
},
|
||||
{
|
||||
"name": "Experience One",
|
||||
"type": "brand",
|
||||
"logo": "./src/assets/brands/eo.png",
|
||||
"href": "https://www.experienceone.com/"
|
||||
},
|
||||
{
|
||||
"name": "DHBW Stuttgart",
|
||||
"type": "brand",
|
||||
"logo": "./src/assets/brands/dhbw.svg",
|
||||
"href": "https://www.dhbw-stuttgart.de/"
|
||||
},
|
||||
{
|
||||
"name": "Stoll von Gáti",
|
||||
"type": "brand",
|
||||
"logo": "./src/assets/brands/stollvongati.png",
|
||||
"href": "https://www.stollvongati.com/"
|
||||
}
|
||||
],
|
||||
"intro": {
|
||||
"heading": "After $1"
|
||||
},
|
||||
"professional": {
|
||||
"title": "Make it <i>run</i><br>Make it <i>right</i><br>Make it <i>fast¹</i> ",
|
||||
"title": "Make it <i>run</i><br>Make it <i>right</i><br>Make it <i>fast <sup><a href=\"https://wiki.c2.com/?MakeItWorkMakeItRightMakeItFast\" class=\"text-xs\" target=\"_blank\" title=\"Article about Make It Work Make It Right Make It Fast\" aria-label=\"Article about Make It Work Make It Right Make It Fast\">1</a></sup></i> ",
|
||||
"principlesIntro": "Throughout my career, I've been guided by the philosophies and innovations of free software and industry pioneers. These principles form the foundation of my approach to software engineering and didactics:",
|
||||
"principlesPeople": [
|
||||
{
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
doctype html
|
||||
html.scroll-smooth(lang=lang)
|
||||
include src/components/Head
|
||||
include src/components/Carousel
|
||||
|
||||
body.m-0.p-0
|
||||
main.flex.flex-col
|
||||
article(itemscope, itemtype="http://schema.org/Person")
|
||||
include src/components/Landingpage
|
||||
include src/components/Brands
|
||||
include src/components/Academia
|
||||
include src/components/Professional
|
||||
include src/components/Footer
|
||||
|
||||
6
src/components/Brands.pug
Normal file
6
src/components/Brands.pug
Normal file
@@ -0,0 +1,6 @@
|
||||
include Carousel
|
||||
include Container
|
||||
|
||||
section#brands
|
||||
.p-8.bg-nls-black.text-nls-white(class="sm:py-2")
|
||||
+Carousel([...brands, ...brands, ...brands], {id: "brands-carousel", color: "black", category: "brands"})
|
||||
@@ -1,24 +1,24 @@
|
||||
mixin Carousel(items, options)
|
||||
- const id = options.id || "carousel";
|
||||
- const color = options.color || "orange";
|
||||
- const color = options.color || "white";
|
||||
- const category = options.category || "portfolio";
|
||||
|
||||
.carousel-container.relative.w-full.overflow-hidden(id=id)
|
||||
//- Navigation buttons
|
||||
button.carousel-btn.carousel-prev.absolute.left-4.z-20.transform(
|
||||
class=`-translate-y-1/2 top-1/2 bg-white/80 hover:bg-white dark:bg-black/80 dark:hover:bg-black rounded-full p-3 shadow-lg transition-all focus:outline-none focus:ring-4 focus:ring-nls-${color}`,
|
||||
class=`-translate-y-1/2 top-1/2 bg-white/40 hover:bg-white/80 text-nls-black rounded-full p-3 shadow-lg transition-all focus:outline-none focus:ring-4 focus:ring-nls-${color}`,
|
||||
aria-label="Previous slide",
|
||||
onclick=`carouselPrev('${id}'); umami.track('carousel navigation', { direction: 'prev', category: '${category}', visitDuration: getVisitDuration() })`
|
||||
)
|
||||
svg.w-6.h-6.text-gray-800(class="dark:text-white", fill="none", stroke="currentColor", viewBox="0 0 24 24")
|
||||
svg.w-6.h-6.text-gray-800(fill="none", stroke="currentColor", viewBox="0 0 24 24")
|
||||
path(stroke-linecap="round", stroke-linejoin="round", stroke-width="2", d="M15 19l-7-7 7-7")
|
||||
|
||||
button.carousel-btn.carousel-next.absolute.right-4.z-20.transform(
|
||||
class=`top-1/2 -translate-y-1/2 bg-white/80 hover:bg-white dark:bg-black/80 dark:hover:bg-black rounded-full p-3 shadow-lg transition-all focus:outline-none focus:ring-4 focus:ring-nls-${color}`,
|
||||
class=`top-1/2 -translate-y-1/2 bg-white/40 hover:bg-white/80 text-nls-black rounded-full p-3 shadow-lg transition-all focus:outline-none focus:ring-4 focus:ring-nls-${color}`,
|
||||
aria-label="Next slide",
|
||||
onclick=`carouselNext('${id}'); umami.track('carousel navigation', { direction: 'next', category: '${category}', visitDuration: getVisitDuration() })`
|
||||
)
|
||||
svg.w-6.h-6.text-gray-800(class="dark:text-white", fill="none", stroke="currentColor", viewBox="0 0 24 24")
|
||||
svg.w-6.h-6.text-gray-800(fill="none", stroke="currentColor", viewBox="0 0 24 24")
|
||||
path(stroke-linecap="round", stroke-linejoin="round", stroke-width="2", d="M9 5l7 7-7 7")
|
||||
|
||||
//- Carousel track
|
||||
@@ -34,5 +34,17 @@ mixin Carousel(items, options)
|
||||
.absolute.bottom-0.left-0.right-0.bg-gradient-to-t.p-4(class="from-black/70")
|
||||
p.text-white.text-sm.font-medium= item.caption
|
||||
else if item.type === "brand"
|
||||
.aspect-square.flex.items-center.justify-center.bg-white.rounded-lg.mx-2.mb-4.shadow-sm(class="dark:bg-gray-800")
|
||||
.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")
|
||||
|
||||
script.
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
setInterval(() => {
|
||||
const track = document.querySelector(`##{id} .carousel-track`);
|
||||
if (track.scrollLeft + track.clientWidth >= track.scrollWidth) {
|
||||
track.scrollTo({left: 0, behavior: "smooth"});
|
||||
} else {
|
||||
carouselNext("#{id}");
|
||||
}
|
||||
}, 4700);
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
mixin Collapsable(name, data, open)
|
||||
- const isExpanded = open || false;
|
||||
- const color = data.color || "orange";
|
||||
- const color = data.color || "nls-text-black dark:nls-text-white";
|
||||
- const category = data.category || "default";
|
||||
- const linkEventName = "external link clicked";
|
||||
|
||||
details.mb-4(open=isExpanded, name=name)
|
||||
summary(
|
||||
class=`rounded-sm transition mb-2 cursor-pointer text-md font-semibold mb-2 cursor-pointer sm:text-lg text-nls-${color} dark:text-nls-${color} focus:outline-none focus:z-10 focus:ring-4 focus:ring-nls-${color} focus:bg-nls-${color} focus:text-black dark:focus:text-white focus:no-underline`,
|
||||
class=`rounded-sm transition mb-2 cursor-pointer text-md font-semibold mb-2 cursor-pointer sm:text-lg text-nls-${color} focus:outline-none focus:z-10 focus:ring-4 focus:ring-nls-${color} focus:bg-nls-${color} focus:text-black dark:focus:text-white focus:no-underline`,
|
||||
onclick=`umami.track('collapsable clicked', { category: '${category}', visitDuration: getVisitDuration() })`
|
||||
)= data.summary
|
||||
.text-slate-600(class="dark:text-stone-300")
|
||||
|
||||
@@ -150,6 +150,10 @@ head
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.carousel-container {
|
||||
padding: 0 3rem;
|
||||
}
|
||||
|
||||
.carousel-track {
|
||||
/* Hide scrollbars but keep functionality */
|
||||
scrollbar-width: none;
|
||||
@@ -169,19 +173,19 @@ head
|
||||
|
||||
@media (min-width: 641px) and (max-width: 1024px) {
|
||||
.carousel-slide {
|
||||
width: 50%;
|
||||
width: 33.333333%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1025px) and (max-width: 1280px) {
|
||||
.carousel-slide {
|
||||
width: 33.333333%;
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1281px) {
|
||||
.carousel-slide {
|
||||
width: 25%;
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ section#professional.bg-white.text-nls-black(class="dark:bg-nls-black dark:text-
|
||||
| #{professional.principlesIntro}
|
||||
.list-disc.list-inside.mb-8
|
||||
each person, i in professional.principlesPeople
|
||||
- const data = {summary: `${person.name} — ${person.concept}`, color: "text-nls-black dark:text-white", category: "professional"};
|
||||
- const data = {summary: `${person.name} — ${person.concept}`, category: "professional"};
|
||||
- const isOpen = i === 0;
|
||||
+Collapsable("professional", data, isOpen)
|
||||
each paragraph, j in person.paragraphs
|
||||
|
||||
Reference in New Issue
Block a user