Componenteditors
Webhook List
Webhook list with URL, event chips, test button and remove.
Preview
Live Preview
https://api.example.com/hookorder.created
Installation
Tokens guide →Add to your project via CLI (zero dependencies, code you own):
npx bigbullui add webhook-listOr install the full npm package:
npm install bigbulluiUsage
import { WebhookList } from "@/components/ui/webhook-list";
<WebhookList />Source code
webhook-list.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 Webhook {
id: string;
url: string;
events: string[];
active?: boolean;
}
export interface WebhookListProps extends React.HTMLAttributes<HTMLDivElement> {
webhooks: Webhook[];
onTest?: (id: string) => void;
onRemove?: (id: string) => void;
}
/** Webhook listesi: URL + olay rozetleri + durum + test/kaldır. */
export function WebhookList({ webhooks, onTest, onRemove, className, ...props }: WebhookListProps) {
const [tested, setTested] = React.useState<string | null>(null);
return (
<div className={cn("w-full max-w-lg space-y-2", className)} {...props}>
<style>{`@keyframes whIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }`}</style>
{webhooks.map((w, idx) => (
<div
key={w.id}
className="rounded-md border border-border bg-card p-3 animate-[whIn_0.3s_ease-out_both] motion-reduce:animate-none transition-colors hover:border-foreground/30 motion-reduce:transition-none"
style={{ animationDelay: `${idx * 60}ms` }}
>
<div className="flex items-center gap-2">
<span className={cn("size-1.5 shrink-0 rounded-full", w.active ? "bg-emerald-500 animate-pulse motion-reduce:animate-none" : "bg-border")} aria-hidden="true" />
<code className="min-w-0 flex-1 truncate font-mono text-xs text-foreground">{w.url}</code>
<button
onClick={() => { onTest?.(w.id); setTested(w.id); setTimeout(() => setTested(null), 1500); }}
className="shrink-0 rounded-sm border border-dashed border-border px-2 py-0.5 font-mono text-[9px] uppercase tracking-wider text-muted-foreground transition-colors hover:border-accent hover:text-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring motion-reduce:transition-none"
>
{tested === w.id ? "✓ 200" : "TEST"}
</button>
<button
onClick={() => onRemove?.(w.id)}
className="shrink-0 rounded-sm p-1 text-muted-foreground transition-colors hover:text-destructive focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring motion-reduce:transition-none"
aria-label={`${w.url} webhookunu kaldır`}
>
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true"><path d="M18 6L6 18M6 6l12 12" /></svg>
</button>
</div>
<div className="mt-2 flex flex-wrap gap-1">
{w.events.map((ev) => (
<span key={ev} className="rounded-full border border-border bg-secondary px-1.5 py-px font-mono text-[9px] text-secondary-foreground">{ev}</span>
))}
</div>
</div>
))}
{webhooks.length === 0 && (
<p className="rounded-md border border-dashed border-border p-4 text-center text-sm text-muted-foreground">Henüz webhook yok.</p>
)}
</div>
);
}
Props
| Prop | Type | Description |
|---|---|---|
| webhooks | Webhook[] | |
| onTest | (id: string) => void | |
| onRemove | (id: string) => void |