Componentpickers0.89 KB gzipZero dependencies
Saved Searches
Named queries with run and delete.
Preview
Live Preview
Saved searches
Friday VIP
tier:vip fri
Cheap seats
price<30
Installation
Tokens guide →Add to your project via CLI (zero dependencies, code you own):
npx bigbullui add saved-searchesOr install the full npm package:
npm install bigbulluiUsage
Open in StackBlitzimport { SavedSearches } from "@/components/ui/saved-searches";
<SavedSearches />Usage guidance
Use Saved Searches when a ticket stub surface needs Named queries with run and delete. Keep props minimal and prefer composition with sibling stubs.
Avoid Saved Searches for long form flows or dense data grids where a dedicated layout block fits better.
Source code
saved-searches.tsxZero dependencies (only React + utils). Copy and paste directly into your project:
"use client";
import * as React from "react";
import { cn } from "./lib/utils";
export interface SavedSearchesProps extends React.HTMLAttributes<HTMLDivElement> {
items?: { name: string; query: string }[];
onRun?: (query: string) => void;
onDelete?: (name: string) => void;
}
/** Saved searches stub: named query cards with run and delete. */
export function SavedSearches({ items = [{ name: "Friday VIP", query: "tier:vip fri" }, { name: "Cheap seats", query: "price<30" }], onRun, onDelete, className, ...props }: SavedSearchesProps) {
const [list, setList] = React.useState(items);
return (
<div className={cn("w-full max-w-sm rounded-lg border border-border bg-card p-3", className)} {...props}>
<span className="font-mono text-[10px] uppercase tracking-[0.15em] text-muted-foreground">Saved searches</span>
<ul className="mt-2 space-y-1.5">
{list.map((s) => (
<li key={s.name} className="flex items-center gap-2 rounded-md border border-border bg-background px-2.5 py-1.5">
<div className="min-w-0 flex-1">
<p className="truncate font-mono text-xs font-bold text-foreground">{s.name}</p>
<p className="truncate font-mono text-[10px] text-muted-foreground">{s.query}</p>
</div>
<button type="button" onClick={() => onRun?.(s.query)} className="rounded border border-accent/50 px-2 py-0.5 font-mono text-[10px] font-bold uppercase text-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">Run</button>
<button
type="button"
aria-label={`Delete ${s.name}`}
onClick={() => { setList((l) => l.filter((x) => x.name !== s.name)); onDelete?.(s.name); }}
className="rounded px-1 font-mono text-xs text-muted-foreground hover:text-destructive focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
>
×
</button>
</li>
))}
{list.length === 0 && <li className="py-2 text-center font-mono text-[11px] text-muted-foreground">No saved searches</li>}
</ul>
</div>
);
}