Move. Then right-click anything here.
Live customization
Preset Themes
Pointer Icon
Colors
Sizes
What's different: the pointer only exists inside the PointerProvider's region, and the menu is this page's own three items. Change a control and both the pointer and the source below update. The right-click circle animation is not shown inside an anyclick region (the pointer package skips it once the event is handled).
'use client';
import { PointerProvider } from '@ewjdev/anyclick-pointer';import { AnyclickProvider } from '@ewjdev/anyclick-react';import { createHttpAdapter } from '@ewjdev/anyclick-github';import { Default } from 'lucide-react';
const adapter = createHttpAdapter({ endpoint: '/api/feedback' });
const theme = { colors: { pointerColor: '#3b82f6', circleColor: 'rgba(59, 130, 246, 0.4)', circleBorderColor: '#3b82f699', }, sizes: { pointerSize: 24, circleSize: 44, circleBorderWidth: 2 }, pointerIcon: ( <Default size={24} strokeWidth={2} fill="rgba(59, 130, 246, 0.3)" stroke="#3b82f6" /> ),};
const menuItems = [ { type: 'issue', label: 'Report pointer glitch', showComment: true }, { type: 'copy-theme', label: 'Copy pointer theme', onClick: () => navigator.clipboard.writeText(JSON.stringify(theme)) }, { type: 'feature', label: 'Send feedback', showComment: true },];
export function Providers({ children }) { return ( <PointerProvider theme={theme}> <AnyclickProvider adapter={adapter} scoped menuItems={menuItems}> {children} </AnyclickProvider> </PointerProvider> );}// This page also calls usePointer().setTheme(theme) when you change a control.Implementation details, API and theme options
What You Get
- Custom themed cursor that follows mouse movement
- Smooth right-click animation with expanding circle
- Press effect when clicking (scaled pointer + faint circle)
- Menu-aware: shows pointer over menus, circle elsewhere when menu open
- High z-index to appear above all UI elements
- Respects prefers-reduced-motion for accessibility
- Direct DOM manipulation for 60fps performance
- Dynamic theme updates via usePointer hook
Implementation
1. Install the Package
npm install @ewjdev/anyclick-pointer# oryarn add @ewjdev/anyclick-pointer2. Basic Setup with PointerProvider
'use client';
import { PointerProvider } from '@ewjdev/anyclick-pointer';
export function Providers({ children }: { children: React.ReactNode }) { return ( <PointerProvider> {children} </PointerProvider> );}3. Wrap Your App
import { Providers } from './providers';
export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body> <Providers>{children}</Providers> </body> </html> );}Custom Theme
Customize colors, sizes, and even replace the pointer icon. Use fill="none" for transparent background or a semi-transparent color for filled:
import { PointerProvider } from '@ewjdev/anyclick-pointer';import { Default } from 'lucide-react';
export function Providers({ children }: { children: React.ReactNode }) { return ( <PointerProvider theme={{ colors: { pointerColor: '#3b82f6', circleColor: 'rgba(59, 130, 246, 0.4)', circleBorderColor: '#3b82f699', }, sizes: { pointerSize: 24, circleSize: 44, circleBorderWidth: 2, }, // fill="none" for transparent, or use rgba for semi-transparent fill pointerIcon: <Default size={24} fill="rgba(59, 130, 246, 0.15)" stroke="#3b82f6" />, }} config={{ visibility: 'always', hideDefaultCursor: true, zIndex: 10001, }} > {children} </PointerProvider> );}Dynamic Theme Updates
Update the pointer theme at runtime using the usePointer hook:
import { usePointer } from '@ewjdev/anyclick-pointer';import { Crosshair } from 'lucide-react';
function ThemeSwitcher() { const { setTheme, setInteractionState } = usePointer();
const applyDarkTheme = () => { setTheme({ colors: { pointerColor: '#8b5cf6', circleColor: 'rgba(139, 92, 246, 0.4)', }, sizes: { pointerSize: 28, circleSize: 50, }, pointerIcon: <Crosshair size={28} fill="white" stroke="#8b5cf6" />, }); };
const triggerCircle = () => { setInteractionState('rightClick'); };
return ( <div> <button onClick={applyDarkTheme}>Apply Dark Theme</button> <button onClick={triggerCircle}>Show Circle</button> </div> );}Integration with AnyclickProvider
Combine with the feedback system for a complete experience:
'use client';
import { AnyclickProvider } from '@ewjdev/anyclick-react';import { PointerProvider } from '@ewjdev/anyclick-pointer';import { createHttpAdapter } from '@ewjdev/anyclick-github';
const adapter = createHttpAdapter({ endpoint: '/api/feedback' });
export function Providers({ children }: { children: React.ReactNode }) { return ( <AnyclickProvider adapter={adapter}> <PointerProvider theme={{ colors: { pointerColor: '#3b82f6', circleColor: 'rgba(59, 130, 246, 0.4)', }, }} config={{ visibility: 'always', hideDefaultCursor: true, }} > {children} </PointerProvider> </AnyclickProvider> );}Configuration Reference
Theme Options
| Property | Default | Description |
|---|---|---|
| colors.pointerColor | currentColor | Pointer icon color |
| colors.circleColor | rgba(59, 130, 246, 0.4) | Circle background |
| sizes.pointerSize | 24 | Pointer icon size (px) |
| sizes.circleSize | 44 | Circle size (px) |
| pointerIcon | MousePointer2 | Custom icon component |
Hook Methods
| Method | Description |
|---|---|
| setTheme(theme) | Update theme colors, sizes, and icon |
| setConfig(config) | Update behavior config |
| setEnabled(bool) | Enable/disable the pointer |
| setInteractionState(state) | Trigger states: 'normal' | 'rightClick' | 'pressing' |
Your changes are live!
The customizations you made above are applied to the actual pointer on this page. Navigate to other pages to see your theme persist, or refresh to reset.
Basic Setup Example