Scoped & Nested Providers
Control feedback capture at a granular level with scoped providers and nested theming. Perfect for complex applications with different feedback requirements per section.
Try It
Right-click elements in different sections to see how scoped providers work. Notice the different highlight colors and behavior:
This area uses the global provider with default blue highlights and blue pointer. Right-click to see the blue highlight color.
This section has nested providers with custom rose-colored highlights AND rose pointer. Right-click to see the rose/pink colors and custom menu items!
Each section can have completely different theming, menu options, and pointer colors. This one uses emerald/cyan colors.
This section demonstrates a fully custom-styled context menu with glassmorphism effect, custom border radius, and emoji icons. Right-click to see the custom menu design!
Both feedback AND custom pointer are disabled in this section. Right-click shows the native browser menu, and you see the default cursor.
AnyclickProvider AND PointerProvider, demonstrating different highlight colors, menu items, pointer themes, custom menu styling, and disabled states.Use Cases
- Different feedback configurations per page section
- Custom theming for specific components (colors, styles)
- Disable feedback in sensitive areas (forms, payments)
- Separate adapters for different feedback destinations
- Role-based feedback with different menu items per section
Implementation
1. Basic Scoped Provider
Use the scoped prop to limit feedback capture to a specific section:
'use client';
import { AnyclickProvider } from '@ewjdev/anyclick-react';
export function Dashboard({ children }) { return ( <AnyclickProvider adapter={dashboardAdapter} scoped // Only captures events within this provider's children menuItems={dashboardMenuItems} > {children} </AnyclickProvider> );}2. Nested Theming
Child providers inherit and can override parent themes:
'use client';
import { AnyclickProvider } from '@ewjdev/anyclick-react';
export function Providers({ children }) { return ( // Root provider with blue highlights <AnyclickProvider adapter={adapter} theme={{ highlightConfig: { colors: { targetColor: '#3b82f6', // Blue containerColor: '#8b5cf6', // Purple } } }} > <Header /> <main>{children}</main> {/* Nested provider with custom rose theme */} <AnyclickProvider scoped theme={{ highlightConfig: { colors: { targetColor: '#f43f5e', // Rose containerColor: '#ec4899', // Pink } } }} > <SpecialSection /> </AnyclickProvider> <Footer /> </AnyclickProvider> );}3. Scoped Pointer Theming
To have different pointer (cursor) themes per section, wrap with both AnyclickProvider and PointerProvider:
'use client';
import { AnyclickProvider } from '@ewjdev/anyclick-react';import { PointerProvider } from '@ewjdev/anyclick-pointer';import { MousePointer2 } from 'lucide-react';
export function RoseSection({ children }) { return ( <AnyclickProvider scoped theme={{ highlightConfig: { colors: { targetColor: '#f43f5e', // Rose highlights containerColor: '#ec4899', } } }} > <PointerProvider theme={{ colors: { pointerColor: '#f43f5e', // Rose pointer circleColor: 'rgba(244, 63, 94, 0.4)', }, pointerIcon: ( <MousePointer2 size={24} fill="rgba(244, 63, 94, 0.3)" stroke="#f43f5e" /> ), }} config={{ visibility: 'always', hideDefaultCursor: true }} > {children} </PointerProvider> </AnyclickProvider> );}4. Disabling Feedback & Pointer
Disable both feedback and custom pointer for sensitive areas:
'use client';
import { AnyclickProvider } from '@ewjdev/anyclick-react';import { PointerProvider } from '@ewjdev/anyclick-pointer';
export function PaymentForm({ children }) { return ( // Disable feedback <AnyclickProvider scoped theme={{ disabled: true }}> {/* Disable custom pointer, show default cursor */} <PointerProvider config={{ visibility: 'never', hideDefaultCursor: false }}> <form> <input type="text" placeholder="Card Number" /> <input type="text" placeholder="CVV" /> <button type="submit">Pay Now</button> </form> </PointerProvider> </AnyclickProvider> );}5. Different Adapters Per Section
Route feedback to different destinations based on the section:
'use client';
import { AnyclickProvider } from '@ewjdev/anyclick-react';import { createHttpAdapter } from '@ewjdev/anyclick-github';
// Main app feedback goes to GitHubconst githubAdapter = createHttpAdapter({ endpoint: '/api/feedback/github',});
// Dashboard feedback goes to internal toolconst internalAdapter = createHttpAdapter({ endpoint: '/api/feedback/internal',});
export function Providers({ children }) { return ( <AnyclickProvider adapter={githubAdapter}> <Header /> {/* Dashboard uses different adapter */} <AnyclickProvider adapter={internalAdapter} scoped menuItems={internalMenuItems} > <Dashboard /> </AnyclickProvider> <Footer /> </AnyclickProvider> );}Theme Configuration
The AnyclickTheme interface:
interface AnyclickTheme { // Custom styles for the context menu menuStyle?: CSSProperties; // Custom class name for the context menu menuClassName?: string; // Highlight configuration highlightConfig?: { enabled?: boolean; colors?: { targetColor?: string; containerColor?: string; targetShadowOpacity?: number; containerShadowOpacity?: number; }; containerSelectors?: string[]; }; // Screenshot configuration screenshotConfig?: ScreenshotConfig; // Disable anyclick in this subtree disabled?: boolean;}useAnyclick Hook
Access the current provider context, including the merged theme:
import { useAnyclick } from '@ewjdev/anyclick-react';
function MyComponent() { const { isEnabled, // Whether feedback is enabled isSubmitting, // Whether submission is in progress theme, // Merged theme (includes parent themes) scoped, // Whether this provider is scoped providerId, // Unique ID for this provider openMenu, // Open menu programmatically closeMenu, // Close menu submitFeedback, // Submit feedback programmatically } = useAnyclick(); return ( <div> <p>Feedback enabled: {isEnabled ? 'Yes' : 'No'}</p> <p>Current highlight color: {theme.highlightConfig?.colors?.targetColor}</p> </div> );}Event Handling
When nested providers exist, events bubble from the nearest provider to the outermost. The nearest non-disabled provider handles the event:
<AnyclickProvider adapter={a1}> ← Handles if inner is disabled
<AnyclickProvider scoped adapter={a2}> ← Handles first (nearest)
<Button /> ← Right-click here
</AnyclickProvider>
</AnyclickProvider>Explore More
Learn about other advanced features like custom pointers and sensitive data masking.