# Marker

A marker for labeling sections with optional icons, borders, and separators.

## Installation

```bash
npx shadcn@latest add https://reactdocs.canceydejean.dev/r/marker.json
```

[Registry JSON](https://reactdocs.canceydejean.dev/r/marker.json)

## Preview

```tsx
import { IconInfoCircle } from "@tabler/icons-react";

import { Marker, MarkerContent, MarkerIcon } from "@/components/ui/marker/marker";

export function Preview() {
  return (
    <Marker className="w-full max-w-sm">
      <MarkerIcon>
        <IconInfoCircle />
      </MarkerIcon>
      <MarkerContent>Optional section label</MarkerContent>
    </Marker>
  );
}
```


## Source

### marker.tsx

```tsx
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { type VariantProps } from "class-variance-authority";
import * as React from "react";

import { cn } from "cn";

import { markerVariants } from "./marker.variants";

function Marker({
  className,
  variant = "default",
  render,
  ...props
}: useRender.ComponentProps<"div"> & VariantProps<typeof markerVariants>) {
  return useRender({
    defaultTagName: "div",
    props: mergeProps<"div">(
      {
        className: cn(markerVariants({ variant, className })),
      },
      props,
    ),
    render,
    state: {
      slot: "marker",
      variant,
    },
  });
}

function MarkerIcon({ className, ...props }: React.ComponentProps<"span">) {
  return (
    <span
      data-slot="marker-icon"
      aria-hidden="true"
      className={cn(
        "size-4 shrink-0 [&_svg:not([class*='size-'])]:size-4",
        className,
      )}
      {...props}
    />
  );
}

function MarkerContent({ className, ...props }: React.ComponentProps<"span">) {
  return (
    <span
      data-slot="marker-content"
      className={cn(
        "*:[a]:hover:text-foreground min-w-0 wrap-break-word group-data-[variant=separator]/marker:flex-none group-data-[variant=separator]/marker:text-center *:[a]:underline *:[a]:underline-offset-3",
        className,
      )}
      {...props}
    />
  );
}

export { Marker, MarkerIcon, MarkerContent, markerVariants };
```


### marker.variants.ts

```ts
import { cva } from "class-variance-authority";

import { cn } from "cn"

const markerBase = cn(
  "group/marker relative flex min-h-4 w-full items-center gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground",
);

const markerConfig = {
  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",
    },
  },
  compoundVariants: [],
  defaultVariants: {
    variant: "default",
  },
} as const;

export const markerCva = cva(markerBase, {
  ...markerConfig,
  compoundVariants: [...markerConfig.compoundVariants],
});

// Export the variant variants
export const MARKER_VARIANTS = Object.keys(
  markerConfig.variants.variant,
) as (keyof typeof markerConfig.variants.variant)[];

export const markerVariants = markerCva;
```



## Usage

Use markers as section captions, inline notes, or divider labels in lists and forms.

```tsx
import { Marker, MarkerContent, MarkerIcon } from "@/components/marker/marker";

export function Example() {
  return (
    <Marker>
      <MarkerIcon>{/* icon */}</MarkerIcon>
      <MarkerContent>Optional section label</MarkerContent>
    </Marker>
  );
}
```

Variants: `default`, `separator` (horizontal rules around the label), and `border` (bottom border).
Render as another element with `render`.

