Ai Sources
smoothui-registry/ai-sourcesFreeComponent
Favicon stack that fans out on hover and expands into a source list, with each favicon morphing into its row.
Install it
npx shadcn@latest add https://www.smoothui.dev/r/ai-sources.jsonSource
1"use client";23import { cn } from "@/lib/utils";4import { ChevronRight, Globe } from "lucide-react";5import { AnimatePresence, motion, useReducedMotion } from "motion/react";6import { type ReactNode, useId, useState } from "react";78const SPRING_DEFAULT = {9 bounce: 0.1,10 duration: 0.25,11 type: "spring" as const,12};13const EASE_OUT = [0.23, 1, 0.32, 1] as const;14/** Favicons shown in the collapsed stack before the "+n" chip. */15const STACK_LIMIT = 3;16/** Overlap of the collapsed stack, and how far it fans on hover. */17const STACK_OVERLAP_PX = 8;18const FAN_GAP_PX = 3;19const ROW_STAGGER = 0.035;2021export type AISource = {22 /**23 * The source's mark — a real isotype or an `<img>`, never a letter.24 *25 * A node rather than a URL so a brand's own SVG can be passed straight in.26 * When omitted the component draws a neutral globe: an honest "unknown host"27 * icon beats a fabricated one-letter badge pretending to be a logo.28 */29 favicon?: ReactNode;30 id: string;31 /** Short excerpt or description. */32 snippet?: string;33 title: string;34 url: string;35};3637export type AISourcesProps = {38 className?: string;39 /** Start expanded. */40 defaultOpen?: boolean;41 /** Label before the stack, e.g. "Sources". */42 label?: string;43 sources: AISource[];44};4546const hostOf = (url: string): string => {47 try {48 return new URL(url).hostname.replace(/^www\./, "");49 } catch {50 return url;51 }52};5354const Favicon = ({ size, source }: { size: number; source: AISource }) => (55 <span56 className="flex items-center justify-center overflow-hidden rounded-full border border-border bg-background text-muted-foreground"57 style={{ height: size, width: size }}58 >59 {source.favicon ? (60 // Sized here so any mark fits: an `<img>` from a logo service, or a repo61 // isotype SVG, which ships as `fill="none"` and expects the host to pick62 // the colour — the same contract the logo-cloud blocks rely on.63 <span className="flex size-full items-center justify-center *:size-full *:fill-foreground *:object-cover">64 {source.favicon}65 </span>66 ) : (67 <Globe aria-hidden="true" size={size * 0.6} />68 )}69 </span>70);7172/**73 * The sources behind an answer.74 *75 * Collapsed to a stack of overlapping favicons, because provenance should be76 * available rather than loud. Hovering fans the stack apart as a hint that it is77 * a set and not a single badge; opening it moves each favicon into its own row —78// … truncated
What it pulls in
npm packages
Files it writes
More from SmoothUI Registry
All 178 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Agent Avataragent-avatar | SmoothUI Registry | Components | Free | no deps | |
| Ai Approvalai-approval | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Artifactai-artifact | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Branchai-branch | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Citationai-citation | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Context Meterai-context-meter | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Conversationai-conversation | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Coreai-core | SmoothUI Registry | Components | Free | 1 dep |
