Suggestion Banner
spectrumui/suggestion-bannerFreeBlock
An inline AI suggestion with apply and dismiss.
Install it
npx shadcn@latest add https://ui.spectrumhq.in/r/suggestion-banner.jsonSource
1'use client';23import { useState } from 'react';4import { Check, Sparkles, X } from 'lucide-react';5import { cn } from '@/lib/utils';67const KEYFRAMES = `8@keyframes su-pop { 0% { opacity: 0; transform: scale(0.85) } 100% { opacity: 1; transform: none } }9@keyframes su-msg-in { from { opacity: 0; transform: translateY(4px) } to { opacity: 1; transform: none } }10`;1112export type SuggestionState = 'open' | 'applied' | 'dismissed';1314export type SuggestionBannerVariant = 'Inline' | 'Floating';1516export interface SuggestionBannerProps {17 suggestion?: string;18 detail?: string;19 applyLabel?: string;20 state?: SuggestionState;21 onApply?: () => void;22 onDismiss?: () => void;23 variant?: SuggestionBannerVariant;24 className?: string;25}2627export function SuggestionBanner({28 suggestion = 'Flag Meridian Lines in the weekly carrier report',29 detail = 'Based on the SLA breach found on the Rotterdam–Felixstowe lane.',30 applyLabel = 'Apply',31 state: stateProp,32 onApply,33 onDismiss,34 variant = 'Inline',35 className,36}: SuggestionBannerProps) {37 const [stateState, setStateState] = useState<SuggestionState>('open');38 const state = stateProp !== undefined ? stateProp : stateState;3940 function apply() {41 setStateState('applied');42 onApply?.();43 }44 function dismiss() {45 setStateState('dismissed');46 onDismiss?.();47 }4849 if (state === 'dismissed') return null;5051 if (state === 'applied') {52 return (53 <div54 role="status"55 className={cn(56 'flex w-fit items-center gap-2 rounded-full bg-emerald-500/10 px-3 py-1.5 text-[12.5px] font-medium text-emerald-700 motion-safe:animate-[su-msg-in_240ms_cubic-bezier(0.23,1,0.32,1)_both] dark:text-emerald-400',57 className,58 )}59 >60 <style dangerouslySetInnerHTML={{ __html: KEYFRAMES }} />61 <Check className="size-3.5 motion-safe:animate-[su-pop_200ms_cubic-bezier(0.23,1,0.32,1)_both]" strokeWidth={2.5} />62 Applied — {suggestion.charAt(0).toLowerCase() + suggestion.slice(1)}63 </div>64 );65 }6667 return (68 <div69 className={cn(70 'flex w-full max-w-[480px] items-start gap-2.5 rounded-xl border border-black/[0.08] bg-white py-2.5 pl-3 pr-2 dark:border-white/[0.09] dark:bg-[#0B0B0D]',71 variant === 'Floating' && 'shadow-lg',72 className,73 )}74 >75 <style dangerouslySetInnerHTML={{ __html: KEYFRAMES }} />76 <Sparkles className="mt-0.5 size-3.5 shrink-0 text-neutral-400 dark:text-neutral-500" />7778// … truncated
What it pulls in
npm packages
Files it writes
More from spectrumui
All 182 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Agent Planagent-plan | spectrumui | Blocks | Free | 1 dep | |
| Agent Stepsagent-steps | spectrumui | Blocks | Free | 1 dep · 2 files | |
| Approval Cardapproval-card | spectrumui | Blocks | Free | 1 dep | |
| Chat Empty Statechat-empty-state | spectrumui | Blocks | Free | 1 dep · 2 files | |
| Citation Sourcescitation-sources | spectrumui | Blocks | Free | no deps · 2 files | |
| Code Blockcode-block | spectrumui | Blocks | Free | 1 dep | |
| Conversation Listconversation-list | spectrumui | Blocks | Free | 1 dep | |
| Diff Viewdiff-view | spectrumui | Blocks | Free | 1 dep |
