diff --git a/public/js/carousel.js b/public/js/carousel.js new file mode 100644 index 0000000..d251cd7 --- /dev/null +++ b/public/js/carousel.js @@ -0,0 +1,71 @@ +function initCarousel(container, durationMS = 0) { + const numCarouselItems = container.querySelectorAll('.carousel-item').length; + const buttonContainer = container.querySelector('.carousel-buttons'); + + let current = 0; + function activateCarousel(i) { + const items = document.querySelectorAll('.carousel-item'); + for (const item of items) { + item.classList.remove('active'); + } + items[i].classList.add('active'); + + const smallItems = document.querySelectorAll('.carousel-item-small'); + if (smallItems.length > 0) { + for (const item of smallItems) { + item.classList.remove('active'); + } + smallItems[i].classList.add('active'); + } + + const buttons = document.querySelectorAll('.carousel-button'); + for (const button of buttons) { + button.classList.remove('active'); + } + buttons[i].classList.add('active'); + + current = i; + } + + function activateNext() { + activateCarousel((current + numCarouselItems + 1) % numCarouselItems); + } + + function activatePrev() { + activateCarousel((current + numCarouselItems - 1) % numCarouselItems); + } + + const carouselTimer = durationMS > 0 && setInterval(() => { + if (numCarouselItems === 0) { + return; + } + activateNext(); + }, durationMS); + + function carouselButtonClick(i) { + activateCarousel(i); + if (carouselTimer) { + clearInterval(carouselTimer); + } + } + + for (let i = 0; i < numCarouselItems; i++) { + const button = document.createElement('div'); + button.classList.add('carousel-button', 'br-pill', 'w1', 'h1', 'mh2'); + button.classList.toggle('active', i === 0); + + const clickIndex = i; + button.addEventListener('click', () => { + carouselButtonClick(clickIndex); + }); + + buttonContainer.appendChild(button); + } + + activateCarousel(0); + + return { + next: activateNext, + prev: activatePrev, + }; +} diff --git a/public/style.css b/public/style.css index 07374a5..628e8b0 100644 --- a/public/style.css +++ b/public/style.css @@ -8512,7 +8512,6 @@ input[type=submit] { .avatar-icon { width: 40px; height: 40px; - object-fit: cover; flex-shrink: 0; border-radius: 100%; overflow: hidden; @@ -9135,6 +9134,33 @@ span.icon-rss::before { padding: 0px; min-height: 0em; } +.project-carousel .carousel-item { + position: absolute; + top: 0; + left: 0; } + .project-carousel .carousel-item br { + line-height: 0.6em; } + +.project-carousel .carousel-item-small { + position: absolute; + top: 0; + left: 0; } + .project-carousel .carousel-item-small:not(.active) { + display: none; } + +.project-carousel .carousel-description { + max-height: 14rem; + overflow: hidden; } + +.project-carousel .carousel-fade { + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 30px; + background: linear-gradient( rgba(240, 240, 240, 0) , #f0f0f0 ); + background: linear-gradient( var(--dim-background-transparent) , var(--dim-background) ); } + .project .pair { display: flex; align-items: flex-start; } @@ -9365,37 +9391,14 @@ span.icon-rss::before { max-height: calc(100vh - 2rem); } } .carousel-container .carousel { - box-sizing: content-box; position: relative; } -.carousel-container .carousel-item { - position: absolute; - top: 0; - left: 0; } - .carousel-container .carousel-item:not(.active) { - display: none; } - .carousel-container .carousel-item br { - line-height: 0.6em; } +.carousel-container .carousel-item:not(.active) { + display: none; } -.carousel-container .carousel-description { - max-height: 14rem; - overflow: hidden; } - -.carousel-container .carousel-fade { - position: absolute; - left: 0; - right: 0; - bottom: 0; - height: 30px; - background: linear-gradient( rgba(240, 240, 240, 0) , #f0f0f0 ); - background: linear-gradient( var(--dim-background-transparent) , var(--dim-background) ); } - -.carousel-container .carousel-item-small { - position: absolute; - top: 0; - left: 0; } - .carousel-container .carousel-item-small:not(.active) { - display: none; } +.carousel-container .carousel-buttons { + display: flex; + justify-content: center; } .carousel-container .carousel-button { border: 1px solid; diff --git a/public/wheeljam2022/databaseexplorer.png b/public/wheeljam2022/databaseexplorer.png new file mode 100644 index 0000000..2ac8f90 Binary files /dev/null and b/public/wheeljam2022/databaseexplorer.png differ diff --git a/public/wheeljam2022/nearmanager.gif b/public/wheeljam2022/nearmanager.gif new file mode 100644 index 0000000..3eaa458 Binary files /dev/null and b/public/wheeljam2022/nearmanager.gif differ diff --git a/public/wheeljam2022/scroll.png b/public/wheeljam2022/scroll.png new file mode 100644 index 0000000..f7efa91 Binary files /dev/null and b/public/wheeljam2022/scroll.png differ diff --git a/public/wheeljam2022/visaviz.png b/public/wheeljam2022/visaviz.png new file mode 100644 index 0000000..c5866d9 Binary files /dev/null and b/public/wheeljam2022/visaviz.png differ diff --git a/src/rawdata/scss/_carousel.scss b/src/rawdata/scss/_carousel.scss index c4ee964..2527b94 100644 --- a/src/rawdata/scss/_carousel.scss +++ b/src/rawdata/scss/_carousel.scss @@ -1,51 +1,15 @@ .carousel-container { .carousel { - box-sizing: content-box; position: relative; - // height: 12rem; - - @media #{$breakpoint-large} { - // height: $height-5; - } } - .carousel-item { - position: absolute; - top: 0; - left: 0; - - &:not(.active) { - display: none; - } - - br { - line-height: 0.6em; - } + .carousel-item:not(.active) { + display: none; } - .carousel-description { - max-height: 14rem; - overflow: hidden; - } - - .carousel-fade { - position: absolute; - left: 0; - right: 0; - bottom: 0; - height: 30px; - - @include usevar(background, "linear-gradient(" dim-background-transparent "," dim-background ")") - } - - .carousel-item-small { - position: absolute; - top: 0; - left: 0; - - &:not(.active) { - display: none; - } + .carousel-buttons { + display: flex; + justify-content: center; } .carousel-button { diff --git a/src/rawdata/scss/_projects.scss b/src/rawdata/scss/_projects.scss index 046ad7a..5c817c6 100644 --- a/src/rawdata/scss/_projects.scss +++ b/src/rawdata/scss/_projects.scss @@ -1,3 +1,40 @@ +.project-carousel { + .carousel-item { + position: absolute; + top: 0; + left: 0; + + br { + line-height: 0.6em; + } + } + + .carousel-item-small { + position: absolute; + top: 0; + left: 0; + + &:not(.active) { + display: none; + } + } + + .carousel-description { + max-height: 14rem; + overflow: hidden; + } + + .carousel-fade { + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 30px; + + @include usevar(background, "linear-gradient(" dim-background-transparent "," dim-background ")") + } +} + .project { .pair { display: flex; diff --git a/src/templates/src/project_index.html b/src/templates/src/project_index.html index 571a04c..ea28d42 100644 --- a/src/templates/src/project_index.html +++ b/src/templates/src/project_index.html @@ -1,9 +1,13 @@ {{ template "base.html" . }} +{{ define "extrahead" }} + +{{ end }} + {{ define "content" }}
+ We had many incredible entries last year. Here are a few of our favorites: +
+ ++ Scroll is an experimental new typesetting format and editor. The document structure is inherently non-textual; in fact, even words within paragraphs are individual nodes that can easily be selected and moved as a whole. It's a great proof-of-concept of what "word processors" could be—and it even has a PDF export. +
+ Full Submission ➜ + Recap Interview ➜ ++ Near (or Near Manager) is an experimental file viewer that breaks away from a plain hierarchy. By allowing you to flatten folder hierarchies, create custom groups, and reorder your files, Near allows you to tame any complex file structure and view it in a way that works for you. +
+ Full Submission ➜ + Recap Interview ➜ ++ This project extended an existing personal project with a unique way of exploring Twitter threads. When the author found existing layout algorithms insufficient, he decided to roll his own. The project submission is an insightful look at why you sometimes need to do things yourself. +
++ This project was featured as a demo at Handmade Seattle 2021. +
+ Full Submission ➜ + Recap Interview ➜ + Handmade Seattle Demo ➜ ++ This project explores a new way of querying SQL databases, by throwing away SQL in favor of a visual node graph. It allows you to incrementally build queries, seeing the data at every point along the way, and to reuse smaller queries in a way SQL cannot. +
+ Full Submission ➜ + Recap Interview ➜ +@@ -308,31 +391,34 @@
- The Handmade ethos and Handmade community are software development superpowers. Don't be afraid to question your foundations and rebuild what needs rebuilding. The community is here to help you take on those challenges and do what others might consider impossible. -
-- Of course, this is a jam, so focus on what matters to your project. There are many excellent libraries in the community that can save you time and help you focus on your core ideas. Don't be afraid to use them. But don't be afraid to do your own thing if they're holding you back. -
-- This is a chance to build something truly new. Learn from previous work, but don't settle for “the same, but better”. It would be a huge shame to spend a week building nothing more than a clone of the same broken software we use today. -
-- This is where working with a team can really help. Bounce ideas off each other, do some research, and brainstorm before the jam starts. The software you end up building might be pretty different from your original ideas. -
-- In the end, this is a jam. Get weird and try something different. -
++ The Handmade ethos and Handmade community are software development superpowers. Don't be afraid to question your foundations and rebuild what needs rebuilding. The community is here to help you take on those challenges and do what others might consider impossible. +
++ Of course, this is a jam, so focus on what matters to your project. There are many excellent libraries in the community that can save you time and help you focus on your core ideas. Don't be afraid to use them. But don't be afraid to do your own thing if they're holding you back. +
++ This is a chance to build something truly new. Learn from previous work, but don't settle for “the same, but better”. It would be a huge shame to spend a week building nothing more than a clone of the same broken software we use today. +
++ This is where working with a team can really help. Bounce ideas off each other, do some research, and brainstorm before the jam starts. The software you end up building might be pretty different from your original ideas. +
++ In the end, this is a jam. Get weird and try something different. +
+