Skip to main content
Refine provides first-class support for Ant Design (antd), a comprehensive enterprise-level UI design language and React component library. The @refinedev/antd package offers pre-built components that seamlessly integrate with Refine’s core functionality.

Installation

npm install @refinedev/antd antd @ant-design/icons dayjs

Setup

Basic Setup

Wrap your application with Ant Design’s theme provider and use Refine’s themed layout:
App.tsx
import { Refine } from "@refinedev/core";
import {
  ThemedLayout,
  RefineThemes,
  useNotificationProvider,
} from "@refinedev/antd";
import { ConfigProvider, App as AntdApp } from "antd";
import dataProvider from "@refinedev/simple-rest";

import "@refinedev/antd/dist/reset.css";

function App() {
  return (
    <ConfigProvider theme={RefineThemes.Blue}>
      <AntdApp>
        <Refine
          dataProvider={dataProvider("https://api.example.com")}
          notificationProvider={useNotificationProvider}
          resources={[
            {
              name: "products",
              list: "/products",
              create: "/products/create",
              edit: "/products/edit/:id",
              show: "/products/show/:id",
            },
          ]}
        >
          <ThemedLayout>
            {/* Your pages here */}
          </ThemedLayout>
        </Refine>
      </AntdApp>
    </ConfigProvider>
  );
}

export default App;

Available Themes

Refine provides pre-configured Ant Design themes:
import { RefineThemes } from "@refinedev/antd";

// Available themes:
RefineThemes.Blue
RefineThemes.Purple
RefineThemes.Magenta
RefineThemes.Red
RefineThemes.Orange
RefineThemes.Yellow

Custom Theme

You can customize the theme using Ant Design’s theme configuration:
import { ConfigProvider, theme } from "antd";

function App() {
  return (
    <ConfigProvider
      theme={{
        algorithm: theme.darkAlgorithm,
        token: {
          colorPrimary: "#1890ff",
          borderRadius: 8,
        },
      }}
    >
      {/* Your app */}
    </ConfigProvider>
  );
}

Layout Components

ThemedLayout

The main layout component with sidebar, header, and content area:
import { ThemedLayout } from "@refinedev/antd";

function App() {
  return (
    <Refine
      // ... other props
    >
      <ThemedLayout>
        {/* Your routes */}
      </ThemedLayout>
    </Refine>
  );
}

Custom Layout Components

You can customize individual layout components:
import {
  ThemedLayout,
  ThemedSider,
  ThemedHeader,
  ThemedTitle,
} from "@refinedev/antd";

function App() {
  return (
    <ThemedLayout
      Sider={() => <ThemedSider fixed />}
      Header={() => <ThemedHeader sticky />}
      Title={({ collapsed }) => (
        <ThemedTitle collapsed={collapsed} text="My Admin" />
      )}
    >
      {/* Your routes */}
    </ThemedLayout>
  );
}

CRUD Components

List

Display list of records with automatic page header and create button:
pages/products/list.tsx
import { List, useTable, EditButton, ShowButton } from "@refinedev/antd";
import { Table, Space } from "antd";

export const ProductList = () => {
  const { tableProps } = useTable();

  return (
    <List>
      <Table {...tableProps} rowKey="id">
        <Table.Column dataIndex="id" title="ID" />
        <Table.Column dataIndex="name" title="Name" />
        <Table.Column dataIndex="price" title="Price" />
        <Table.Column
          title="Actions"
          render={(_, record) => (
            <Space>
              <EditButton size="small" recordItemId={record.id} />
              <ShowButton size="small" recordItemId={record.id} />
            </Space>
          )}
        />
      </Table>
    </List>
  );
};

Create

Create form with automatic save button and navigation:
pages/products/create.tsx
import { Create, useForm } from "@refinedev/antd";
import { Form, Input, InputNumber } from "antd";

export const ProductCreate = () => {
  const { formProps, saveButtonProps } = useForm();

  return (
    <Create saveButtonProps={saveButtonProps}>
      <Form {...formProps} layout="vertical">
        <Form.Item
          label="Name"
          name="name"
          rules={[{ required: true }]}
        >
          <Input />
        </Form.Item>
        <Form.Item
          label="Price"
          name="price"
          rules={[{ required: true }]}
        >
          <InputNumber style={{ width: "100%" }} />
        </Form.Item>
        <Form.Item label="Description" name="description">
          <Input.TextArea rows={4} />
        </Form.Item>
      </Form>
    </Create>
  );
};

Edit

Edit form with automatic data fetching and save button:
pages/products/edit.tsx
import { Edit, useForm } from "@refinedev/antd";
import { Form, Input, InputNumber } from "antd";

export const ProductEdit = () => {
  const { formProps, saveButtonProps, queryResult } = useForm();

  return (
    <Edit saveButtonProps={saveButtonProps}>
      <Form {...formProps} layout="vertical">
        <Form.Item label="ID" name="id">
          <Input disabled />
        </Form.Item>
        <Form.Item
          label="Name"
          name="name"
          rules={[{ required: true }]}
        >
          <Input />
        </Form.Item>
        <Form.Item
          label="Price"
          name="price"
          rules={[{ required: true }]}
        >
          <InputNumber style={{ width: "100%" }} />
        </Form.Item>
      </Form>
    </Edit>
  );
};

Show

Display single record in read-only mode:
pages/products/show.tsx
import {
  Show,
  TextField,
  NumberField,
  DateField,
} from "@refinedev/antd";
import { useShow } from "@refinedev/core";
import { Typography } from "antd";

const { Title } = Typography;

