segmented-button
jolyui-ui/segmented-buttonFreeComponent
jolyui/ui publishes no description for this item.
Live preview
live · rendered by the registry
Rendered by jolyui/ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://jolyui.dev/r/segmented-button.jsonSource
1"use client";23import { motion } from "motion/react";4import { useEffect, useRef, useState } from "react";56interface SegmentedButtonItem {7 id: string;8 label?: string | null;9 isLogo?: boolean;10}1112interface SegmentedButtonProps {13 buttons: SegmentedButtonItem[];14 defaultActive?: string;15 onChange?: (activeId: string) => void;16 className?: string;17}1819export default function SegmentedButton({20 buttons,21 defaultActive,22 onChange,23 className = "",24}: SegmentedButtonProps) {25 const [activeButton, setActiveButton] = useState(26 defaultActive || buttons[0]?.id || "",27 );28 const [indicatorStyle, setIndicatorStyle] = useState({ left: 0, width: 0 });29 const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);30 const [hoverStyle, setHoverStyle] = useState({ left: 0, width: 0 });31 const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]);32 const containerRef = useRef<HTMLDivElement>(null);3334 useEffect(() => {35 const activeIndex = buttons.findIndex((btn) => btn.id === activeButton);36 const activeElement = buttonRefs.current[activeIndex];3738 if (activeElement) {39 setIndicatorStyle({40 left: activeElement.offsetLeft,41 width: activeElement.offsetWidth,42 });43 }44 }, [activeButton, buttons]);4546 useEffect(() => {47 if (hoveredIndex !== null) {48 const hoveredElement = buttonRefs.current[hoveredIndex];49 if (hoveredElement) {50 setHoverStyle({51 left: hoveredElement.offsetLeft,52 width: hoveredElement.offsetWidth,53 });54 }55 } else {56 if (containerRef.current) {57 setHoverStyle({58 left: 0,59 width: containerRef.current.offsetWidth,60 });61 }62 }63 }, [hoveredIndex]);6465 useEffect(() => {66 if (containerRef.current) {67 setHoverStyle({68 left: 0,69 width: containerRef.current.offsetWidth,70 });71 }72 }, []);7374 const handleButtonClick = (buttonId: string) => {75 setActiveButton(buttonId);76 onChange?.(buttonId);77 };7879 return (80 <div81 ref={containerRef}82 className={`relative inline-flex items-center justify-start rounded-full ${className}`}83 onMouseLeave={() => setHoveredIndex(null)}84 role="group"85 >86 <motion.div87 className="absolute top-0 h-7 rounded-full bg-black/10 dark:bg-white/15"88 animate={{89 left: hoverStyle.left,90 width: hoverStyle.width,91 }}92 transition={{93 type: "spring",94 stiffness: 400,95// … truncated
What it pulls in
npm packages
Files it writes
More from jolyui/ui
All 199 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| ai-prompt-boxai-prompt-box | jolyui/ui | Components | Free | 4 deps | |
| animated-beamanimated-beam | jolyui/ui | Components | Free | 1 dep | |
| animated-tableanimated-table | jolyui/ui | Components | Free | 2 deps | |
| animated-theme-toggleanimated-theme-toggle | jolyui/ui | Components | Free | 2 deps | |
| animated-toastanimated-toast | jolyui/ui | Components | Free | 2 deps | |
| animated-tooltipanimated-tooltip | jolyui/ui | Components | Free | 1 dep | |
| bento-gridbento-grid | jolyui/ui | Components | Free | no deps | |
| buttonbutton | jolyui/ui | Components | Free | 3 deps |
