Location Pin 1 Streamline Icon: https://streamlinehq.com applied cartography

Order, Tailwind, DRY

(Order in the CSS rule sense, not the metaphysical sense.)

The time has come to begin exfiltrating some higher-traffic, higher-leverage parts of Buttondown's admin UI away from the autogenerated Django admin and into some more bespoke components.

Take, for instance, this rather grisly (but useful) inline admin table:

This contains useful information but is annoying to parse. It gets replaced with the following HTML, all still governed by Django and a wallop of Tailwind Not mobile friendly, I'm afraid! Not exactly a pressing concern for the admin site at the moment.:

  1. draft

  2. <li class="relative sm:mb-0 flex-1 last:text-right group">
        <div class="flex items-center">
            <div class="z-10 flex items-center justify-center w-6 h-6 bg-blue-100 group-last:bg-blue-500 rounded-full ring-0 ring-white dark:bg-blue-900 sm:ring-8 dark:ring-gray-900 shrink-0">
            </div>
            <div class="sm:flex w-full bg-gray-200 h-0.5 dark:bg-gray-700 group-last:order-first"></div>
        </div>
        <div class="mt-3 sm:pe-8 group-last:pe-0">
            <h3 class="text-md font-semibold text-gray-900 dark:text-white">about_to_send</h3>
            <time class="block text-sm font-normal leading-none text-gray-400 dark:text-gray-500">8:16 p.m.</time>
        </div>
    </li>
    
    <li class="relative sm:mb-0 flex-1 last:text-right group">
        <div class="flex items-center">
            <div class="z-10 flex items-center justify-center w-6 h-6 bg-blue-100 group-last:bg-blue-500 rounded-full ring-0 ring-white dark:bg-blue-900 sm:ring-8 dark:ring-gray-900 shrink-0">
            </div>
            <div class="sm:flex w-full bg-gray-200 h-0.5 dark:bg-gray-700 group-last:order-first"></div>
        </div>
        <div class="mt-3 sm:pe-8 group-last:pe-0">
            <h3 class="text-md font-semibold text-gray-900 dark:text-white">in_flight</h3>
            <time class="block text-sm font-normal leading-none text-gray-400 dark:text-gray-500">8:18 p.m.</time>
        </div>
    </li>
    
    <li class="relative sm:mb-0 flex-1 last:text-right group">
        <div class="flex items-center">
            <div class="z-10 flex items-center justify-center w-6 h-6 bg-blue-100 group-last:bg-blue-500 rounded-full ring-0 ring-white dark:bg-blue-900 sm:ring-8 dark:ring-gray-900 shrink-0">
            </div>
            <div class="sm:flex w-full bg-gray-200 h-0.5 dark:bg-gray-700 group-last:order-first"></div>
        </div>
        <div class="mt-3 sm:pe-8 group-last:pe-0">
            <h3 class="text-md font-semibold text-gray-900 dark:text-white">sent</h3>
            <time class="block text-sm font-normal leading-none text-gray-400 dark:text-gray-500">8:20 p.m.</time>
        </div>
    </li></ol>
    

It's a trivial thing, but lets me pull out a new toy that I learned from Mary a few weeks back: order, which lets you re-arrange the rendering order of elements in a flex container irrespective of their original order.

For instance, consider the following:

<div class="flex gap-1">
  <div class="order-2">world</div>
  <div class="order-1">hello</div>
</div>

This, as you might expect, renders as:

world
hello

Where this gets really useful is composition with groups. Consider the following:

<div class="flex gap-1 w-[200px]">
  <div class="group flex-1 flex items-center">
    <div class="z-10 flex items-center justify-center size-6 bg-red-500"></div>
    <div class="w-full bg-gray-200 h-0.5"></div>
  </div>
  <div class="group flex-1 flex items-center">
    <div class="z-10 flex items-center justify-center size-6 bg-red-500"></div>
    <div class="w-full bg-gray-200 h-0.5"></div>
  </div>
  <div class="group flex-1 flex items-center">
    <div class="z-10 flex items-center justify-center size-6 bg-red-500"></div>
    <div class="w-full bg-gray-200 h-0.5"></div>
  </div>
</div>

This renders, unexcitingly, as:

But! Add a tiny sprinkle of group-last:

<div class="flex gap-1 w-[200px]">
  <div class="group flex-1 flex items-center">
    <div
      class="z-10 flex items-center justify-center size-6 bg-red-500 group-last:bg-blue-500"
    ></div>
    <div class="w-full bg-gray-200 h-0.5 group-last:order-first"></div>
  </div>
  <div class="group flex-1 flex items-center">
    <div
      class="z-10 flex items-center justify-center size-6 bg-red-500 group-last:bg-blue-500"
    ></div>
    <div class="w-full bg-gray-200 h-0.5 group-last:order-first"></div>
  </div>
  <div class="group flex-1 flex items-center">
    <div
      class="z-10 flex items-center justify-center size-6 bg-red-500 group-last:bg-blue-500"
    ></div>
    <div class="w-full bg-gray-200 h-0.5 group-last:order-first"></div>
  </div>
</div>

And you get:

Obviously, that is a lot of HTML to write for a very simple outcome. There are a bunch of ways you could reduce this. Why so much repetition? Why specify group-last for every node when you know it's going to be the last one?

Because in reality, the above HTML is actually, in Django, a pure and concise for loop:

<div class="flex gap-1 w-[200px]">
  {\% for item in items \%}
  <div class="group flex-1 flex items-center">
    <div
      class="z-10 flex items-center justify-center size-6 bg-red-500 group-last:bg-blue-500"
    ></div>
    <div class="w-full bg-gray-200 h-0.5 group-last:order-first"></div>
  </div>
  {\% endfor \%}
</div>

Which suddenly looks much more pleasant and maintainable than its conditionally-rendered alternative:

<div class="flex gap-1 w-[200px]">
  {\% for item in items \%}
  <div class="group flex-1 flex items-center">
    <div
      class="z-10 flex items-center justify-center size-6 {\% if forloop.last \%} bg-blue-500 {\% else \%} bg-red-500 {\% endif \%}"
    ></div>
    <div
      class="w-full bg-gray-200 h-0.5 {\% if forloop.last \%} order-first {\% endif \%}"
    ></div>
  </div>
  {\% endfor \%}
</div>

About the Author

I'm Justin Duke — a software engineer, writer, and founder. I currently work as the CEO of Buttondown, the best way to start and grow your newsletter, and as a partner at Third South Capital.