export const ProductShow = () => {
  const { queryResult } = useShow();
  const { data, isLoading } = queryResult;
  const record = data?.data;

  return (
    <Show isLoading={isLoading}>
      <Title level={5}>ID</Title>
      <TextField value={record?.id} />

      <Title level={5}>Name</Title>
      <TextField value={record?.name} />

      <Title level={5}>Price</Title>
      <NumberField
        value={record?.price}
        options={{
          style: "currency",
          currency: "USD",
        }}
      />

      <Title level={5}>Created At</Title>
      <DateField value={record?.createdAt} />
    </Show>
  );
};

Field Components

Refine provides field components for displaying different types of data:
import {
  TextField,
  NumberField,
  DateField,
  EmailField,
  UrlField,
  BooleanField,
  TagField,
  ImageField,
  FileField,
  MarkdownField,
} from "@refinedev/antd";
import { Space } from "antd";

function FieldExamples() {
  return (
    <Space direction="vertical">
      <TextField value="Simple text" />
      
      <NumberField
        value={1234.56}
        options={{ style: "currency", currency: "USD" }}
      />
      
      <DateField value="2024-01-15" format="LLL" />
      
      <EmailField value="[email protected]" />
      
      <UrlField value="https://example.com" />
      
      <BooleanField value={true} />
      
      <TagField value="Active" color="green" />
      
      <ImageField value="https://example.com/image.jpg" width={200} />
      
      <FileField src="https://example.com/file.pdf" title="Download" />
      
      <MarkdownField value="# Hello\n\nThis is **markdown**" />
    </Space>
  );
}

Button Components

Refine provides action buttons with automatic routing and confirmation:
import {
  CreateButton,
  EditButton,
  ShowButton,
  DeleteButton,
  ListButton,
  RefreshButton,
  SaveButton,
  CloneButton,
  ExportButton,
  ImportButton,
} from "@refinedev/antd";
import { Space } from "antd";

function ButtonExamples() {
  return (
    <Space>
      <CreateButton resource="products" />
      <EditButton resource="products" recordItemId="1" />
      <ShowButton resource="products" recordItemId="1" />
      <DeleteButton resource="products" recordItemId="1" />
      <ListButton resource="products" />
      <RefreshButton resource="products" />
      <SaveButton />
      <CloneButton resource="products" recordItemId="1" />
      <ExportButton />
      <ImportButton />
    </Space>
  );
}

Advanced Features

Data Grid with Filters

import { List, useTable, FilterDropdown } from "@refinedev/antd";
import { Table, Input, Select, DatePicker } from "antd";
import { SearchOutlined } from "@ant-design/icons";

export const ProductList = () => {
  const { tableProps, filters, sorters } = useTable({
    initialSorter: [
      {
        field: "id",
        order: "desc",
      },
    ],
  });

  return (
    <List>
      <Table {...tableProps} rowKey="id">
        <Table.Column
          dataIndex="name"
          title="Name"
          filterDropdown={(props) => (
            <FilterDropdown {...props}>
              <Input placeholder="Search name" />
            </FilterDropdown>
          )}
          filterIcon={<SearchOutlined />}
        />
        <Table.Column
          dataIndex="status"
          title="Status"
          filterDropdown={(props) => (
            <FilterDropdown {...props}>
              <Select
                style={{ width: 200 }}
                placeholder="Select status"
                options={[
                  { label: "Active", value: "active" },
                  { label: "Inactive", value: "inactive" },
                ]}
              />
            </FilterDropdown>
          )}
        />
        <Table.Column
          dataIndex="price"
          title="Price"
          sorter
        />
      </Table>
    </List>
  );
};
import { useModalForm, CreateButton, Edit } from "@refinedev/antd";
import { Modal, Form, Input } from "antd";

export const ProductList = () => {
  const { modalProps, formProps, show } = useModalForm({
    action: "create",
  });

  return (
    <>
      <CreateButton onClick={() => show()} />
      
      <Modal {...modalProps}>
        <Form {...formProps} layout="vertical">
          <Form.Item label="Name" name="name" rules={[{ required: true }]}>
            <Input />
          </Form.Item>
        </Form>
      </Modal>
    </>
  );
};

Drawer Forms

import { useDrawerForm, EditButton } from "@refinedev/antd";
import { Drawer, Form, Input } from "antd";

export const ProductList = () => {
  const { drawerProps, formProps, show } = useDrawerForm({
    action: "edit",
  });

  return (
    <>
      <EditButton onClick={() => show("1")} />
      
      <Drawer {...drawerProps}>
        <Form {...formProps} layout="vertical">
          <Form.Item label="Name" name="name" rules={[{ required: true }]}>
            <Input />
          </Form.Item>
        </Form>
      </Drawer>
    </>
  );
};

Auto-Save Indicator

import { AutoSaveIndicator, useForm } from "@refinedev/antd";
import { Form, Input } from "antd";

export const ProductEdit = () => {
  const { formProps, autoSaveProps } = useForm({
    autoSave: {
      enabled: true,
      debounce: 2000,
    },
  });

  return (
    <>
      <AutoSaveIndicator {...autoSaveProps} />
      <Form {...formProps} layout="vertical">
        <Form.Item label="Name" name="name">
          <Input />
        </Form.Item>
      </Form>
    </>
  );
};

Pro Layout

Refine integrates with Ant Design Pro Layout for advanced layouts:
import { ThemedLayout } from "@refinedev/antd";

// Pro Layout is automatically used in ThemedLayout
// It provides:
// - Collapsible sidebar
// - Responsive design
// - Breadcrumb navigation
// - Multiple menu modes

Next Steps

Ant Design Docs

Official Ant Design documentation

Examples

See complete Ant Design examples

Hooks

Learn about Refine hooks

Theming

Customize your theme

Build docs developers (and LLMs) love