Thinking Steps
fluid-functionalism/thinking-stepsFreeComponent
Collapsible AI reasoning steps with animated expand/collapse, per-step icons, sources, and nested details. Radix flavor.
Install it
npx shadcn@latest add https://fluidfunctionalism.com/r/thinking-steps.jsonSource
1"use client";23import {4 useState,5 useEffect,6 useLayoutEffect,7 useRef,8 useCallback,9 useContext,10 createContext,11 forwardRef,12 type ReactNode,13 type HTMLAttributes,14} from "react";15import { motion, AnimatePresence } from "framer-motion";16import * as Collapsible from "@radix-ui/react-collapsible";1718// SSR-safe layout effect (client components still server-render in Next).19const useIsoLayoutEffect =20 typeof window !== "undefined" ? useLayoutEffect : useEffect;21import { cn } from "@/lib/utils";22import { useIcon } from "@/lib/icon-context";23import type { IconName } from "@/lib/icon-context";24import { spring } from "@/lib/springs";25import { fontWeights } from "@/lib/font-weight";26import { useShape } from "@/lib/shape-context";27import { Badge } from "@/registry/default/badge";28import type { BadgeColor } from "@/registry/default/badge";2930// ─── Shared collapsible parts ───────────────────────────────────────────────31//32// ThinkingSteps and ThinkingStepDetails are both single collapsible sections,33// built directly on Radix's Collapsible (Root/Trigger/Content) with the34// library's framer-motion springs layered on top.3536/** Open state of the nearest ThinkingSteps root, for the header trigger/panel. */37const ThinkingStepsOpenContext = createContext(false);3839interface TriggerRowProps extends HTMLAttributes<HTMLButtonElement> {40 open: boolean;41 children: ReactNode;42}4344/**45 * Trigger row: hover background, dual-layer variable-weight label, and a46 * chevron that rotates from right (closed) to down (open). Mirrors the47 * library's accordion trigger styling.48 */49const TriggerRow = forwardRef<HTMLButtonElement, TriggerRowProps>(50 ({ open, children, className, ...props }, ref) => {51 const ChevronRight = useIcon("chevron-right");52 const shape = useShape();53 const [isHovered, setIsHovered] = useState(false);54 const highlighted = open || isHovered;5556 return (57 <div58 className="relative w-fit"59 onMouseEnter={() => setIsHovered(true)}60 onMouseLeave={() => setIsHovered(false)}61 >62 <AnimatePresence>63 {isHovered && (64 <motion.div65 className={`absolute inset-0 ${shape.bg} bg-hover pointer-events-none`}66 initial={{ opacity: 0 }}67 animate={{ opacity: 1 }}68 exit={{ opacity: 0, transition: spring.fast.exit }}69// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from fluid-functionalism
All 53 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | fluid-functionalism | Components | Free | 3 deps | |
| Accordion (Base UI)accordion-base | fluid-functionalism | Components | Free | 3 deps | |
| Ask User Questionsask-user-questions | fluid-functionalism | Components | Free | 2 deps | |
| Badgebadge | fluid-functionalism | Components | Free | 1 dep | |
| Buttonbutton | fluid-functionalism | Components | Free | 4 deps | |
| Button (Base UI)button-base | fluid-functionalism | Components | Free | 4 deps | |
| Cardcard | fluid-functionalism | Components | Free | 1 dep | |
| Chat Messagechat-message | fluid-functionalism | Components | Free | 1 dep |
