<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.