HTML 77.2%
TypeScript 10.5%
Python 9.6%
JavaScript 2.5%
1'use client';2import { Star } from 'lucide-react';3import { cn } from '@/lib/cn';4import { toWatchItem, useWatchlist, WATCH_MAX } from '@/lib/watchlist';56/**7 * Star toggle that adds/removes an entity from the local watchlist (`lib/watchlist.ts`). `aria-pressed` reflects the8 * state; renders a neutral placeholder before hydration so server and client markup match. Sits next to `CompareButton`.9 */10export function WatchButton({ e, size = 'md', className, label = 'Watch' }: { e: { slug: string; name: string; entity_type: string; organization?: { name: string } | string | null }; size?: 'sm' | 'md'; className?: string; label?: string }) {11 const wl = useWatchlist();12 const item = toWatchItem(e);13 const on = wl.ready && wl.has(item.slug);14 const full = wl.ready && wl.full && !on;15 return (16 <button17 type="button"18 onClick={() => {19 if (full) return;20 wl.toggle(item);21 }}22 aria-pressed={on}23 disabled={full}24 title={on ? 'Remove from watchlist' : full ? `The watchlist holds at most ${WATCH_MAX} entities` : 'Add to watchlist (stored in this browser)'}25 data-watch-button26 className={cn(27 'inline-flex shrink-0 items-center gap-1 border text-xs font-medium whitespace-nowrap transition-colors disabled:cursor-not-allowed disabled:opacity-40',28 size === 'sm' ? 'h-7 px-1.5' : 'h-9 px-2.5 text-sm',29 on ? 'border-accent-2 bg-accent-2-soft text-accent-2' : 'border-rule text-ink-2 hover:border-rule-strong hover:text-ink',30 className,31 )}32 >33 <Star className={cn(size === 'sm' ? 'size-3' : 'size-3.5', on && 'fill-current')} aria-hidden />34 <span>{on ? 'Watching' : label}</span>35 </button>36 );37}38