🎨

UI Knihovna

Kolekce nádherných, znovupoužitelných React komponent a CSS fragmentů vytvořená pomocí Tailwind CSS a Framer Motion.

Tlačítka

Interaktivní a přístupné komponenty tlačítek s různými stavy a styly.

Primární tlačítko

ButtonPrimary.tsxLanguage: tsx
import { motion } from 'framer-motion'; export function PrimaryButton() { return ( <motion.button whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} className="px-6 py-3 rounded-xl bg-button text-background font-semibold hover:bg-button-hover transition-colors duration-300" > Click Me </motion.button> ); }

Sekundární tlačítko

ButtonSecondary.tsxLanguage: tsx
import { motion } from 'framer-motion'; export function SecondaryButton() { return ( <motion.button whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} className="px-6 py-3 rounded-xl border border-border bg-surface hover:bg-black/5 dark:hover:bg-white/5 text-foreground font-medium transition-colors duration-300" > Secondary Action </motion.button> ); }

Loading State

ButtonLoading.tsxLanguage: tsx
import { motion } from 'framer-motion'; import { useState } from 'react'; export function LoadingButton() { const [isLoading, setIsLoading] = useState(false); const handleClick = () => { setIsLoading(true); setTimeout(() => setIsLoading(false), 2000); }; return ( <motion.button onClick={handleClick} disabled={isLoading} whileHover={{ scale: isLoading ? 1 : 1.02 }} whileTap={{ scale: isLoading ? 1 : 0.98 }} className="relative flex items-center justify-center px-6 py-3 min-w-[140px] rounded-xl bg-button text-white font-semibold disabled:opacity-80 transition-all duration-300" > {isLoading ? ( <svg className="w-5 h-5 animate-spin" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle> <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> </svg> ) : ( "Submit" )} </motion.button> ); }

Gradient & Glow Effect

ButtonGradient.tsxLanguage: tsx
import { motion } from 'framer-motion'; export function GradientButton() { return ( <div className="relative group"> <div className="absolute -inset-0.5 bg-gradient-to-r from-accent to-purple-600 rounded-xl blur opacity-30 group-hover:opacity-100 transition duration-500 group-hover:duration-200" /> <motion.button whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} className="relative px-6 py-3 bg-surface border border-border rounded-xl font-bold flex items-center gap-2 hover:bg-black/5 dark:hover:bg-white/5 transition-colors" > <span className="bg-gradient-to-r from-accent to-purple-500 bg-clip-text text-transparent"> Gradient Glow </span> <svg className="w-5 h-5 text-purple-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" /></svg> </motion.button> </div> ); }

Icon-only Variants

ButtonIcon.tsxLanguage: tsx
import { motion } from 'framer-motion'; export function IconOnlyButton() { return ( <div className="flex gap-4"> {/* Primary Icon */} <motion.button whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }} className="p-3 rounded-full bg-button text-white shadow-lg shadow-accent/20 hover:bg-button-hover transition-colors" aria-label="Add new" > <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" /></svg> </motion.button> {/* Surface Icon */} <motion.button whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }} className="p-3 rounded-xl border border-border bg-surface text-foreground hover:bg-black/5 dark:hover:bg-white/5 transition-colors" aria-label="Settings" > <svg className="w-6 h-6" 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.37... (truncated visually)" /><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /></svg> </motion.button> </div> ); }

Neaktivní stav

ButtonDisabled.tsxLanguage: tsx
export function DisabledButton() { return ( <button disabled className="px-6 py-3 rounded-xl bg-surface text-muted cursor-not-allowed border border-border opacity-60" > Not Allowed </button> ); }