Spot Icon
betaA brand-colored sticker around an icon that names a piece of content, like a feature, an empty state, or a card's header.
Preview
size
feature list: each spot's edge lines up with the heading
What you get
The whole team
Invite teammates, managers, and guests in one go.
Reminders
They go out the day before, so nobody forgets.
Directions
Every event away from the office links to a map.
empty state
No events this week
New events show up here once they are published.
card header
Ask an admin if you need to see them.
title
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the component.
npx shadcn@latest add @txbrendan/spot-icon
Use it for
- Naming a piece of content: a feature in a list, an empty state, a hub link, or a card's header.
- Use size lg over an empty state, md in a hub link or card header, and sm in a dense feature list.
- Use one spot per item. Pass any icon element, like <Calendar /> from lucide-react.
- Its side margins hang outside its box, so the sticker's edge lines up with the text above or below it.
Avoid it for
- Anything you press, and rows, menus, charts, and statuses. Use a plain icon there.
- Saying something with its color. Artwork colors are decorative; use a visible label for meaning.
- Sizes under 24px. Use a plain icon instead.
Props
- ink
Optional artwork foreground color. Omit to follow the brand theme.
string
- paper
Optional sticker background color. Omit to follow the brand theme.
string
- icon
The icon on the sticker, like <Calendar /> from lucide-react. It is sized for you.
ReactNode
- size
sm is 24px, md is 32px, lg is 40px.
"sm" | "md" | "lg" · default "md"
- title
Names the spot for screen readers. Without it the spot is hidden from them.
string
- className
Extra classes. Later classes win.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| ink | string | - | Optional artwork foreground color. Omit to follow the brand theme. |
| paper | string | - | Optional sticker background color. Omit to follow the brand theme. |
| icon | ReactNode | - | The icon on the sticker, like <Calendar /> from lucide-react. It is sized for you. |
| size | "sm" | "md" | "lg" | "md" | sm is 24px, md is 32px, lg is 40px. |
| title | string | - | Names the spot for screen readers. Without it the spot is hidden from them. |
| className | string | - | Extra classes. Later classes win. |
Accessibility
- Without title the spot has aria-hidden, since the text beside it names the same thing.
- With title it is role="img" with that name.
- The default brand pair is checked at 4.5:1. Custom ink and paper colors are not contrast-checked.
Examples
Over an empty state
import { CalendarDays } from "lucide-react";
<div className="flex flex-col items-center gap-3 text-center">
<SpotIcon icon={<CalendarDays />} size="lg" />
<p className="font-semibold">No events this week</p>
</div>In a feature list
import { Bell, Users } from "lucide-react";
<ul className="flex flex-col gap-4">
<li className="flex items-start gap-3">
<SpotIcon icon={<Users />} />
<p>Invite the whole team in one go.</p>
</li>
<li className="flex items-start gap-3">
<SpotIcon icon={<Bell />} />
<p>Reminders go out the day before.</p>
</li>
</ul>Standing alone, with a name
import { Trophy } from "lucide-react";
<SpotIcon icon={<Trophy />} title="Award" />