primitives
Command Button
A wide command-palette trigger button with a left search icon, a muted placeholder label, and a right-aligned keyboard shortcut badge. Hover shifts the surface from background to muted and restores full foreground contrast. Fully accessible: native button semantics, focus-visible ring from --ring, aria-hidden decorative icon, keyboard operable.
Ported from ilkhoeri (MIT)
Install
1. Register the namespace (once per project):
json
// components.json — register the @bottega namespace once
{
"registries": {
"@bottega": { "url": "https://bottega.ariacode.ca/r/{name}.json" }
}
}2. Add the component:
bash
npx shadcn add @bottega/command-buttonUsage
Usagetsx
<CommandButton />Props
| Prop | Type | Default | Description |
|---|---|---|---|
| placeholder | string | Search… | Placeholder label shown inside the button. |
| shortcut | string | ⌘K | Keyboard shortcut hint rendered in the trailing badge. |
Source
command-button.tsxtsx
"use client";
import type React from "react";
import styles from "./command-button.module.css";
function cn(...parts: Array<string | false | undefined>) {
return parts.filter(Boolean).join(" ");
}
export interface CommandButtonProps
extends React.ComponentProps<"button"> {
/** Placeholder label shown inside the button. */
placeholder?: string;
/** Keyboard shortcut hint rendered in the trailing badge. */
shortcut?: string;
}
export function CommandButton({
placeholder = "Search…",
shortcut = "⌘K",
className,
...props
}: CommandButtonProps) {
return (
<button
type="button"
className={cn(
"relative inline-flex items-center justify-start whitespace-nowrap",
"h-8 w-64 px-4 rounded-[var(--radius)]",
"border text-sm font-normal shadow-none",
"focus-visible:outline-none",
"disabled:pointer-events-none disabled:opacity-50",
styles.button,
className,
)}
{...props}
>
{/* Search icon */}
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="mr-2 shrink-0"
>
<circle cx="11" cy="11" r="8" />
<path d="m21 21-4.3-4.3" />
</svg>
<span className="grow">{placeholder}</span>
{/* ponytail: single <kbd> mirrors the original; nested ⌘/K are one string */}
<kbd
className={cn(
"pointer-events-none absolute right-[0.3rem] top-[0.3rem]",
"flex h-5 select-none items-center gap-1 rounded",
"border px-1.5 font-mono text-[10px] font-medium",
styles.kbd,
)}
>
{shortcut}
</kbd>
</button>
);
}
Dependencies
- @bottega/tokens