Skip to main content
Version: v7 / v8

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 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
Tremor@react-querybuilder/tremorDemoCodeSandboxStackBlitz

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 packageContext provider
@react-querybuilder/antdQueryBuilderAntD
@react-querybuilder/bootstrapQueryBuilderBootstrap
@react-querybuilder/bulmaQueryBuilderBulma
@react-querybuilder/chakraQueryBuilderChakra
@react-querybuilder/fluentQueryBuilderFluent
@react-querybuilder/mantineQueryBuilderMantine
@react-querybuilder/materialQueryBuilderMaterial
@react-querybuilder/tremorQueryBuilderTremor
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 packagecontrolElements object
@react-querybuilder/antdantdControlElements
@react-querybuilder/bootstrapbootstrapControlElements
@react-querybuilder/bulmabulmaControlElements
@react-querybuilder/chakrachakraControlElements
@react-querybuilder/fluentfluentControlElements
@react-querybuilder/mantinemantineControlElements
@react-querybuilder/materialmaterialControlElements
@react-querybuilder/nativenativeControlElements
@react-querybuilder/tremortremorControlElements

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.

ComponentBase props (from RQB)Rendered library component
@react-querybuilder/antd
AntDActionElementActionPropsimport { Button } from 'antd'
AntDDragHandleDragHandlePropsimport { HolderOutlined } from '@ant-design/icons'
AntDNotToggleNotTogglePropsimport { Switch } from 'antd'
AntDValueSelectorVersatileSelectorPropsimport { Select } from 'antd'
@react-querybuilder/chakra
ChakraActionElementActionPropsimport { Button } from '@chakra-ui/react'
ChakraDragHandle (removed in v8)DragHandlePropsimport { IconButton } from '@chakra-ui/react'
ChakraNotToggleNotTogglePropsimport { Switch } from '@chakra-ui/react'
ChakraValueSelectorVersatileSelectorPropsimport { Select } from '@chakra-ui/react'
@react-querybuilder/fluent
FluentActionElementActionPropsimport { Button } from '@fluentui/react-components'
FluentDragHandleDragHandlePropsimport { Text } from '@fluentui/react-components'
FluentNotToggleNotTogglePropsimport { Switch } from '@fluentui/react-components'
FluentValueSelectorVersatileSelectorPropsimport { Dropdown, Select } from '@fluentui/react-components'
@react-querybuilder/mantine
MantineActionElementActionPropsimport { Button } from '@mantine/core'
MantineNotToggleNotTogglePropsimport { Switch } from '@mantine/core'
MantineValueSelectorVersatileSelectorPropsimport { Select } from '@mantine/core'
@react-querybuilder/material
MaterialActionElementActionPropsimport { Button } from '@mui/material'
MaterialDragHandleDragHandlePropsimport { DragIndicator } from '@mui/icons-material'
MaterialNotToggleNotTogglePropsimport { Switch } from '@mui/material'
MaterialValueSelectorVersatileSelectorPropsimport { Select } from '@mui/material'
@react-querybuilder/tremor
TremorActionElementActionPropsimport { Button } from '@tremor/react'
TremorNotToggleNotTogglePropsimport { Switch } from '@tremor/react'
TremorValueSelectorVersatileSelectorPropsimport { 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';
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)
};

const muiTheme = createTheme();

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