Skip to content

Latest commit

 

History

History
267 lines (224 loc) · 16.2 KB

File metadata and controls

267 lines (224 loc) · 16.2 KB
title Compatibility packages

React Query Builder's default components use basic HTML5 form controls that are highly customizable through styling, especially via the controlClassnames prop. However, some UI libraries require specific components or HTML structures to properly style their form controls.

Packages

Official component packages for several popular style libraries are available under the @react-querybuilder org on npm.

See each component package in action by selecting the "Style library" option on the demo page. The "Demo" links below load the demo with that library preselected, while CodeSandbox/StackBlitz links open editable examples on their respective platforms.

Official site Compatibility package Demo CodeSandbox StackBlitz
Ant Design @react-querybuilder/antd Demo CodeSandbox StackBlitz
Bootstrap @react-querybuilder/bootstrap Demo CodeSandbox StackBlitz
Bulma @react-querybuilder/bulma Demo CodeSandbox StackBlitz
Chakra UI @react-querybuilder/chakra Demo CodeSandbox StackBlitz
Fluent UI @react-querybuilder/fluent Demo CodeSandbox StackBlitz
Mantine @react-querybuilder/mantine Demo CodeSandbox StackBlitz
MUI @react-querybuilder/material Demo CodeSandbox StackBlitz
React Native @react-querybuilder/native Coming soon! CodeSandbox StackBlitz
Tremor @react-querybuilder/tremor Demo CodeSandbox StackBlitz

Usage

The recommended approach is to wrap <QueryBuilder /> in the appropriate QueryBuilder* context provider from the compatibility package.

This example uses the Ant Design library:

import { QueryBuilderAntD } from '@react-querybuilder/antd';
import 'antd/dist/antd.compact.css'; // <- include this only if using `antd@<5`
import { QueryBuilder } from 'react-querybuilder';
import 'react-querybuilder/dist/query-builder.css';
import { defaultQuery, fields } from './constants';

export function App() {
  return (
    <QueryBuilderAntD>
      <QueryBuilder fields={fields} defaultQuery={defaultQuery} />
    </QueryBuilderAntD>
  );
}

Each compatibility package exports its own context provider, except @react-querybuilder/native, which provides <QueryBuilderNative /> as a direct replacement for <QueryBuilder /> with identical props.

Compatibility package Context provider
@react-querybuilder/antd QueryBuilderAntD
@react-querybuilder/bootstrap QueryBuilderBootstrap
@react-querybuilder/bulma QueryBuilderBulma
@react-querybuilder/chakra QueryBuilderChakra
@react-querybuilder/fluent QueryBuilderFluent
@react-querybuilder/mantine QueryBuilderMantine
@react-querybuilder/material QueryBuilderMaterial
@react-querybuilder/tremor QueryBuilderTremor

:::tip

Context providers can be nested to combine features. For example, nest a UI library provider under QueryBuilderDnD to add both drag-and-drop functionality and styled components.

This example uses the Bulma library and enables drag-and-drop:

import { QueryBuilderBulma } from '@react-querybuilder/bulma';
import { QueryBuilderDnD } from '@react-querybuilder/dnd';
import 'bulma/bulma.sass';
import { QueryBuilder } from 'react-querybuilder';
import 'react-querybuilder/dist/query-builder.css';
import { defaultQuery, fields } from './constants';

export function App() {
  return (
    <QueryBuilderDnD>
      <QueryBuilderBulma>
        <QueryBuilder fields={fields} defaultQuery={defaultQuery} />
      </QueryBuilderBulma>
    </QueryBuilderDnD>
  );
}

:::

Other exports

Each compatibility package exports a *ControlElements object for the controlElements prop. Some packages also include *ControlClassnames and *Translations objects for their respective props. Use these exports when you need granular control over component replacement. See Customization below for advanced usage.

This example uses the Bootstrap library:

import {
  bootstrapControlClassnames,
  bootstrapControlElements,
} from '@react-querybuilder/bootstrap';
import 'bootstrap/dist/css/bootstrap.css';
import { QueryBuilder } from 'react-querybuilder';
import { defaultQuery, fields } from './constants';

export function App() {
  return (
    <QueryBuilder
      fields={fields}
      defaultQuery={defaultQuery}
      controlElements={bootstrapControlElements}
      controlClassnames={bootstrapControlClassnames}
    />
  );
}
Compatibility package controlElements object
@react-querybuilder/antd antdControlElements
@react-querybuilder/bootstrap bootstrapControlElements
@react-querybuilder/bulma bulmaControlElements
@react-querybuilder/chakra chakraControlElements
@react-querybuilder/fluent fluentControlElements
@react-querybuilder/mantine mantineControlElements
@react-querybuilder/material materialControlElements
@react-querybuilder/native nativeControlElements
@react-querybuilder/tremor tremorControlElements

Customization

All compatibility components except the *ValueEditors accept props defined by the style library for the actual rendered component in addition to the standard props defined by react-querybuilder. This allows you to idiomatically customize the style library's component while leaving query builder integration to the compatibility layer.

For example, the AntDActionElement component from @react-querybuilder/antd renders an antd Button component, so it accepts properties from both the ActionProps interface (react-querybuilder) and the ButtonProps interface (antd).

In the example below, the size prop is accepted because it's an antd Button prop (from the ButtonProps interface), even though it's not in the ActionProps interface.

import { AntDActionElement, antdControlElements } from '@react-querybuilder/antd';
import { QueryBuilder, type ActionProps } from 'react-querybuilder';

const MyAntDActionElement = (props: ActionProps) => <AntDActionElement {...props} size="large" />;

