Radix UI Documentation

repository·main·Indexed 21 days ago

https://github.com/radix-ui/website

Documentation and source code for Radix UI, a library of unstyled, accessible primitives. Includes implementation guides and demos for components such as Accordion, Alert Dialog, AspectRatio, and Avatar, featuring integration examples for CSS Modules and Tailwind CSS.

Tokens
168K
Snippets
498
Records
744
Agent score
75%

What's inside Radix UI

  1. Overview of the Menubar component

    main

    The Menubar is a visually persistent menu common in desktop applications, providing quick access to a consistent set of commands.

    Key features include:

    • Controlled or uncontrolled state management.
    • Support for submenus with configurable reading direction.
    • Support for items, labels, and groups of items.
    • Support for checkable items (single or multiple selection).
    • Customizable side, alignment, offsets, and collision handling.
    • Optional pointing arrow rendering.
    • Fully managed focus and full keyboard navigation, including typeahead support.
  2. Overview of the Select component

    main

    The Select component displays a list of options for a user to pick from, which is triggered by a button. It is designed to be highly flexible and accessible, following the WAI-ARIA listbox pattern.

    Key features include:

    • Supports both controlled and uncontrolled states.
    • Offers two positioning modes.
    • Supports items, labels, and groups of items.
    • Fully managed focus and full keyboard navigation.
    • Supports custom placeholders and typeahead.
    • Supports Right to Left (RTL) direction.
  3. Case Study: Using Radix Primitives at Vercel

    main

    Vercel uses Radix Primitives across their design system, multiple public and internal Next.js applications, marketing websites, and internal prototypes.

    Key benefits reported by Vercel include:

    • Speed of Development: Avoiding the need to re-implement common UI components from scratch, allowing teams to focus on core user experiences.
    • Consistency: Replacing a scattered stack of custom components and various 3rd party libraries (like Reach UI or React Spectrum) with a single, unified vendor for primitive needs.
    • Transferable Knowledge: API consistency across components makes it easier for engineers to move between different parts of the codebase.
    • Reduced Bundle Size: Consolidating on Radix helps avoid introducing multiple 3rd party dependencies and their associated utilities.
    • Ease of Animation: The primitives allow for easy implementation of entry/exit CSS animations.
  4. Case Study: Using Radix Primitives in Node.js Web Design System

    main

    Node.js utilizes Radix Primitives as a core part of its Web Design System. This integration allows engineers to implement standard UX primitives (such as Dropdowns and Dialogs) while offloading the complexity of cross-browser compatibility, accessibility (A11y), and internationalization to the library.

    Key benefits identified in the Node.js implementation include:

    • Single Responsibility Pattern: Each Primitive is its own JavaScript package, which reduces resource wastage and simplifies bundling by allowing for precise tree-shaking.
    • DOM-like Structure: Components are structured similarly to a DOM tree (using wrappers, root elements, triggers, etc.), providing high control over UI decoration and layout.
    • Predictable API: A consistent and opinionated API across different components facilitates the standardization of UI elements.
    • Extensibility: Radix focuses on a core set of primitives that users can extend and combine to build complex interfaces.
  5. Styling Radix Primitives

    main

    Radix Primitives are unstyled components, meaning they do not come with any default visual presentation. They are designed to be compatible with any styling solution (CSS, CSS-in-JS, etc.), giving you complete control over the visual layer while Radix handles accessibility and functionality.

    Key styling mechanisms include:

    • className prop: All components and their parts accept a className prop which is passed directly to the underlying DOM element.
    • data-state attribute: Stateful components expose their current state via a data-state attribute (e.g., data-state="open" or data-state="closed"), allowing you to style different states easily.
  6. Case Study: Using Radix Primitives at Liveblocks

    main

    Liveblocks uses Radix Primitives, Tailwind CSS, and React to build their design system across their marketing site, documentation, and product dashboard.

    Key benefits noted by Liveblocks:

    • Native-like behavior: Radix handles complex interactions (like nested menu items, screen real-estate management, and keyboard navigation) that are difficult to build from scratch.
    • Unstyled components: The unstyled nature of Radix allows for complete design freedom and easy integration with Tailwind CSS.
    • Granular installation: Developers can install only the specific components needed, allowing for incremental adoption.

    Components currently used by Liveblocks:

    • Dialog
    • AlertDialog
    • Menu
    • ContextMenu
    • ScrollArea
    • Tooltip
    • NavigationMenu (used for main navigation to improve accessibility)
  7. Use Radix Themes layout components

    main

    Radix Themes provides a set of layout components designed to separate layout responsibilities from content and interactivity.

    • Box: The most fundamental component. Use it for spacing, sizing constraints, controlling flex/grid behavior, and responsive visibility via the display prop.
    • Flex: Extends Box with props to organize items along an axis using CSS Flexbox properties.
    • Grid: Used to organize content in columns and rows using CSS Grid properties.
    • Section: Provides consistent vertical spacing between large parts of a page using pre-defined spacing levels.
    • Container: Provides a consistent max-width to its children, using pre-defined sizes optimized for common breakpoints.
    import { Box, Flex, Grid, Section, Container } from '@radix-ui/themes';
    
    // Example usage of different layout components
    <Section>
      <Container>
        <Grid columns="3" gap="4">
          <Box>Column 1</Box>
          <Box>Column 2</Box>
          <Box>Column 3</Box>
        </Grid>
      </Container>
    </Section>
  8. Handle duplicate toasts

    main

    To show a new toast every time a user performs an action (like clicking a button), you have two main options:

    1. Declarative State: Use React state to maintain a count of active toasts and map over that count to render multiple Toast.Root instances.
    2. Imperative API: Create a custom wrapper component using useImperativeHandle to expose a publish() method that increments a local state count.
    export default () => {
      const [savedCount, setSavedCount] = React.useState(0);
    
      return (
        <div>
          <form onSubmit={() => setSavedCount((count) => count + 1)}>
            <button>save</button>
          </form>
    
          {Array.from({ length: savedCount }).map((_, index) => (
            <Toast.Root key={index}>
              <Toast.Description>Saved!</Toast.Description>
            </Toast.Root>
          ))}
        </div>
      );
    };
  9. Accessibility for the Label component

    main

    The Label component is built on the native label element. It automatically applies correct labeling when:

    1. Wrapping a control element.
    2. Using the htmlFor attribute to point to a control's id.

    To ensure custom controls work correctly with Label, ensure they use native elements like button or input as their base.

  10. Decouple the Switch hidden input

    main

    By default, Switch.Root renders a visually hidden input for form submission. If you need to recompose, move, or exclude this input, you can use the unstable lower-level parts.

    Warning: These parts are prefixed with unstable_ and their API may change.

    • Switch.unstable_Provider: Manages state and accepts form props (name, value, checked, defaultChecked, required, disabled, onCheckedChange).
    • Switch.unstable_Trigger: The interactive button element that wraps Switch.Thumb.
    • Switch.unstable_BubbleInput: The visually hidden input. Omit this if form submission is not required.
    import { Switch } from "radix-ui";
    
    export default () => (
    	<Switch.unstable_Provider name="airplane-mode">
    		<Switch.unstable_Trigger>
    			<Switch.Thumb />
    		</Switch.unstable_Trigger>
    		{/* The hidden input can be omitted if you don't need form submission */}
    		<Switch.unstable_BubbleInput />
    	</Switch.unstable_Provider>
    );