CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-aria--utils

Essential utility functions and React hooks for building accessible React Aria UI components

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

links-and-navigation.mddocs/

Links & Navigation

Client-side routing integration, synthetic link handling, and programmatic navigation utilities for React applications.

Capabilities

Router Integration

Components and hooks for integrating with client-side routing systems.

/**
 * Provides client-side navigation context to nested components
 * @param props - Router configuration
 * @returns JSX element providing router context
 */
function RouterProvider(props: {
  navigate: (path: string) => void;
  useHref?: (href: string) => string;
  children: ReactNode;
}): JSX.Element;

/**
 * Accesses router context for navigation
 * @returns Router object with navigation methods
 */
function useRouter(): Router;

interface Router {
  /** Whether native browser navigation should be used */
  isNative: boolean;
  /** Open link with modifier key handling */
  open: (target: HTMLAnchorElement, modifiers: Modifiers, setOpening?: boolean) => void;
  /** Transform href for routing system */
  useHref?: (href: string) => string;
}

Usage Examples:

import { RouterProvider, useRouter } from "@react-aria/utils";

// App-level router setup
function App() {
  const navigate = (path: string) => {
    // Your router's navigation function
    history.push(path);
  };
  
  const useHref = (href: string) => {
    // Transform href for your routing system
    return `/app${href}`;
  };
  
  return (
    <RouterProvider navigate={navigate} useHref={useHref}>
      <MainContent />
    </RouterProvider>
  );
}

// Using router in components
function NavigationComponent() {
  const router = useRouter();
  
  const handleLinkClick = (href: string, modifiers: Modifiers) => {
    if (router.isNative) {
      // Use browser navigation
      window.location.href = href;
    } else {
      // Use client-side navigation
      router.open(document.createElement('a'), modifiers);
    }
  };
  
  return <div>Navigation component</div>;
}

Link Opening

Functions for programmatically opening links with modifier key support.

/**
 * Programmatically opens links with modifier key support
 * @param target - Anchor element to open
 * @param modifiers - Object with modifier key states
 * @param setOpening - Whether to set opening flag for popup blockers
 */
function openLink(
  target: HTMLAnchorElement,
  modifiers: Modifiers,
  setOpening?: boolean
): void;

/**
 * Determines if link should use client-side navigation
 * @param link - Anchor element to check
 * @param modifiers - Modifier key states
 * @returns Boolean indicating if router should handle navigation
 */
function shouldClientNavigate(
  link: HTMLAnchorElement,
  modifiers: Modifiers
): boolean;

/**
 * Handles link clicks with modifier key support
 * @param target - Anchor element clicked
 * @param modifiers - Modifier key states from event
 */
function handleLinkClick(
  target: HTMLAnchorElement,
  modifiers: Modifiers
): void;

interface Modifiers {
  metaKey: boolean;
  ctrlKey: boolean;
  altKey: boolean;
  shiftKey: boolean;
}

Usage Examples:

import { openLink, shouldClientNavigate, handleLinkClick } from "@react-aria/utils";

function SmartLink({ href, children, onClick, ...props }) {
  const linkRef = useRef<HTMLAnchorElement>(null);
  
  const handleClick = (e: MouseEvent) => {
    if (!linkRef.current) return;
    
    const modifiers = {
      metaKey: e.metaKey,
      ctrlKey: e.ctrlKey,
      altKey: e.altKey,
      shiftKey: e.shiftKey
    };
    
    // Check if we should use client-side navigation
    if (shouldClientNavigate(linkRef.current, modifiers)) {
      e.preventDefault();
      handleLinkClick(linkRef.current, modifiers);
    } else {
      // Let browser handle navigation
      openLink(linkRef.current, modifiers, true);
    }
    
    onClick?.(e);
  };
  
  return (
    <a 
      ref={linkRef}
      href={href}
      onClick={handleClick}
      {...props}
    >
      {children}
    </a>
  );
}

// Link with programmatic opening
function ProgrammaticLink({ href, openInNewTab = false }) {
  const linkRef = useRef<HTMLAnchorElement>(null);
  
  const handleButtonClick = () => {
    if (!linkRef.current) return;
    
    const modifiers = {
      metaKey: openInNewTab,
      ctrlKey: openInNewTab,
      altKey: false,
      shiftKey: false
    };
    
    openLink(linkRef.current, modifiers, true);
  };
  
  return (
    <div>
      <a ref={linkRef} href={href} style={{ display: 'none' }} />
      <button onClick={handleButtonClick}>
        Open Link {openInNewTab ? '(New Tab)' : ''}
      </button>
    </div>
  );
}

Synthetic Links

Utilities for creating non-anchor elements that behave like links.

/**
 * Creates data attributes for synthetic links
 * @param props - Link DOM properties
 * @returns Object with data-* attributes for non-anchor elements
 */
function getSyntheticLinkProps(props: LinkDOMProps): DOMAttributes<HTMLElement>;

/**
 * Hook that creates data attributes for synthetic links
 * @param props - Link DOM properties  
 * @returns Object with data-* attributes for non-anchor elements
 */
function useSyntheticLinkProps(props: LinkDOMProps): DOMAttributes<HTMLElement>;

/**
 * Hook that processes link props with router context
 * @param props - Optional link properties
 * @returns Link props with router-processed href
 */
function useLinkProps(props?: LinkDOMProps): LinkDOMProps;