export function App() {
  return (
    <QueryBuilder
      controlElements={{
        ...antdControlElements,
        addRuleAction: MyAntDActionElement,
        addGroupAction: MyAntDActionElement,
        cloneRuleAction: MyAntDActionElement,
        cloneGroupAction: MyAntDActionElement,
        lockRuleAction: MyAntDActionElement,
        lockGroupAction: MyAntDActionElement,
        removeRuleAction: MyAntDActionElement,
        removeGroupAction: MyAntDActionElement,
      }}
    />
  );
}

This list shows which library components' props are accepted by the compatibility components, in addition to those defined by react-querybuilder.

Component Base props (from RQB) Rendered library component
@react-querybuilder/antd
AntDActionElement ActionProps import { Button } from 'antd'
AntDDragHandle DragHandleProps import { HolderOutlined } from '@ant-design/icons'
AntDNotToggle NotToggleProps import { Switch } from 'antd'
AntDValueSelector VersatileSelectorProps import { Select } from 'antd'
@react-querybuilder/chakra
ChakraActionElement ActionProps import { Button } from '@chakra-ui/react'
ChakraDragHandle (removed in v8) DragHandleProps import { IconButton } from '@chakra-ui/react'
ChakraNotToggle NotToggleProps import { Switch } from '@chakra-ui/react'
ChakraValueSelector VersatileSelectorProps import { Select } from '@chakra-ui/react'
@react-querybuilder/fluent
FluentActionElement ActionProps import { Button } from '@fluentui/react-components'
FluentDragHandle DragHandleProps import { Text } from '@fluentui/react-components'
FluentNotToggle NotToggleProps import { Switch } from '@fluentui/react-components'
FluentValueSelector VersatileSelectorProps import { Dropdown, Select } from '@fluentui/react-components'
@react-querybuilder/mantine
MantineActionElement ActionProps import { Button } from '@mantine/core'
MantineNotToggle NotToggleProps import { Switch } from '@mantine/core'
MantineValueSelector VersatileSelectorProps import { Select } from '@mantine/core'
@react-querybuilder/material
MaterialActionElement ActionProps import { Button } from '@mui/material'
MaterialDragHandle DragHandleProps import { DragIndicator } from '@mui/icons-material'
MaterialNotToggle NotToggleProps import { Switch } from '@mui/material'
MaterialValueSelector VersatileSelectorProps import { Select } from '@mui/material'
@react-querybuilder/tremor
TremorActionElement ActionProps import { Button } from '@tremor/react'
TremorNotToggle NotToggleProps import { Switch } from '@tremor/react'
TremorValueSelector VersatileSelectorProps import { MultiSelect, Select } from '@tremor/react'

Preload MUI components

:::tip

As of v6.2.0, MUI components are loaded synchronously in traditional environments. However, preloading MUI components may still be necessary when using React Server Components, even if the component file rendering the query builder includes the "use client" directive.

:::

Prior to v6.2.0, the @react-querybuilder/material compatibility package loaded components from @mui/material asynchronously to properly inherit the theme context (issue/PR). This meant the query builder was initially rendered with default components, then—very quickly, if all went well—the MUI components would replace them.

To avoid rendering default components and render MUI components immediately instead, import the MUI components in your application code and assign them as properties of the muiComponents prop on the QueryBuilderMaterial context provider. (Individual MUI compatibility components—MaterialValueEditor, MaterialActionElement, etc.—also accept an optional muiComponents prop.)

import { createTheme, ThemeProvider } from '@mui/material/styles';
import { QueryBuilderMaterial } from '@react-querybuilder/material';
import { QueryBuilder } from 'react-querybuilder';
import { defaultQuery, fields } from './constants';
// highlight-start
import CloseIcon from '@mui/icons-material/Close';
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
import DragIndicator from '@mui/icons-material/DragIndicator';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import LockIcon from '@mui/icons-material/Lock';
import LockOpenIcon from '@mui/icons-material/LockOpen';
import Button from '@mui/material/Button';
import Checkbox from '@mui/material/Checkbox';
import FormControl from '@mui/material/FormControl';
import FormControlLabel from '@mui/material/FormControlLabel';
import ListSubheader from '@mui/material/ListSubheader';
import MenuItem from '@mui/material/MenuItem';
import Radio from '@mui/material/Radio';
import RadioGroup from '@mui/material/RadioGroup';
import Select from '@mui/material/Select';
import Switch from '@mui/material/Switch';
import TextareaAutosize from '@mui/material/TextareaAutosize';
// (Use `Input` instead of `TextField` in versions lower than 7.7.1)
import TextField from '@mui/material/TextField';

const muiComponents = {
  Button,
  Checkbox,
  CloseIcon,
  ContentCopyIcon,
  DragIndicator,
  FormControl,
  FormControlLabel,
  KeyboardArrowDownIcon,
  KeyboardArrowUpIcon,
  ListSubheader,
  LockIcon,
  LockOpenIcon,
  MenuItem,
  Radio,
  RadioGroup,
  Select,
  Switch,
  TextareaAutosize,
  TextField, // (Use `Input` instead of `TextField` in versions lower than 7.7.1)
};
// highlight-end

const muiTheme = createTheme();

export function App() {
  return (
    <ThemeProvider theme={muiTheme}>
      {/* highlight-start */}
      <QueryBuilderMaterial muiComponents={muiComponents}>
        {/* highlight-end */}
        <QueryBuilder fields={fields} defaultQuery={defaultQuery} />
      </QueryBuilderMaterial>
    </ThemeProvider>
  );
}