Chat
Marker.
Mono uppercase dividers and status notes for a thread, like day breaks, joins and system events.
import { CircleCheck, UserPlus } from "lucide-react";
import { Bubble, BubbleContent } from "@/components/ui/bubble";
import { Marker, MarkerContent, MarkerIcon } from "@/components/ui/marker";
export default function MarkerDemo() {
return (
<div className="flex w-full max-w-md flex-col gap-4">
<Marker variant="separator" role="separator">
<MarkerContent>Yesterday</MarkerContent>
</Marker>
<Bubble variant="muted">
<BubbleContent>Server restart at midnight.</BubbleContent>
</Bubble>
<Marker variant="separator" role="separator">
<MarkerContent>Today</MarkerContent>
</Marker>
<Marker className="justify-center">
<MarkerIcon>
<UserPlus />
</MarkerIcon>
<MarkerContent>moss_builder joined the channel</MarkerContent>
</Marker>
<Bubble align="end">
<BubbleContent>Welcome in. Tunnels are on the east wall.</BubbleContent>
</Bubble>
<Marker variant="border" className="text-success">
<MarkerIcon>
<CircleCheck />
</MarkerIcon>
<MarkerContent>
Backup finished. <a href="#">View log</a>
</MarkerContent>
</Marker>
</div>
);
}Installation#
With the CLI
$npx lanterncn add markerThis 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/marker. See Installation if your project is not set up yet.
Manually
Install the dependencies
npm install class-variance-authority radix-uiCopy the source into your project
components/ui/marker.tsximport * as React from "react"; import { cva, type VariantProps } from "class-variance-authority"; import { Slot } from "radix-ui"; import { cn } from "@/lib/utils"; const markerVariants = cva( "group/marker relative flex min-h-4 w-full items-center gap-2 text-left font-mono text-[10px] leading-relaxed tracking-[0.2em] text-muted-foreground uppercase [&_svg:not([class*='size-'])]:size-3.5 [a]:text-primary [a]:underline-offset-4 [a]:hover:underline", { variants: { variant: { default: "", separator: "before:mr-1 before:h-px before:min-w-0 before:flex-1 before:bg-border after:ml-1 after:h-px after:min-w-0 after:flex-1 after:bg-border", border: "border-b border-border pb-2", }, }, }, ); function Marker({ className, variant = "default", asChild = false, ...props }: React.ComponentProps<"div"> & VariantProps<typeof markerVariants> & { asChild?: boolean }) { const Comp = asChild ? Slot.Root : "div"; return <Comp data-slot="marker" data-variant={variant} className={cn(markerVariants({ variant, className }))} {...props} />; } function MarkerIcon({ className, ...props }: React.ComponentProps<"span">) { return ( <span data-slot="marker-icon" aria-hidden="true" className={cn("flex size-3.5 shrink-0 items-center justify-center [&_svg:not([class*='size-'])]:size-3.5", className)} {...props} /> ); } function MarkerContent({ className, ...props }: React.ComponentProps<"span">) { return ( <span data-slot="marker-content" className={cn( "min-w-0 wrap-break-word group-data-[variant=separator]/marker:flex-none group-data-[variant=separator]/marker:text-center *:[a]:text-primary *:[a]:underline-offset-4 *:[a]:hover:underline", className, )} {...props} /> ); } export { Marker, MarkerIcon, MarkerContent, markerVariants };Update the import paths to match your project
The source imports
cnfrom@/lib/utils.
Usage#
import { Marker, MarkerIcon, MarkerContent } from "@/components/ui/marker";<Marker variant="separator">
<MarkerContent>Today</MarkerContent>
</Marker>