๐ŸŽจ

UI Library

A collection of beautiful, reusable React components and CSS snippets built with Tailwind CSS and Framer Motion.

Tabs

Navigation elements used to organize and transition between related views.

Underline Tabs

Settings for account go here.

TabsBasic.tsxLanguage: tsx
import { useState } from 'react'; import { motion } from 'framer-motion'; export function BasicTabs() { const [activeTab, setActiveTab] = useState('account'); const tabs = [ { id: 'account', label: 'Account' }, { id: 'password', label: 'Password' }, { id: 'team', label: 'Team' }, ]; return ( <div className="w-full max-w-md"> <div className="flex space-x-1 border-b border-border"> {tabs.map((tab) => ( <button key={tab.id} onClick={() => setActiveTab(tab.id)} className={`relative px-4 py-2 text-sm font-medium transition-colors ${ activeTab === tab.id ? 'text-foreground' : 'text-muted hover:text-foreground' }`} > {tab.label} {activeTab === tab.id && ( <motion.div layoutId="basicTabIndicator" className="absolute bottom-0 left-0 right-0 h-0.5 bg-accent" transition={{ type: 'spring', bounce: 0.2, duration: 0.6 }} /> )} </button> ))} </div> <div className="p-4 mt-2"> <p className="text-muted text-sm">Content for {activeTab}</p> </div> </div> ); }

Pill Tabs

TabsSegment.tsxLanguage: tsx
import { useState } from 'react'; import { motion } from 'framer-motion'; export function PillTabs() { const [activeTab, setActiveTab] = useState('monthly'); const tabs = [ { id: 'monthly', label: 'Monthly' }, { id: 'annually', label: 'Annually' }, ]; return ( <div className="inline-flex bg-surface border border-border p-1 rounded-xl"> {tabs.map((tab) => ( <button key={tab.id} onClick={() => setActiveTab(tab.id)} className={`relative px-6 py-2 text-sm font-medium rounded-lg transition-colors ${ activeTab === tab.id ? 'text-background' : 'text-muted hover:text-foreground' }`} > {activeTab === tab.id && ( <motion.div layoutId="pillTabIndicator" className="absolute inset-0 bg-accent rounded-lg" transition={{ type: 'spring', bounce: 0.2, duration: 0.6 }} /> )} <span className="relative z-10">{tab.label}</span> </button> ))} </div> ); }

Vertical Navigation

profile Config

Navigate through settings easily.

TabsVertical.tsxLanguage: tsx
import { useState } from 'react'; import { motion } from 'framer-motion'; export function VerticalTabs() { const [activeTab, setActiveTab] = useState('profile'); const tabs = [ { id: 'profile', label: 'Profile Settings' }, { id: 'notifications', label: 'Notifications' }, { id: 'billing', label: 'Billing & Plans' }, { id: 'security', label: 'Security' }, ]; return ( <div className="flex gap-8 w-full max-w-2xl"> <div className="flex flex-col gap-1 w-48 shrink-0"> {tabs.map((tab) => ( <button key={tab.id} onClick={() => setActiveTab(tab.id)} className={`relative px-4 py-2.5 text-sm font-medium rounded-lg transition-colors text-left ${ activeTab === tab.id ? 'text-accent' : 'text-muted hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5' }`} > {activeTab === tab.id && ( <motion.div layoutId="verticalTabIndicator" className="absolute inset-0 bg-accent/10 rounded-lg border border-accent/20" transition={{ type: 'spring', bounce: 0.2, duration: 0.6 }} /> )} <span className="relative z-10">{tab.label}</span> </button> ))} </div> <div className="flex-1 p-6 bg-surface/30 border border-border rounded-2xl"> <h4 className="font-semibold mb-2 capitalize">{activeTab} Details</h4> <p className="text-muted text-sm">Select options from the left sidebar to navigate.</p> </div> </div> ); }

Icons & Badges

TabsIcons.tsxLanguage: tsx
import { useState } from 'react'; import { motion } from 'framer-motion'; export function IconTabs() { const [activeTab, setActiveTab] = useState('overview'); const tabs = [ { id: 'overview', label: 'Overview', icon: <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/></svg> }, { id: 'messages', label: 'Messages', badge: '3', icon: <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" /></svg> }, { id: 'settings', label: 'Settings', icon: <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /></svg> } ]; return ( <div className="flex gap-6 border-b border-border w-max"> {tabs.map((tab) => ( <button key={tab.id} onClick={() => setActiveTab(tab.id)} className={`relative flex items-center gap-2 pb-4 text-sm font-medium transition-colors ${ activeTab === tab.id ? 'text-accent' : 'text-muted hover:text-foreground' }`} > {tab.icon} {tab.label} {tab.badge && ( <span className="ml-0.5 inline-flex items-center justify-center w-4 h-4 text-[10px] font-bold text-white bg-red-500 rounded-full"> {tab.badge} </span> )} {activeTab === tab.id && ( <motion.div layoutId="iconTabIndicator" className="absolute bottom-0 left-0 right-0 h-0.5 bg-accent rounded-t-full" transition={{ type: 'spring', bounce: 0.2, duration: 0.6 }} /> )} </button> ))} </div> ); }