Skip to content
  1. Keyline UI
  2. Marker
Keyline UIComponents
  • Get started
    • Installation
    • Theming
    • Modes
    • Configuration
    • Composition
  • Actions
    • Button
    • Button group
    • Split button
    • Toggle
    • Toggle group
    • Toolbar
    • Menu
    • Menubar
    • Context menu
  • Inputs
    • Field and form
    • Checkbox
    • Checkbox group
    • Radio group
    • Switch
    • Slider
    • Segmented
    • Select
    • Native select
    • Combobox
    • Multiselect
    • Number field
    • OTP field
    • Time field
    • Date picker and calendar
    • Date range
  • Data
    • Table
    • Chart
    • Stat and meter
    • Status and badge
    • Progress
    • Skeleton
    • Empty
    • Avatar
    • Kbd
    • Marker
  • Navigation
    • Tabs
    • Breadcrumb
    • Pagination
    • Nav
    • Navigation menu
    • Command menu
  • Overlays
    • Dialog
    • Alert dialog
    • Drawer
    • Sheet
    • Popover
    • Hover card
    • Tooltip
    • Toast
    • Notice
  • Layout
    • App shell
    • Sidebar
    • Panel
    • Resizable
    • Scroll area
    • Accordion
    • Collapsible
    • Carousel
    • Inspector
    • Item
    • Direction
  • Conversation
    • Message
    • Bubble
    • Message scroller
    • Attachment
    • Questionnaire
  • Blocks
    • Shipments

Marker

A step in an activity timeline or between messages, in the code voice. A glyph and words, a divider between days, a heading over a run of steps, or work still going. Pending runs the yellow segment under the words, never a spinner.

Loading the live example…

"use client"

import { Package, Phone, Truck } from "lucide-react"
import { useEffect, useRef, useState } from "react"
import { Button } from "@/components/keyline/ui/button"
import { Marker, MarkerContent, MarkerIcon } from "@/components/keyline/ui/marker"
import { Status } from "@/components/keyline/ui/status"

const PHONE = <Phone size={16} aria-hidden="true" />
const BOX = <Package size={16} aria-hidden="true" />
const TRUCK = <Truck size={16} aria-hidden="true" />

type Step = "idle" | "picking" | "picked"

export function OrderActivity() {
  const [step, setStep] = useState<Step>("idle")
  const timer = useRef<ReturnType<typeof setTimeout>>(undefined)
  useEffect(() => () => clearTimeout(timer.current), [])

  const send = () => {
    setStep("picking")
    timer.current = setTimeout(() => setStep("picked"), 2400)
  }

  return (
    <div className="grid max-w-[460px] gap-3">
      <Marker variant="border">
        <MarkerContent>DM-4107 · Lackawanna County</MarkerContent>
      </Marker>
      <Marker variant="separator">
        <MarkerContent>Yesterday</MarkerContent>
      </Marker>
      <Marker>
        <MarkerIcon>{PHONE}</MarkerIcon>
        <MarkerContent>Dwight took the order by phone: 120 cases</MarkerContent>
      </Marker>
      <Marker variant="separator">
        <MarkerContent>Today</MarkerContent>
      </Marker>
      <Marker>
        <MarkerIcon>{BOX}</MarkerIcon>
        <MarkerContent>Angela approved the credit check</MarkerContent>
      </Marker>
      {step !== "idle" ? (
        <Marker pending={step === "picking"}>
          <MarkerIcon>{step === "picking" ? TRUCK : <Status kind="done" />}</MarkerIcon>
          <MarkerContent>{step === "picking" ? "Darryl's team is picking 120 cases…" : "Picked and on the truck for Thursday"}</MarkerContent>
        </Marker>
      ) : null}
      <Button className="mt-2 justify-self-start" disabled={step !== "idle"} onClick={send}>
        {step === "idle" ? "Send to the warehouse" : "Sent to the warehouse"}
      </Button>
    </div>
  )
}

Installation

npx shadcn@latest add @keyline-ui/marker

Run it where your components.json is. The first time, map the @keyline-ui registry: one command, in Installation.

Usage

import { Marker, MarkerContent, MarkerIcon } from "@/components/keyline/ui/marker"
<Marker variant="separator">
  <MarkerContent>Today</MarkerContent>
</Marker>
<Marker pending={picking}>
  <MarkerIcon>{TruckIcon}</MarkerIcon>
  <MarkerContent>Darryl's team is picking 120 cases…</MarkerContent>
</Marker>

Props

PropTypeDefaultDescription
variant"default" | "separator" | "border"Default "default"A step; words between two seams, such as a day; or a heading with a keyline under it.
pendingbooleanDefault falseWork in progress. The marker becomes a polite status, so the change is announced. Remove it when the step is done.
MarkerIconReactNodeDefault —A 16px glyph cell, hidden from screen readers.
MarkerContentReactNodeDefault —The words.

A marker is a div; a separator marker has the separator role.

Sheet 41 of 73PreviousKbdNextTabs
On this page