Skip to content
txbrendan/ui

Spot Icon

beta

A 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

Private project
Only admins can see the billing notes.

Ask an admin if you need to see them.

title

Install

  1. 1. Add the registry to components.json, once per app. Without it, the shadcn CLI looks up @txbrendan in a public list that txbrendan/ui does not control.

    npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"
  2. 2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.

    npx shadcn@latest add @txbrendan/theme
  3. 3. 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

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" />