Home Writing

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:

2023
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 my data-year attribute is not equal to the data-year attribute on the previous list item. If this is true, remove the before:content-none class and add the before: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.


  • Loading next post...
  • Loading previous post...