<dialog id="modal"> <p>Modal content</p> <button onclick="modal.close()">Close</button> </dialog> <button onclick="modal.showModal()">Open Modal</button>
// Modal.jsx import { useState, useEffect, useRef, useCallback } from 'react'; import { createPortal } from 'react-dom'; import { motion, AnimatePresence } from 'framer-motion'; const Modal = ({ isOpen, onClose, children }) => { const [isMounted, setIsMounted] = useState(false); const modalRef = useRef(null); const handleEscape = useCallback((e) => { if (e.key === 'Escape') onClose(); }, [onClose]); useEffect(() => { setIsMounted(true); document.addEventListener('keydown', handleEscape); return () => document.removeEventListener('keydown', handleEscape); }, [handleEscape]); if (!isMounted) return null; return createPortal( <AnimatePresence> {isOpen && ( <motion.div className="modal-overlay" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} onClick={onClose} > <motion.div ref={modalRef} initial={{ scale: 0.8 }} animate={{ scale: 1 }} exit={{ scale: 0.8 }} onClick={(e) => e.stopPropagation()} > {children} </motion.div> </motion.div> )} </AnimatePresence>, document.body ); };
<button onclick="document.documentElement.classList.toggle('dark')"> Toggle Dark Mode </button>
// ThemeProvider.jsx import { createContext, useContext, useState, useEffect } from 'react'; const ThemeContext = createContext(); export const useTheme = () => { const context = useContext(ThemeContext); if (!context) throw new Error('useTheme must be used within ThemeProvider'); return context; }; export const ThemeProvider = ({ children }) => { const [theme, setTheme] = useState(() => localStorage.getItem('theme') || 'light' ); useEffect(() => { document.documentElement.setAttribute('data-theme', theme); localStorage.setItem('theme', theme); }, [theme]); const toggleTheme = () => setTheme(prev => prev === 'light' ? 'dark' : 'light'); return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); }; // DarkModeToggle.jsx import { useTheme } from './ThemeProvider'; const DarkModeToggle = () => { const { theme, toggleTheme } = useTheme(); return <button onClick={toggleTheme}>{theme}</button>; };
<form> <input type="email" required> <input type="password" minlength="8" required> <button type="submit">Login</button> </form>
import { useState, useEffect } from 'react'; import { useForm } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import * as yup from 'yup'; const schema = yup.object({ email: yup.string().email().required(), password: yup.string().min(8).required() }); const LoginForm = () => { const { register, handleSubmit, formState: { errors } } = useForm({ resolver: yupResolver(schema) }); const onSubmit = (data) => console.log(data); return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...register('email')} /> {errors.email && <span>{errors.email.message}</span>} <input {...register('password')} type="password" /> {errors.password && <span>{errors.password.message}</span>} <button type="submit">Login</button> </form> ); };
<details> <summary>Click to expand</summary> <p>Hidden content appears here</p> </details>
import { useState } from 'react'; const Accordion = ({ items }) => { const [openItems, setOpenItems] = useState(new Set()); const toggleItem = (index) => { setOpenItems(prev => { const newSet = new Set(prev); if (newSet.has(index)) newSet.delete(index); else newSet.add(index); return newSet; }); }; return ( <div> {items.map((item, index) => ( <div key={index}> <button onClick={() => toggleItem(index)}> {item.title} </button> {openItems.has(index) && <div>{item.content}</div>} </div> ))} </div> ); };
This is native HTML. No JavaScript needed.