Lantern

Status Pill.

The TurtleDeck status label: a colored dot and a mono uppercase word for online, offline, running and idle. Running pulses.

onlineofflinerunningidle

Installation#

With the CLI

$npx lanterncn add status-pill

This also installs the Lantern theme and any Lantern UI components it depends on. The shadcn CLI works directly too: npx shadcn@latest add httptim/lantern-ui/status-pill. See Installation if your project is not set up yet.

Manually

  1. Install the dependencies

    npm install class-variance-authority
  2. Copy the source into your project

    components/ui/status-pill.tsx
    import * as React from "react";
    import { cva, type VariantProps } from "class-variance-authority";
    
    import { cn } from "@/lib/utils";
    
    const statusPillVariants = cva(
      "inline-flex w-fit shrink-0 items-center gap-[7px] font-mono text-[10px] leading-none font-semibold tracking-[0.15em] whitespace-nowrap uppercase",
      {
        variants: {
          tone: {
            online: "text-success",
            offline: "text-destructive",
            running: "text-primary",
            idle: "text-muted-foreground",
          },
        },
        defaultVariants: { tone: "idle" },
      },
    );
    
    const dotTones = {
      online: "bg-success shadow-[0_0_10px_#9bba8660]",
      offline: "bg-destructive",
      running: "animate-lantern-pulse bg-primary shadow-[0_0_10px_#f5a66560] [animation-duration:1.2s]",
      idle: "bg-input",
    } as const;
    
    /** The TurtleDeck status pill: a dot and a mono uppercase label. */
    function StatusPill({
      className,
      tone,
      children,
      ...props
    }: React.ComponentProps<"span"> & VariantProps<typeof statusPillVariants>) {
      const t = tone ?? "idle";
      return (
        <span data-slot="status-pill" data-tone={t} className={cn(statusPillVariants({ tone: t }), className)} {...props}>
          <span aria-hidden="true" data-slot="status-pill-dot" className={cn("size-1.5 shrink-0 rounded-full", dotTones[t])} />
          {children ?? t}
        </span>
      );
    }
    
    export { StatusPill, statusPillVariants };
  3. Update the import paths to match your project

    The source imports cn from @/lib/utils.

Usage#

import { StatusPill } from "@/components/ui/status-pill";
<StatusPill tone="running">Running</StatusPill>

With no children the pill shows the tone name. Add ml-auto through className to push it to the end of a flex row.

Examples#

In a list row

  • Miner 01
    Strip mine y=-54
    Running
  • Farmer
    Wheat field
    Online
  • Builder
    No job
    Idle
  • Scout
    Last seen 2h ago
    Offline