til / Displaying a section title with hyperscript
I’ve been tracking the movies I watch for a long time and recently rebuilt the website using Go and htmx (an awesome experience btw. Same stack as the site you’re reading on.)
The feed on the start page is an endless scroll and I wanted to section the movies by the year that I watched them. I took inspiration from Anthony Fu’s blog that has some nice outlined text for the years. It will look something like this:
Full Tailwind classes I'm using for the interested
relative before:relative before:mb-4 before:block before:text-4xl before:text-transparent before:opacity-10 before:[-webkit-text-stroke-color:_#000] before:[-webkit-text-stroke-width:2px] dark:before:[-webkit-text-stroke-color:#fff] lg:before:absolute lg:before:-left-52 lg:before:-top-0 lg:before:mb-0 lg:before:mt-0 lg:before:text-7xl [&:not(:first-child)]:before:mt-8 [&:not(:first-child)]:before:lg:-top-8 before:font-mono before:content-[attr(data-year)]
As the feed is continuous I didn’t want to chunk the data into years.
type Movie struct {
Title string
}
// I don't want to do this
var data = map[int][]Movie{
2022: {
{
Title: "Godfather",
},
},
2021: {
{
Title: "Requiem for a Dream",
},
},
}
The solution I came up with was to use data-*
attributes and conditional apply Tailwind’s data attribute styles using hyperscript. For starters, let’s add the data attribute and a class we’re going to need.
<li
class="before:content-[attr(data-year)]"
data-year={ movie.WatchedAt.Format("2006") }>
<!-- Content -->
</li>
This gets the year the movie was watched and sets it as data-year
. The before:content-[attr(data-year)]
class sets the content of the before pseudo element from the data-year
attribute. This is working well, but we’re displaying the year on each movie. I just want it on the first movie each year. Here’s where hyperscript comes in.
<li
class="before:content-none"
data-year={ movie.WatchedAt.Format("2006") }
_="init if my @data-year is not equal to @data-year of previous <li/>
then
remove .before:content-none
add .{'before:content-[attr(data-year)]'}
end
">
<!-- Content -->
</li>
We change the class to before:content-none
to hide the pseudo elements for all movies. The _
is the attribute we use to write our hyperscript code. The syntax is similar to AppleScript (which I like). It reads like a sentence.
When the element loads (
init
), check if mydata-year
attribute is not equal to thedata-year
attribute on the previous list item. If this is true, remove thebefore:content-none
class and add thebefore:content-[attr(data-year)]
class.
The slightly awkward syntax for the added content class is needed because it contains square brackets. This will only display the year whenever it changes from one list element to the next and will work perfectly with continuously loading data.