Skip to main content
Version: v6

Compatibility packages

The default React Query Builder components, being basic HTML5 form controls, are very flexible when it comes to styling (primarily through the controlClassnames prop). However, some style libraries require different HTML structure to style their form controls correctly.

Packages

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

You can see each alternate component package in action by clicking the corresponding link on the demo page. The "Demo" links in the table below will load the demo with the respective style library preselected, and the CodeSandbox links will open codesandbox.io with an editable example of the library preloaded.

Official siteCompatibility packageDemoCodeSandboxStackBlitz
Ant Design@react-querybuilder/antdDemoCodeSandboxStackBlitz
Bootstrap@react-querybuilder/bootstrapDemoCodeSandboxStackBlitz
Bulma@react-querybuilder/bulmaDemoCodeSandboxStackBlitz
Chakra UI@react-querybuilder/chakraDemoCodeSandboxStackBlitz
Fluent UI@react-querybuilder/fluentDemoCodeSandboxStackBlitz
Mantine@react-querybuilder/mantineDemoCodeSandboxStackBlitz
MUI@react-querybuilder/materialDemoCodeSandboxStackBlitz
React Native@react-querybuilder/nativeComing soon!CodeSandboxStackBlitz

Usage

The recommended way to apply one of the other compatibility packages to <QueryBuilder /> is to wrap it in the appropriate QueryBuilder* context provider.

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 for @react-querybuilder/native. For that package, render <QueryBuilderNative /> instead of <QueryBuilder />. They accept the same props.

Compatibility packageContext provider
@react-querybuilder/antdQueryBuilderAntD
@react-querybuilder/bootstrapQueryBuilderBootstrap
@react-querybuilder/bulmaQueryBuilderBulma
@react-querybuilder/chakraQueryBuilderChakra
@react-querybuilder/fluentQueryBuilderFluent
@react-querybuilder/mantineQueryBuilderMantine
@react-querybuilder/materialQueryBuilderMaterial
tip

React Query Builder context providers can be nested beneath one another to progressively add features and customization. For example, QueryBuilderDnD adds drag-and-drop features to the query builder, and you can nest the compatibility package context providers beneath it (or vice versa) to add the style library's components while maintaining the drag-and-drop features.

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 that can be used as the controlElements prop in <QueryBuilder />. Some packages also export a *ControlClassnames object for use with the controlClassnames prop. Use these exports if you need more fine-grained control over which standard components get replaced. For even more detailed customization, continue reading below.

This example uses the Bootstrap library:

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

export function App() {
return (
<QueryBuilder
fields={fields}
defaultQuery={defaultQuery}
controlElements={bootstrapControlElements}
controlClassnames={bootstrapControlClassnames}
/>
);
}
Compatibility packagecontrolElements object
@react-querybuilder/antdantdControlElements
@react-querybuilder/bootstrapbootstrapControlElements
@react-querybuilder/bulmabulmaControlElements
@react-querybuilder/chakrachakraControlElements
@react-querybuilder/fluentfluentControlElements
@react-querybuilder/mantinemantineControlElements
@react-querybuilder/materialmaterialControlElements

Customization

All of the 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 the query builder integration up to the compatibility layer.

For example, the AntDActionElement component from @react-querybuilder/antd renders a Button component from antd, so it can accept properties of the ActionWithRulesProps interface from react-querybuilder and the ButtonProps interface from antd.

In the example below, the size prop is accepted because it's one of antd's Button props (from the ButtonProps interface), even though it's not included in the ActionWithRulesProps interface.

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

const MyAntDActionElement = (props: ActionWithRulesProps) => (
<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 will be accepted by the compatibility components, in addition to those defined by react-querybuilder.

ComponentBase props (from RQB)Rendered library component
AntDActionElementActionWithRulesPropsimport { Button } from 'antd'
AntDDragHandleDragHandlePropsimport { HolderOutlined } from '@ant-design/icons'
AntDNotToggleNotTogglePropsimport { Switch } from 'antd'
AntDValueSelectorVersatileSelectorPropsimport { Select } from 'antd'
ChakraActionElementActionWithRulesPropsimport { Button } from '@chakra-ui/react'
ChakraDragHandleDragHandlePropsimport { IconButton } from '@chakra-ui/react'
ChakraNotToggleNotTogglePropsimport { Switch } from '@chakra-ui/react'
ChakraValueSelectorVersatileSelectorPropsimport { Select } from '@chakra-ui/react'
FluentActionElementActionWithRulesPropsimport { Button } from '@fluentui/react-components'
FluentDragHandleDragHandlePropsimport { Text } from '@fluentui/react-components'
FluentNotToggleNotTogglePropsimport { Switch } from '@fluentui/react-components'
FluentValueSelectorVersatileSelectorPropsimport { Dropdown, Select } from '@fluentui/react-components'
MantineActionElementActionWithRulesPropsimport { Button } from '@mantine/core'
MantineNotToggleNotTogglePropsimport { Switch } from '@mantine/core'
MantineValueSelectorVersatileSelectorPropsimport { Select } from '@mantine/core'
MaterialActionElementActionWithRulesPropsimport Button from '@mui/material/Button'
MaterialDragHandleDragHandlePropsimport DragIndicator from '@mui/icons-material/DragIndicator'
MaterialNotToggleNotTogglePropsimport Switch from '@mui/material/Switch'
MaterialValueSelectorVersatileSelectorPropsimport Select from '@mui/material/Select'

Preload MUI components

tip

As of v6.2.0, MUI components will be 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 would load components from @mui/material asynchronously in order to properly inherit the theme context (issue/PR). This meant that the query builder would initially be rendered with the default components, and then—very quickly, if all went well—the MUI components would replace them.

To avoid rendering the default components and render the 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. (The 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';
import { DragIndicator } from '@mui/icons-material';
import {
Button,
Checkbox,
FormControl,
FormControlLabel,
// Replace `Input` with `TextField` in versions greater than 7.7.0
Input,
ListSubheader,
MenuItem,
Radio,
RadioGroup,
Select,
Switch,
TextareaAutosize,
} from '@mui/material';

const muiComponents = {
Button,
Checkbox,
DragIndicator,
FormControl,
FormControlLabel,
// Replace `Input` with `TextField` in versions greater than 7.7.0
Input,
ListSubheader,
MenuItem,
Radio,
RadioGroup,
Select,
Switch,
TextareaAutosize,
};

const muiTheme = createTheme();

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