Floating UI

website·Indexed 38 days ago

https://floating-ui.com/

A low-level, unopinionated positioning toolkit for floating elements. It provides a core engine for anchor positioning with bindings for React, Vue, and React Native, featuring middleware like flip, shift, and autoPlacement, as well as hooks for interactions such as useClick, useHover, and useDismiss.

Tokens
35.1K
Snippets
194
Records
226
Agent score
70%

What's inside Floating UI

  1. Overview of Floating UI capabilities

    Floating UI is a modular library for creating floating elements like tooltips, popovers, and dropdowns. It provides two primary feature sets:

    1. Positioning: A toolkit to anchor absolutely-positioned floating elements to reference elements, including features to prevent viewport collisions and maintain anchoring during page scrolls.
    2. Interactions: A set of primitive Hooks and components (specifically in the React package) to build accessible and complex interaction patterns for floating elements.
  2. Overview of Floating UI Smart Anchor Positioning

    Floating UI is a tree-shakeable, platform-agnostic library used to anchor floating elements (such as tooltips, popovers, or dropdowns) next to reference elements. It ensures floating elements stay in view by avoiding collisions through several positioning strategies:

    • Placement: Positions the floating element relative to the anchor.
    • Shift: Shifts the element to keep it within the viewport.
    • Flip: Changes the placement side (e.g., top to bottom) to keep it in view.
    • Size: Adjusts the size of the floating element to fit the available space.
    • Arrow: Dynamically positions a center-aware arrow element.
    • Virtual: Allows anchoring relative to arbitrary coordinates, such as a mouse cursor.
  3. Manage nested floating elements with FloatingTree

    The FloatingTree provider creates a context for nested floating elements that are not direct children of each other in the DOM. This is required for specific features including the bubbles option in the useDismiss() hook, nested virtual list navigation, nested elements that open on hover, and custom communication between parent and child floating elements.
  4. Design a reusable Dialog component architecture

    For complex applications, encapsulate dialog logic into a controller component and a set of render components. This allows for a declarative API that supports both controlled and uncontrolled states.

    Architecture Components:

    • Controller (<Dialog />): Manages the internal state and provides context to child components.
    • Trigger (<DialogTrigger />): The element that opens the dialog. Should support an asChild prop for custom elements and provide a data-state attribute for styling based on the open/closed state.
    • Content (<DialogContent />): The container for the dialog's children.
    • Heading (<DialogHeading />): The accessible title of the dialog.
    • Description (<DialogDescription />): The accessible description of the dialog.
    • Close (<DialogClose />): The button used to dismiss the dialog.

    Implementation Note: Render components should use forwardRef() and merge refs/props to ensure they don't overwrite attributes passed by the user or the interaction hooks.

    function App() {
      return (
        <Dialog>
          <DialogTrigger>My trigger</DialogTrigger>
          <DialogContent>
            <DialogHeading>My dialog heading</DialogHeading>
            <DialogDescription>
              My dialog description
            </DialogDescription>
            <DialogClose>Close</DialogClose>
          </DialogContent>
        </Dialog>
      );
    }
  5. Use Base UI for headless floating components

    Base UI is a headless React component library built on top of Floating UI. It provides pre-built headless components such as tooltips, popovers, menus, selects, preview cards, dialogs, and toasts.
  6. Understand the differences between Floating UI and Popper

    Floating UI is the evolution of Popper v2, designed as a lower-level, unopinionated positioning engine. Key improvements over Popper include:

    • Cross-platform Support: Works on React Native, Canvas, and WebGL, whereas Popper is limited to the web DOM.
    • Bundle Size: Modular by default and fully tree-shakeable. Users can also customize the DOM platform to further reduce size.
    • API Design: Uses a pure, ergonomic API instead of the verbose, mutation-heavy API found in Popper.
    • Inversion of Control: Instead of opinionated style application (like computeStyles), Floating UI returns raw numbers for the developer to apply as needed.
    • Extensibility: Custom middleware is easier to write because it removes complex modifier requirements (e.g., requires, phase) in favor of a simple, developer-controlled array order.
    • Predictability: No "magic" pre-configured middleware or automatic event listeners; features are added explicitly by the developer.
    • TypeScript: Written in TypeScript from the ground up for first-class type safety and autocomplete.
  7. Design a reusable popover component architecture

    For complex applications, encapsulate popover logic into a controller component and a set of render components. This allows for controlled/uncontrolled states and flexible triggers.

    Key components in this pattern:

    • <Popover />: Controller that manages state and provides context.
    • <PopoverTrigger />: The trigger element. Should support asChild for custom elements and use data-state for styling.
    • <PopoverContent />: The floating container.
    • <PopoverHeading /> and <PopoverDescription />: Optional accessibility elements for the popover content.
    • <PopoverClose />: Required close button for modal popovers.
    function App() {
      return (
        <Popover>
          <PopoverTrigger>My trigger</PopoverTrigger>
          <PopoverContent>
            <PopoverHeading>My popover heading</PopoverHeading>
            <PopoverDescription>
              My popover description
            </PopoverDescription>
            <PopoverClose>Close</PopoverClose>
          </PopoverContent>
        </Popover>
      );
    }
  8. Use Base UI for pre-built floating components

    Base UI is a production-ready component library built on top of @floating-ui/react. It provides a set of polished, pre-built components for common floating UI patterns, including Tooltip, Popover, Menu, Menubar, Context Menu, Navigation Menu, Select, Combobox, Autocomplete, Dialog, Preview Card, Alert Dialog, and Toast.
  9. Install @floating-ui/react-native

    Install the React Native bindings for @floating-ui/core to enable anchor positioning for floating elements.
    npm install @floating-ui/react-native
  10. Implement floating element dismissal with useDismiss

    The useDismiss hook closes a floating element when a dismissal is requested (by default, via the escape key or a pointer press outside the floating element). To implement it, pass the context from useFloating to useDismiss, and then include the resulting dismiss object in the useInteractions array. The prop getters from useInteractions must be spread onto the reference and floating elements.
    import { useState } from 'react';
    import { useFloating, useDismiss, useInteractions } from '@floating-ui/react';
    
    function App() {
      const [isOpen, setIsOpen] = useState(false);
     
      const {refs, floatingStyles, context} = useFloating({
        open: isOpen,
        onOpenChange: setIsOpen,
      });
     
      const dismiss = useDismiss(context);
     
      const {getReferenceProps, getFloatingProps} = useInteractions([
        dismiss,
      ]);
     
      return (
        <>
          <div ref={refs.setReference} {...getReferenceProps()}>
            Reference element
          </div>
          {isOpen && (
            <div
              ref={refs.setFloating}
              style={floatingStyles}
              {...getFloatingProps()}
            >
              Floating element
            </div>
          )}
        </>
      );
    }
  11. Apply computed transition styles with useTransitionStyles

    useTransitionStyles is a high-level hook that provides computed inline styles to be spread into a floating element's style prop. It handles the mounting logic via isMounted, which should replace the standard open state variable to allow unmounting animations to complete. It defaults to a 250ms opacity fade.
    import { useFloating, useTransitionStyles } from '@floating-ui/react';
    
    function App() {
      const {context} = useFloating();
      const {isMounted, styles} = useTransitionStyles(context);
     
      return (
        isMounted && (
          <div
            style={{
              ...styles,
            }}
          >
            Tooltip
          </div>
        )
      );
    }