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.
Adds the component and everything it depends on to your project.
npx shadcn add https://ui.beste.co/component/r-base/inspector-linkNew here? Read the installation guide.
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>Turn the props on the right; the snippet under them is what you would write to get what you see.
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
/>Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
label* | string | — | Label rendered on the left, inside the row. |
icon | LucideIcon | — | Optional leading icon shown before the label. |
value | LinkValue | — | Controlled value. Pair it with `onValueChange`. |
defaultValue | LinkValue | — | Initial value in uncontrolled mode. |
onValueChange | (value: LinkValue) => void | — | Fires on every keystroke in the URL field and on every toggle. |
onValueCommit | (value: LinkValue) => void | — | Fires 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) => void | — | Fires 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. |
allowNofollow | boolean | — | Offer the nofollow toggle. |
placeholder | string | — | Ghost text in the URL field. |
emptyLabel | string | "None" | What the row reads while there is no destination. |
disabled | boolean | — | Block 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. |
className | string | — | |
aria-label | string | — | Accessible name. Falls back to `label`. |
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.
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.
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.
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.
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.
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.