circle-menu
obsidianui/circle-menuFreeComponent
obsidianui publishes no description for this item.
Live preview
live · rendered by the registry
Rendered by obsidianui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://obsidianui.dev/r/circle-menu.jsonSource
1'use client';23import { AnimatePresence, motion, useAnimationControls } from 'framer-motion';4import { Menu, X } from 'lucide-react';5import React, { useState } from 'react';6import { cn } from '@/lib/utils';78const CONSTANTS = {9 itemSize: 48,10 containerSize: 250,11 openStagger: 0.02,12 closeStagger: 0.0713};1415const STYLES: Record<string, Record<string, string>> = {16 trigger: {17 container:18 'rounded-full flex items-center bg-[#27272A] justify-center border border-white/10 cursor-pointer outline-none ring-0 hover:brightness-125 transition-all duration-100 z-50',19 active: 'bg-[#27272A]'20 },21 item: {22 container:23 'rounded-full flex items-center justify-center absolute bg-zinc-100 text-black hover:bg-white cursor-pointer',24 label: 'text-xs text-black absolute top-full left-1/2 -translate-x-1/2 text-white mt-1'25 }26};2728const pointOnCircle = (i: number, n: number, r: number, cx = 0, cy = 0) => {29 const theta = (2 * Math.PI * i) / n - Math.PI / 2;30 const x = cx + r * Math.cos(theta);31 const y = cy + r * Math.sin(theta) + 0;32 return { x, y };33};3435interface MenuItemProps {36 icon: React.ReactNode;37 label: string;38 onClick?: () => void;39 index: number;40 totalItems: number;41 isOpen: boolean;42}4344const MenuItem = ({ icon, label, onClick, index, totalItems, isOpen }: MenuItemProps) => {45 const { x, y } = pointOnCircle(index, totalItems, CONSTANTS.containerSize / 2);46 const [hovering, setHovering] = useState(false);4748 return (49 <motion.button50 onClick={onClick}51 animate={{52 x: isOpen ? x : 0,53 y: isOpen ? y : 054 }}55 whileHover={{56 scale: 1.1,57 transition: {58 duration: 0.1,59 delay: 060 }61 }}62 transition={{63 delay: isOpen ? index * CONSTANTS.openStagger : index * CONSTANTS.closeStagger,64 type: 'spring',65 stiffness: 300,66 damping: 3067 }}68 style={{69 height: CONSTANTS.itemSize - 2,70 width: CONSTANTS.itemSize - 271 }}72 className={STYLES.item.container}73 onMouseEnter={() => setHovering(true)}74 onMouseLeave={() => setHovering(false)}75 >76 {icon}77 {hovering && <p className={STYLES.item.label}>{label}</p>}78// … truncated
What it pulls in
npm packages
Files it writes
More from obsidianui
All 111 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| ai-inputai-input | obsidianui | Components | Free | 2 deps | |
| alertalert | obsidianui | Components | Free | no deps | |
| animated-tab-baranimated-tab-bar | obsidianui | Components | Free | no deps | |
| apple-spotlightapple-spotlight | obsidianui | Components | Free | 2 deps | |
| avataravatar | obsidianui | Components | Free | 1 dep | |
| badgebadge | obsidianui | Components | Free | 1 dep | |
| breadcrumbbreadcrumb | obsidianui | Components | Free | 2 deps | |
| buttonbutton | obsidianui | Components | Free | 1 dep |
