📔FujoGuide Spotlight #3: Zine Demo📔
With the cast spotlights out of the way (find the links at the end of the thread), today we want to focus on the actual product we'll be putting in everyone's hands: our Version Control zine.
If you're just joining us, you can get this zine in your eager fujin hands (and help us reach our stretch goals) by backing us on Kickstarter.
If you want to follow along with the demo, you can find it here as a PDF.
Before we go into the nitty-gritty details, we chose Version Control as our first topic because, while working with both beginner and experienced coders, they reported it as the most life-changing (but intimidating) skill they gained. It also helps them join open-source projects!
Keep reading for lots more!
Remember: all you see here is a work in progress, and things may and will change in the zine. Our campaign is a love-letter to Japanese productions like otome games and "cast full of hot boys" anime. Similarly, our zine calls back to Japanese fan productions, a.k.a. doujinshi.
As you likely noticed, we pride ourselves on committing to the bit. This zine is no different. For example, Boba-tan, pitched as the revolutionary brain behind our educational devices, is both its fictional author and protagonist. After all, who doesn't love a good self-insert?
After this, the zine follows a simple pattern: a comic explains the current plight of our protagonist, a new character/technology is introduced, and then we dive deeper into concrete examples of how the technology is used in a practical workflow. We keep it light but useful!
Let's show, not tell! Behold, our first comic by @tempural (🎨) and @essential-randomness (🖋)! Boba-tan, deadline quickly approaching, manages to wreck her website! #relatable
Fear not! Terminal has a simple solution, which we fully endorse: Boba-tan, meet Git! (bonus HTML cameo 👀)
Next is Git’s character introduction featuring @brokemycrown's amazing art. This page serves a double purpose: it adds depth to the character (and some laughs), but most importantly it's a memorable way to help the core concept immediately stick in the reader's brain.
And now we finally reach the core of our offering, that is our actual educational material. The current version (remember, a work in progress) was planned by @essential-randomness, written by @enigmalea, and reviewed by our technical writing consultant wiredferret.
After the campaign, we plan to work closely with backers to deliver material that truly works. But while the content is in flux, you can see the landmarks of our experience: simple explanations that don't shy away from the technical details, with hot men sprinkled all around!
Fun fact: we also used Git & GitHub to collaborate on the zine itself! Thanks to Vivliostyle's powerful tools for typesetting with code, @essential-randomness and @enigmalea were able to use the techniques we're teaching to iterate together without stepping on each other's toes!
And that is all for today! We hope you're now even more excited for this guide to soon be reality. Although we hit our initial goal (🎉🎉🎉) we still have many stretch goals to go. Help us smash through them in this final week by backing us at our Kickstarter page.
If you missed the previous spotlights and wish to learn more about our characters in the Localhost HQ and Browserland spotlights.
44 notes
·
View notes
How to Make a “Scroll to Select” Form Control
New Post has been published on https://thedigitalinsider.com/how-to-make-a-scroll-to-select-form-control/
How to Make a “Scroll to Select” Form Control
The <select> element is a fairly straightforward concept: focus on it to reveal a set of <option>s that can be selected as the input’s value. That’s a great pattern and I’m not suggesting we change it. That said, I do enjoy poking at things and found an interesting way to turn a <select> into a dial of sorts — where options are selected by scrolling them into position, not totally unlike a combination lock or iOS date pickers. Anyone who’s expanded a <select> for selecting a country knows how painfully long lists can be and this could be one way to prevent that.
Here’s what I’m talking about:
It’s fairly common knowledge that styling <select> in CSS is not the easiest thing in the world. But here’s the trick: we’re not working with <select> at all. No, we’re not going to do anything like building our own <select> by jamming a bunch of JavaScript into a <div>. We’re still working with semantic form controls, only it’s radio buttons.
<section class=scroll-container> <label for="madrid" class="scroll-item"> Madrid <abbr>MAD</abbr> <input id="madrid" type="radio" name="items"> </label> <label for="malta" class="scroll-item"> Malta <abbr>MLA</abbr> <input id="malta" type="radio" name="items"> </label> <!-- etc. --> </section>
What we need is to style the list of selectable controls where we are capable of managing their sizes and spacing in CSS. I’ve gone with a group of labels with nested radio boxes as far as the markup goes. The exact styling is totally up to you, of course, but you can use these base styles I wrote up if you want a starting point.
.scroll-container /* SIZING & LAYOUT */ --itemHeight: 60px; --itemGap: 10px; --containerHeight: calc((var(--itemHeight) * 7) + (var(--itemGap) * 6)); width: 400px; height: var(--containerHeight); align-items: center; row-gap: var(--itemGap); border-radius: 4px; /* PAINT */ --topBit: calc((var(--containerHeight) - var(--itemHeight))/2); --footBit: calc((var(--containerHeight) + var(--itemHeight))/2); background: linear-gradient( rgb(254 251 240), rgb(254 251 240) var(--topBit), rgb(229 50 34 / .5) var(--topBit), rgb(229 50 34 / .5) var(--footBit), rgb(254 251 240) var(--footBit)); box-shadow: 0 0 10px #eee;
A couple of details on this:
--itemHeight is the height of each item in the list.
--itemGap is meant to be the space between two items.
The --containerHeight variable is the .scroll-container’s height. It’s the sum of the item sizes and the gaps between them, ensuring that we display, at maximum, seven items at once. (An odd number of items gives us a nice balance where the selected item is directly in the vertical center of the list).
The background is a striped gradient that highlights the middle area, i.e., the location of the currently selected item.
The --topBit and –-footBit variables are color stops that visually paint in the middle area (which is orange in the demo) to represent the currently selected item.
I’ll arrange the controls in a vertical column with flexbox declared on the .scroll-container:
.scroll-container display: flex; flex-direction: column; /* rest of styles */
With layout work done, we can focus on the scrolling part of this. If you haven’t worked with CSS Scroll Snapping before, it’s a convenient way to direct a container’s scrolling behavior. For example, we can tell the .scroll-container that we want to enable scrolling in the vertical direction. That way, it’s possible to scroll to the rest of the items that are not in view.
.scroll-container overflow-y: scroll; /* rest of styles */
Next, we reach for the scroll-snap-style property that can be used to tell the .scroll-container that we want scrolling to stop on an item — not near an item, but directly on it.
.scroll-container overflow-y: scroll; scroll-snap-type: y mandatory; /* rest of styles */
Now items “snap” onto an item instead of allowing a scroll to end wherever it wants. One more little detail I like to include is overscroll-behavior, specifically along the y-axis as far as this demo goes:
.scroll-container overflow-y: scroll; scroll-snap-type: y mandatory; overscroll-behavior-y: none; /* rest of styles */
overscroll-behavior-y: none isn’t required to make this work, but when someone scrolls through the .scroll-container (along the y-axis), scrolling stops once the boundary is reached, and any further continued scrolling action will not trigger scrolling in any nearby scroll containers. Just a form of defensive CSS.
Time to move to the items inside the scroll container. But before we go there, here are some base styles for the items themselves that you can use as a starting point:
.scroll-item /* SIZING & LAYOUT */ width: 90%; box-sizing: border-box; padding-inline: 20px; border-radius: inherit; /* PAINT & FONT */ background: linear-gradient(to right, rgb(242 194 66), rgb(235 122 51)); box-shadow: 0 0 4px rgb(235 122 51); font: 16pt/var(--itemHeight) system-ui; color: #fff; input appearance: none; abbr float: right; /* The airport code */
As I mentioned earlier, the --itemHeight variable is setting as the size of each item and we’re declaring it on the flex property — flex: 0 0 var(--itemHeight). Margin is added before and after the first and last items, respectively, so that every item can reach the middle of the container through scrolling.
The scroll-snap-align property is there to give the .scroll-container a snap point for the items. A center alignment, for instance, snaps an item’s center (vertical center, in this case) with the .scroll-container‘s center (vertical center as well). Since the items are meant to be selected through scrolling alone pointer-events: none is added to prevent selection from clicks.
One last little styling detail is to set a new background on an item when it is in a :checked state:
.scroll-item /* Same styles as before */ /* If input="radio" is :checked */ &:has(:checked) background: rgb(229 50 34);
But wait! You’re probably wondering how in the world an item can be :checked when we’re removing pointer-events. Good question! We’re all finished with styling, so let’s move on to figuring some way to “select” an item purely through scrolling. In other words, whatever item scrolls into view and “snaps” into the container’s vertical center needs to behave like a typical form control selection. Yes, we’ll need JavaScript for that.
let observer = new IntersectionObserver(entries => entries.forEach(entry => with(entry) if(isIntersecting) target.children[1].checked = true; ); , root: document.querySelector(`.scroll-container`), rootMargin: `-51% 0px -49% 0px` ); document.querySelectorAll(`.scroll-item`).forEach(item => observer.observe(item));
The IntersectionObserver object is used to monitor (or “observe”) if and when an element (called a target) crosses through (or “intersects”) another element. That other element could be the viewport itself, but in this case, we’re observing the .scroll-container for when a .scroll-item intersects it. We’ve established the observed boundary with rootMargin:"-51% 0px -49% 0px".
A callback function is executed when that happens, and we can use that to apply changes to the target element, which is the currently selected .scroll-item. In our case, we want to select a .scroll-item that is at the halfway mark in the .scroll-container: target.children[1].checked = true.
That completes the code. Now, as we scroll through the items, whichever one snaps into the center position is the selected item. Here’s a look at the final demo again:
Let’s say that, instead of selecting an item that snaps into the .scroll-container‘s vertical center, the selection point we need to watch is the top of the container. No worries! All we do is update the scroll-snap-align property value from center to start in the CSS and remove the :first-of-type‘s top margin. From there, it’s only a matter of updating the scroll container’s background gradient so that the color stops highlight the top instead of the center. Like this:
And if one of the items has to be pre-selected when the page loads, we can get its position in JavaScript (getBoundingClientRect()) and use the scrollTo() method to scroll the container to where that specific item’s position is at the point of selection (which we’ll say is the center in keeping with our original demo). We’ll append a .selected class on that .scroll-item.
<section class="scroll-container"> <!-- more items --> <label class="scroll-items selected"> 2024 <input type=radio name=items /> </label> <!-- more items --> </section>
Let’s select the .selected class, get its dimensions, and automatically scroll to it on page load:
let selected_item = (document.querySelector(".selected")).getBoundingClientRect(); let scroll_container = document.querySelector(".scroll-container"); scroll_container.scrollTo(0, selected_item.top - scroll_container.offsetHeight - selected_item.height);
It’s a little tough to demo this in a typical CodePen embed, so here’s a live demo in a GitHub Page (source code). I’ll drop a video in as well:
That’s it! You can build up this control or use it as a starting point to experiment with different layouts, styles, animations, and such. It’s important the UX clearly conveys to the users how the selection is done and which item is currently selected. And if I was doing this in a production environment, I’d want to make sure there’s a good fallback experience for when JavaScript might be unavailable and that my markup performs well on a screen reader.
References and further reading
0 notes
Dockge: A New Way To Manage Your Docker Containers
Dockge is a self-hosted Docker stack manager, designed to offer a simple and clean interface for managing multiple Docker compose files. It has been developed by the same individual responsible for creating Uptime Kuma, a popular software for monitoring uptime
Dockge is described as an easy-to-use, and reactive self-hosted manager that is focused on Docker compose.yaml stack orientation. It features an interactive editor for compose.yaml, an interactive web terminal, and a reactive UI where everything is responsive, including real-time progress and terminal output.
It allows for the management of compose.yaml files, including creating, editing, starting, stopping, restarting, and deleting, as well as updating Docker images. The user interface is designed to be easy to use and visually appealing, especially for those who appreciate the UI/UX of Uptime Kuma.
Additionally, Dockge can convert docker run … commands into compose.yaml and maintains a file-based structure, meaning that compose files are stored on the user's drive as usual and can be interacted with using normal docker compose commands.
The motivation behind Dockge's development includes dissatisfaction with existing solutions like Portainer, especially regarding stack management. Challenges with Portainer included issues like indefinite loading times when deploying stacks and unclear error messages. The developer initially planned to use Deno or Bun.js for Dockge's development but ultimately decided on Node.js due to lack of support for arm64 in the former technologies.
In summary, Dockge is a versatile and user-friendly tool for managing Docker stacks, offering a responsive and interactive environment for Docker compose file management. Its development was driven by a desire to improve upon existing tools in terms of usability and clarity.
Resource links:
Github:
https://github.com/louislam/dockge
FAQ:
https://github.com/louislam/dockge#faq
0 notes
Dashboard Unfucker v3.3.0!
As I first discovered today from the massive surge of people reblogging my previous update posts, the shitty new layout is now universal despite widespread protest, since us existing users are now apparently backseat to a Tumblr's hypothetical endless stream of high-revenue new users who are allergic to using social media sites that don't look like every other site. Well, thankfully at least for the time being, reverting the update via userscript is still as easy as ever!
Version 3.3.0 even fixes the new server-side bug where avatars next to posts disappear, because apparently I spend more time reviewing my commits than a multimillion dollar social media platform.
Installation Guide:
A userscript extension is required to run the script. Currently, the only tested extensions are Tampermonkey and Violentmonkey, but you might have still have luck with a different extension if you already use it.
Once you have the userscript extension installed, simply click this link to open the install page. This also works for updating, but make sure the version listed near the top is up to date, since it only fetches the script from GitHub every so often.
And of course, it's all open-source! Contributions, bug reports, and general insights are all appreciated.
Common troubleshooting info under cut:
Script not working
I can't offer specific help without knowing exact details, but two common issues are caching (try clearing your browser cache) and conflicts with New XKit (the script works fine with XKit Rewritten, which I would recommend anyways). If neither of those solve it, you can open an issue on the repository with more details.
Content takes up the full width of the page
This is an XKit feature, Panorama.
6K notes
·
View notes