interface LinkDOMProps extends DOMProps {
  href?: string;
  target?: string;
  rel?: string;
  download?: boolean | string;
  ping?: string;
  referrerPolicy?: string;
}

Usage Examples:

import { useSyntheticLinkProps, useLinkProps, getSyntheticLinkProps } from "@react-aria/utils";

// Button that acts like a link
function LinkButton({ href, children, ...props }) {
  const linkProps = useLinkProps({ href, ...props });
  const syntheticProps = useSyntheticLinkProps(linkProps);
  
  return (
    <button 
      {...syntheticProps}
      onClick={(e) => {
        // Handle click as link
        const link = document.createElement('a');
        link.href = href;
        handleLinkClick(link, {
          metaKey: e.metaKey,
          ctrlKey: e.ctrlKey,
          altKey: e.altKey,
          shiftKey: e.shiftKey
        });
      }}
    >
      {children}
    </button>
  );
}

// Card component that's entirely clickable
function ClickableCard({ href, title, description }) {
  const syntheticProps = getSyntheticLinkProps({ href });
  
  return (
    <div 
      {...syntheticProps}
      className="card clickable"
      role="link"
      tabIndex={0}
      onClick={(e) => {
        const link = document.createElement('a');
        link.href = href;
        openLink(link, {
          metaKey: e.metaKey,
          ctrlKey: e.ctrlKey,
          altKey: e.altKey,
          shiftKey: e.shiftKey
        });
      }}
      onKeyDown={(e) => {
        if (e.key === 'Enter' || e.key === ' ') {
          e.preventDefault();
          const link = document.createElement('a');
          link.href = href;
          openLink(link, { metaKey: false, ctrlKey: false, altKey: false, shiftKey: false });
        }
      }}
    >
      <h3>{title}</h3>
      <p>{description}</p>
    </div>
  );
}

// Router-aware link component
function RouterLink({ href, children, ...props }) {
  const linkProps = useLinkProps({ href, ...props });
  const router = useRouter();
  
  return (
    <a 
      {...linkProps}
      onClick={(e) => {
        const modifiers = {
          metaKey: e.metaKey,
          ctrlKey: e.ctrlKey,
          altKey: e.altKey,
          shiftKey: e.shiftKey
        };
        
        if (shouldClientNavigate(e.currentTarget, modifiers)) {
          e.preventDefault();
          if (router.isNative) {
            window.location.href = href;
          } else {
            // Use router navigation
            router.open(e.currentTarget, modifiers);
          }
        }
      }}
    >
      {children}
    </a>
  );
}

Advanced Navigation Patterns

Complex navigation scenarios with conditional routing and state management:

import { 
  useRouter, 
  shouldClientNavigate, 
  useLinkProps,
  useSyntheticLinkProps 
} from "@react-aria/utils";

function AdvancedNavigation() {
  const router = useRouter();
  const [isNavigating, setIsNavigating] = useState(false);
  
  const handleNavigation = useCallback(async (href: string, modifiers: Modifiers) => {
    const link = document.createElement('a');
    link.href = href;
    
    if (shouldClientNavigate(link, modifiers)) {
      setIsNavigating(true);
      
      try {
        // Perform client-side navigation with loading state
        await router.navigate(href);
      } finally {
        setIsNavigating(false);
      }
    } else {
      // Use browser navigation
      openLink(link, modifiers, true);
    }
  }, [router]);
  
  return (
    <nav>
      <NavigationItem 
        href="/dashboard"
        onClick={handleNavigation}
        isLoading={isNavigating}
      >
        Dashboard
      </NavigationItem>
    </nav>
  );
}

// Context menu with link actions
function ContextMenu({ href, onClose }) {
  const menuActions = [
    {
      label: 'Open',
      action: () => {
        const link = document.createElement('a');
        link.href = href;
        openLink(link, { metaKey: false, ctrlKey: false, altKey: false, shiftKey: false });
        onClose();
      }
    },
    {
      label: 'Open in New Tab',
      action: () => {
        const link = document.createElement('a');
        link.href = href;
        openLink(link, { metaKey: true, ctrlKey: false, altKey: false, shiftKey: false });
        onClose();
      }
    },
    {
      label: 'Copy Link',
      action: () => {
        navigator.clipboard.writeText(href);
        onClose();
      }
    }
  ];
  
  return (
    <ul role="menu">
      {menuActions.map(action => (
        <li key={action.label}>
          <button onClick={action.action}>
            {action.label}
          </button>
        </li>
      ))}
    </ul>
  );
}

Types

interface DOMProps {
  id?: string;
}

interface LinkDOMProps extends DOMProps {
  href?: string;
  target?: string;
  rel?: string;
  download?: boolean | string;
  ping?: string;
  referrerPolicy?: string;
}

interface Modifiers {
  metaKey: boolean;
  ctrlKey: boolean;
  altKey: boolean;
  shiftKey: boolean;
}

interface Router {
  isNative: boolean;
  open: (target: HTMLAnchorElement, modifiers: Modifiers, setOpening?: boolean) => void;
  useHref?: (href: string) => string;
}

Install with Tessl CLI

npx tessl i tessl/npm-react-aria--utils

docs

animation-and-transitions.md

event-management.md

focus-and-accessibility.md

id-and-refs.md

index.md

links-and-navigation.md

miscellaneous-utilities.md

platform-detection.md

props-and-events.md

scrolling-and-layout.md

shadow-dom-support.md

state-and-effects.md

virtual-events-and-input.md

tile.json