A modern, smooth trailing cursor effect that enhances user experience with elegant visual feedback and interactivity.
- Dot Cursor: Small, solid dot that immediately tracks the user's exact cursor position
- Trailing Circle: Larger, semi-transparent circle that follows with smooth interpolation
- Interactive Hover States: Dynamic scaling and color changes when hovering over interactive elements
- Performance Optimized: Lightweight JavaScript with efficient animations
- Mobile Responsive: Automatically disables on mobile and touch devices
- Accessibility Compliant: Respects reduced motion preferences and maintains keyboard navigation
- Color Customization: Multiple color themes and presets
- Real-time Controls: Live settings panel for instant customization
- Smart Detection: Automatically detects interactive elements
- Smooth Easing: Cubic-bezier transitions for professional feel
- Memory Efficient: Optimized animation loops with smart frame skipping
components/
βββ cursor-provider.tsx # Global cursor context and provider
βββ cursor-settings.tsx # Settings panel with live controls
βββ ui/
β βββ trailing-cursor.tsx # Main cursor component
β βββ interactive.tsx # Utility component for interactive elements
hooks/
βββ use-trailing-cursor.ts # Custom hook for cursor logic
types/
βββ cursor.ts # TypeScript type definitions
- Manages global cursor state
- Provides context for cursor customization
- Handles user preferences (reduced motion)
- Wraps the entire application
- Renders the dot and trail elements
- Handles position updates and animations
- Manages hover state detection
- Optimizes performance with RAF
- Encapsulates cursor logic
- Manages event listeners
- Handles mobile detection
- Provides smooth animation loop
The cursor supports multiple color themes:
- Ocean Blue:
rgb(59, 130, 246)withrgba(59, 130, 246, 0.3)trail - Sunset Gold:
rgb(245, 158, 11)withrgba(245, 158, 11, 0.3)trail - Forest Green:
rgb(16, 185, 129)withrgba(16, 185, 129, 0.3)trail - Royal Purple:
rgb(124, 58, 237)withrgba(124, 58, 237, 0.3)trail - Rose Pink:
rgb(244, 63, 94)withrgba(244, 63, 94, 0.3)trail - Cyber Cyan:
rgb(6, 182, 212)withrgba(6, 182, 212, 0.3)trail
interface CursorConfig {
dotColor: string; // Color of the dot cursor
trailColor: string; // Color of the trailing circle
dotSize: number; // Size of the dot (default: 8px)
trailSize: number; // Size of the trail (default: 32px)
trailSpeed: number; // Animation speed (default: 0.15)
hoverScale: number; // Scale factor on hover (default: 1.5)
disabled: boolean; // Enable/disable the effect
}- RequestAnimationFrame: Uses RAF for smooth 60fps animations
- Smart Frame Skipping: Only animates when there's significant movement
- GPU Acceleration: Uses
translate3dandbackface-visibility: hidden - Optimized Easing: Efficient interpolation calculations
- Event Listener Cleanup: Proper cleanup on component unmount
- Animation Cancellation: Cancels RAF when not needed
- Passive Event Listeners: Uses passive listeners for better performance
- Touch Detection: Multiple methods to detect touch devices
- Screen Size Detection: Disables on screens smaller than 768px
- User Agent Detection: Fallback detection for mobile browsers
- Automatic Disable: No performance impact on mobile devices
@media (prefers-reduced-motion: reduce) {
.cursor-dot,
.cursor-trail {
transition: none;
animation: none;
}
}@media (prefers-contrast: high) {
.cursor-dot {
mix-blend-mode: normal;
background-color: #000 !important;
}
}- Enhanced focus styles with visible outlines
- Cursor doesn't interfere with keyboard navigation
- Screen reader compatibility maintained
The cursor automatically detects and responds to:
<a>links<button>elements<input>,<textarea>,<select>form elements- Elements with
role="button" - Elements with
tabindexattribute - Elements with
.cursor-pointerclass - Elements with
[data-interactive]attribute
import { Interactive } from "@/components/ui/interactive";
<Interactive
as="div"
cursorScale={1.3}
cursorColor="purple"
className="my-interactive-element"
>
Custom interactive content
</Interactive>- Mix Blend Mode: Uses
mix-blend-mode: differencefor the dot - Z-Index Management: Proper layering with z-index 9998-9999
- Pointer Events:
pointer-events: noneto prevent interference - Will Change: Optimizes for transform animations
- Debounced Resize: Efficient window resize handling
- Memoized Callbacks: Uses
useCallbackfor stable references - Ref-based State: Uses refs for high-frequency updates
- Conditional Rendering: Only renders when necessary
import { CursorProvider } from "@/components/cursor-provider";
function App() {
return (
<CursorProvider>
<YourAppContent />
</CursorProvider>
);
}<CursorProvider
defaultEnabled={true}
defaultDotColor="rgb(245, 158, 11)"
defaultTrailColor="rgba(245, 158, 11, 0.3)"
>
<YourAppContent />
</CursorProvider>import { CursorSettings } from "@/components/cursor-settings";
function Layout() {
return (
<div>
<YourContent />
<CursorSettings />
</div>
);
}-
Cursor not appearing
- Check if device is mobile (automatically disabled)
- Verify
CursorProvideris wrapping your app - Check if reduced motion is enabled
-
Performance issues
- Ensure proper cleanup of event listeners
- Check for memory leaks in animation loops
- Verify GPU acceleration is working
-
Hover detection not working
- Add
data-interactiveattribute to custom elements - Check CSS pointer-events settings
- Verify element is not covered by other elements
- Add
Enable debug logging by setting:
const DEBUG_CURSOR = process.env.NODE_ENV === 'development';- Chrome: Full support
- Firefox: Full support
- Safari: Full support
- Edge: Full support
- Mobile browsers: Automatically disabled
- Use sparingly: Don't overuse hover effects
- Test on mobile: Ensure graceful degradation
- Consider accessibility: Always provide alternatives
- Monitor performance: Check frame rates on lower-end devices
- Customize thoughtfully: Choose colors that complement your design
This implementation is part of the DocMagic project and follows the same licensing terms.