Inspector Link

Settings row for a destination: the row reads the URL with its scheme stripped and marks whether it leaves the tab, and opens an editor holding an optional page menu, the URL field and the target and nofollow switches.

Installation

Adds the component and everything it depends on to your project.

npx shadcn add https://ui.beste.co/component/r-base/inspector-link

New here? Read the installation guide.

Usage

The import and the props worth knowing about, in one place.

import { InspectorLink } from "@/components/beste/component/inspector-link";

// Uncontrolled
<InspectorLink label="Link" defaultValue={{ href: "https://beste.co", newTab: true }} />

// Controlled. The value is the pieces an anchor takes.
<InspectorLink
  label="Button link"
  value={link}
  onValueChange={setLink}
  onValueCommit={(value) => save(value)}
/>

// Destinations inside the site become a menu above the URL field
<InspectorLink
  label="Link"
  pages={[{ value: "/", label: "Home" }, { value: "/pricing", label: "Pricing" }]}
  value={link}
  onValueChange={setLink}
/>

<InspectorLink
  label="Source"
  icon={LinkIcon}          // optional leading icon
  tone="outline"           // "muted" (default) | "outline" | "ghost"
  size="sm"                // "sm" | "default" | "lg"
  allowNofollow            // offer the nofollow toggle
  placeholder="https://"
  emptyLabel="Not linked"  // what the row reads with no destination
  value={link}
  onValueChange={setLink}
/>

// What the value turns into
<a
  href={link.href}
  target={link.newTab ? "_blank" : undefined}
  rel={[link.newTab && "noreferrer", link.nofollow && "nofollow"].filter(Boolean).join(" ") || undefined}
>
  Read more
</a>

Playground

Turn the props on the right; the snippet under them is what you would write to get what you see.

Usage
import { InspectorLink } from "@/components/beste/component/inspector-link";

<InspectorLink
  label="Link"
  className="w-72"
  defaultValue={{"href":"https://beste.co/pricing","newTab":true}}
  pages={[{"value":"/","label":"Home"},{"value":"/pricing","label":"Pricing"},{"value":"/blog","label":"Blog"}]}
  allowNofollow
/>

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
label*stringLabel rendered on the left, inside the row.
iconLucideIconOptional leading icon shown before the label.
valueLinkValueControlled value. Pair it with `onValueChange`.
defaultValueLinkValueInitial value in uncontrolled mode.
onValueChange(value: LinkValue) => voidFires on every keystroke in the URL field and on every toggle.
onValueCommit(value: LinkValue) => voidFires once an edit is finished — the URL field left, a switch flipped, the link removed. Use it for work too expensive to run per keystroke.
onOpenChange(open: boolean) => voidFires when the editor opens or closes.
pages(string | InspectorLinkPage)[]Destinations inside the site. Passing them adds a menu above the URL field, so the common case is a choice rather than a typed path.
allowNofollowbooleanOffer the nofollow toggle.
placeholderstringGhost text in the URL field.
emptyLabelstring"None"What the row reads while there is no destination.
disabledbooleanBlock interaction and dim the row.
tone"muted" | "outline" | "ghost""muted"Surface treatment: filled (default), hairline outline, or bare until hover.
size"sm" | "default" | "lg""default"Row height preset.
classNamestring
aria-labelstringAccessible name. Falls back to `label`.

More Inspector components

View all Inspector

Inspector Tabs

The strip that splits a settings panel into two or three questions instead of one long scroll. It is the strip and nothing else: what the tabs switch between stays in the panel's own markup, beside the state that decides it. The pill slides between equal columns, arrow keys both move and select, and a tab can carry a count of what has changed under it.

Dark Mode

Inspector Segmented

Settings row whose choices sit side by side on the right, with a marker that slides between them: the readable alternative to a switch when the two states deserve names, and the compact one to a select at three or four options.

Inspector Range

Settings row for a span rather than a value: two thumbs on the row itself, the band between them filling it, and both ends of the pair read out on the right. Ticks, tones and thumb states follow inspector-slider exactly, appearing on hover.

Inspector Action

The row that does something instead of holding something: open a sub-panel, replace an asset, regenerate a key, delete the section. It carries a description, a hint, a busy spinner and a destructive treatment, and renders as a plain anchor when given an href.

Inspector Gradient

Settings row for a gradient: the row shows a strip of it, and opens an editor with draggable stops over the ramp, so one colour can hold a wider share than the next. The kind, the direction and the selected stop's colour and offset sit under it as rows of the family.

Inspector Variants

The choice that has to be seen to be made: a template, a layout, a chart type. Each option is a picture, normally a rendered screenshot passed as a URL, or markup for the choices no photograph would show. The row is the trigger, the grid is width-matched to it, and the captions under the pictures can be dropped for a set whose pictures say everything.