src/blog/2022-09-09-new-personal-website-heroicons-2-headless-ui-v17/index.mdx
import { adamwathan } from "@/app/blog/authors"; import card from "./card.jpg"; import spotlightPreview from "./spotlight-preview.png"; import spotlightDetail from "./spotlight-detail.png"; import heroiconsCover from "./heroicons-cover.jpg"; import headlessuiV17 from "./headlessui-v17.jpg"; import playInsiders from "./play-insiders.png"; import phoenix from "./phoenix.png"; import { Image } from "@/components/media"; import Link from "next/link"; import { Example, Figure } from "@/components/example.tsx"; import { CodeExampleGroup, CodeBlock, js, ts } from "@/components/code-example";
export const meta = {
title: "We built you a new personal website + Heroicons v2.0, Headless UI v1.7, and more",
description: We just released a stunning new personal website template for Tailwind UI, redesigned Heroicons from scratch, tagged a new version of Headless UI with some exciting new features, and more.,
date: "2022-09-09T16:24:00.000Z",
authors: [adamwathan],
image: card,
excerpt: (
<>
We just released a stunning new personal website template for Tailwind UI, redesigned Heroicons from scratch,
tagged a new version of Headless UI with some exciting new features, and more.
</>
),
};
It's been a busy week wrapping up a bunch of projects we've been working on, but everything is finally out the door so it feels like a good time for another update.
We triaged and resolved another <Link href="https://github.com/search?q=is%3Aclosed+org%3Atailwindlabs+archived%3Afalse+sort%3Acreated-desc+is%3Apublic+closed%3A%3E%3D2022-08-19+-author%3Aapp%2Fdependabot+-author%3Aapp%2Fgithub-actions+-author%3Aapp%2Fdepfu&type=Issues">226 GitHub issues and pull requests</Link> since my last post, and we're finally at under 50 open issues/PRs across our entire organization for the first time ever. So please stop finding bugs I just want to design and build beautiful stuff with Tailwind CSS for a while.
Speaking of beautiful stuff, here's what shipped over the last couple of weeks!
A couple of days ago we released <Link href="https://tailwindui.com/templates/spotlight">Spotlight</Link>, a stunning new personal website template we designed for Tailwind UI.
<Link href="https://tailwindui.com/templates/spotlight"> <Image alt="Learn about the Spotlight template" src={spotlightPreview} /> </Link>Like our other templates, it's built with Next.js, and this time we're using MDX to power all of the markdown-driven stuff like the blog section.
Designing this template was a pretty fun and interesting challenge — we wanted to come up with something that was really beautiful and inspiring, but that was also unopinionated enough to feel like a good fit for almost anyone. We landed on a pretty minimalist design that gets its personality from little touches like rotated images, hints of color for links, and some subtle depth from shadows and layering in places like the top navigation.
<Link href="https://spotlight.tailwindui.com"> <Image alt="Preview the Spotlight template" src={spotlightDetail} /> </Link>As always, I recommend checking out <Link href="https://spotlight.tailwindui.com">the live preview</Link> for the full experience — especially pay attention to the way the avatar and navigation works on the home page as you scroll, it's very chef's kiss when you're playing with the real site.
We tried to structure the site the way we'd structure our own personal sites, so it includes a dedicated blog, a page for you to list some of your favorite projects you've worked on, an area for you to link to things like conference talks you've given, and a <Link href="https://spotlight.tailwindui.com/uses">"uses" page</Link> to list all of your favorite tools and gear.
If you've got a <Link href="https://tailwindui.com/all-access">Tailwind UI all-access</Link> license then you've already got access to this template! And if you don't, consider it — it's the best way to support our work on open-source projects like Tailwind CSS, Headless UI, and Heroicons.
Last year we released <Link href="/blog/heroicons-v1">Heroicons v1.0</Link>. Well last week we released <Link href="https://heroicons.com/">Heroicons v2.0</Link>, which is a brand new icon set, illustrated from scratch that Steve has been working on for about a year.
<Link href="https://heroicons.com"> <Image alt="Heroicons v2.0" src={heroiconsCover} /> </Link>It includes 280 icons drawn in three distinct styles:
The biggest differences from v1 are that the outline set uses a thinner stroke, which feels a bit more modern and fashionable these days, and visually the icons are a bit more playful in style.
Even though these have "v2" in the name, it's better to think of Heroicons v2 more like Terminator 2 than OpenSSL 2 — we feel like they represent our best work but it's a new icon set, not strictly an upgrade from the original icon set. Don't feel pressured to upgrade existing projects like you would with a real application dependency, but if you want to migrate, <Link href="https://github.com/tailwindlabs/heroicons/releases/tag/v2.0.0">check out the release notes</Link> for everything you need to switch.
To explore all of the new icons, visit the totally <Link href="https://heroicons.com/">redesigned Heroicons website</Link> we launched with the new set.
Earlier this week we tagged a new release of <Link href="https://headlessui.com/">Headless UI</Link>, our React and Vue libraries of unstyled UI components.
<Link href="https://headlessui.com/"> <Image alt="Headless UI v1.7" src={headlessuiV17} /> </Link>Headless UI v1.7 includes the usual slew of bug fixes and improvements, but also some really useful new features!
We've added a new by prop to the Listbox, Combobox, and RadioGroup components that make it a lot less cumbersome to bind an object as the form value.
import { Listbox } from "@headlessui/react";
const departments = [
{ id: 1, name: "Marketing", contact: "Durward Reynolds" },
{ id: 2, name: "HR", contact: "Kenton Towne" },
{ id: 3, name: "Sales", contact: "Therese Wunsch" },
{ id: 4, name: "Finance", contact: "Benedict Kessler" },
{ id: 5, name: "Customer service", contact: "Katelyn Rohan" },
];
function DepartmentPicker({ selectedDepartment, onChange }) {
return (
<Listbox value={selectedDepartment} by="id" onChange={onChange}>
<Listbox.Button>{selectedDepartment.name}</Listbox.Button>
<Listbox.Options>
{departments.map((department) => (
<Listbox.Option key={department.id} value={department}>
{department.name}
</Listbox.Option>
))}
</Listbox.Options>
</Listbox>
);
}
This makes it a lot easier for the value to come from outside the component, and saves you having to just bind the id or similar and do a bunch of lookups yourself to find the full object when needed.
Check out the updated <Link href="https://headlessui.com/react/listbox#binding-objects-as-values">"Binding objects as values" documentation</Link> for each component for some more detail.
The Listbox, Combobox, and RadioGroup components now let you optionally pass a defaultValue instead of a value, allowing you to use them as an uncontrolled component.
import { Listbox } from "@headlessui/react";
const people = [
{ id: 1, name: "Durward Reynolds" },
{ id: 2, name: "Kenton Towne" },
{ id: 3, name: "Therese Wunsch" },
{ id: 4, name: "Benedict Kessler" },
{ id: 5, name: "Katelyn Rohan" },
];
function Example() {
return (
<form action="/projects/1/assignee" method="post">
<Listbox name="assignee" defaultValue={people[0]}>
<Listbox.Button>{({ value }) => value.name}</Listbox.Button>
<Listbox.Options>
{people.map((person) => (
<Listbox.Option key={person.id} value={person}>
{person.name}
</Listbox.Option>
))}
</Listbox.Options>
</Listbox>
<button>Submit</button>
</form>
);
}
This can simplify your code when using traditional HTML forms or form APIs that collect their state using FormData instead of tracking it using React state.
Check out the <Link href="https://headlessui.com/react/listbox#using-as-an-uncontrolled-component">"Using as an uncontrolled component" documentation</Link> for each component to see some more examples.
Historically, you've always had to style the different states of a Headless UI component by inspecting arguments passed through a render prop and conditionally rendering whatever classes or content made sense. This could feel like a lot of boilerplate when just trying to tweak a background color or make some other CSS-only change.
In Headless UI v1.7, we've added a data-headlessui-state attribute to the rendered HTML that includes information about the current state so you can target it with just CSS.
We've also released a new <Link href="https://github.com/tailwindlabs/headlessui/tree/main/packages/%40headlessui-tailwindcss">@headlessui/tailwindcss</Link> plugin that gives you variants for these states so they are super easy to style with just Tailwind CSS classes:
<Listbox.Option
key={person.id}
value={person}
className="ui-active:bg-blue-500 ui-active:text-white ui-not-active:bg-white ui-not-active:text-black"
>
<CheckIcon className="ui-selected:block hidden" />
{person.name}
</Listbox.Option>
Check out the new documentation on <Link href="https://headlessui.com/react/listbox#using-data-attributes">styling using data attributes</Link> for some more details.
Not everyone knows this but we ship an insiders build of Tailwind CSS to npm that is automatically built and deployed every single time a new commit lands in the repository. This makes it really easy to test out new features and fixes before they are actually tagged in a proper release.
Well now we include access to the insiders build in <Link href="https://play.tailwindcss.com/">Tailwind Play</Link> as well, so you can play with bleeding edge stuff without even setting up a project:
<Link href="https://play.tailwindcss.com"> <Image alt="Tailwind Play insiders option" src={playInsiders} /> </Link>We only keep the latest insiders build on Play, so if you create a demo using an insiders build know that it might break if the next insiders build changes something in some unreleased feature you were using. You shouldn't be putting important things there anyways, come on be a professional.
A while ago we started talking with the <Link href="https://www.phoenixframework.org/">Phoenix</Link> team because they wanted to ship Tailwind CSS by default in a future release. I thought this was super exciting, and wanted to work with them to make the out-of-the-box experience really beautiful.
We designed a new splash screen and all of the necessary scaffolding for their generator system, which will ship as part of Phoenix v1.7.
<Image alt="New designs for Phoenix v1.7" src={phoenix} />Chris McCord the creator of Phoenix gave <Link href="https://www.youtube.com/watch?v=9-rqBLjr5Eo">a great talk</Link> last week that walks through all of the Tailwind CSS stuff they are shipping, worth a watch if you're curious to learn more.
So there you go, that's all of the coolest stuff we've been working on over the last few weeks!
Over the next month or so I'm excited to build a bunch of new Tailwind UI components we've been designing, explore some <Link href="https://caniuse.com/?search=container%20queries">new feature ideas</Link> for Tailwind CSS, and start doing some R&D on what it would look like to create a sort of application starter kit template with Tailwind + Next.js — think it could be pretty cool if we can nail it.
Catch you in the next update!