Skip to main content
Refine provides comprehensive support for Chakra UI, a simple, modular, and accessible component library. The @refinedev/chakra-ui package offers pre-built components that integrate seamlessly with Refine’s core functionality while maintaining Chakra’s focus on accessibility.

Installation

npm install @refinedev/chakra-ui @chakra-ui/react @emotion/react @emotion/styled framer-motion @tabler/icons-react dayjs

Setup

Basic Setup

Wrap your application with Chakra UI’s provider:
App.tsx
import { Refine } from "@refinedev/core";
import {
  ThemedLayout,
  RefineThemes,
  useNotificationProvider,
} from "@refinedev/chakra-ui";
import { ChakraProvider } from "@chakra-ui/react";
import dataProvider from "@refinedev/simple-rest";

function App() {
  return (
    <ChakraProvider theme={RefineThemes.Blue}>
      <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>
    </ChakraProvider>
  );
}

export default App;

Available Themes

Refine provides pre-configured Chakra UI themes:
import { RefineThemes } from "@refinedev/chakra-ui";

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

Custom Theme

Customize the theme using Chakra UI’s extendTheme:
import { ChakraProvider, extendTheme } from "@chakra-ui/react";

const customTheme = extendTheme({
  colors: {
    brand: {
      50: "#e3f2fd",
      100: "#bbdefb",
      500: "#2196f3",
      900: "#0d47a1",
    },
  },
  fonts: {
    heading: "Inter, sans-serif",
    body: "Inter, sans-serif",
  },
  config: {
    initialColorMode: "light",
    useSystemColorMode: true,
  },
});

function App() {
  return (
    <ChakraProvider theme={customTheme}>
      {/* Your app */}
    </ChakraProvider>
  );
}

Layout Components

ThemedLayout

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

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

Custom Layout Components

import {
  ThemedLayout,
  ThemedSider,
  ThemedHeader,
  ThemedTitle,
} from "@refinedev/chakra-ui";

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

CRUD Components

List

Display list with Chakra UI Table:
pages/products/list.tsx
import {
  List,
  EditButton,
  ShowButton,
  DeleteButton,
} from "@refinedev/chakra-ui";
import { useTable } from "@refinedev/react-table";
import { ColumnDef, flexRender } from "@tanstack/react-table";
import {
  Table,
  Thead,
  Tbody,
  Tr,
  Th,
  Td,
  HStack,
  Button,
} from "@chakra-ui/react";
import { useMemo } from "react";

export const ProductList = () => {
  const columns = useMemo<ColumnDef<any>[]>(
    () => [
      {
        id: "id",
        accessorKey: "id",
        header: "ID",
      },
      {
        id: "name",
        accessorKey: "name",
        header: "Name",
      },
      {
        id: "price",
        accessorKey: "price",
        header: "Price",
      },
      {
        id: "actions",
        header: "Actions",
        cell: ({ row }) => (
          <HStack spacing={2}>
            <EditButton hideText size="sm" recordItemId={row.original.id} />
            <ShowButton hideText size="sm" recordItemId={row.original.id} />
            <DeleteButton hideText size="sm" recordItemId={row.original.id} />
          </HStack>
        ),
      },
    ],
    [],
  );

  const { getHeaderGroups, getRowModel } = useTable({
    columns,
  });

  return (
    <List>
      <Table variant="simple">
        <Thead>
          {getHeaderGroups().map((headerGroup) => (
            <Tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => (
                <Th key={header.id}>
                  {flexRender(
                    header.column.columnDef.header,
                    header.getContext(),
                  )}
                </Th>
              ))}
            </Tr>
          ))}
        </Thead>
        <Tbody>
          {getRowModel().rows.map((row) => (
            <Tr key={row.id}>
              {row.getVisibleCells().map((cell) => (
                <Td key={cell.id}>
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </Td>
              ))}
            </Tr>
          ))}
        </Tbody>
      </Table>
    </List>
  );
};

Create

Create form with Chakra UI components:
pages/products/create.tsx
import { Create } from "@refinedev/chakra-ui";
import { useForm } from "@refinedev/react-hook-form";
import {
  FormControl,
  FormLabel,
  FormErrorMessage,
  Input,
  Textarea,
} from "@chakra-ui/react";

export const ProductCreate = () => {
  const {
    refineCore: { formLoading },
    saveButtonProps,
    register,
    formState: { errors },
  } = useForm();

  return (
    <Create isLoading={formLoading} saveButtonProps={saveButtonProps}>
      <FormControl mb="3" isInvalid={!!errors?.name}>
        <FormLabel>Name</FormLabel>
        <Input
          type="text"
          {...register("name", {
            required: "Name is required",
          })}
        />
        <FormErrorMessage>{`${errors.name?.message}`}</FormErrorMessage>
      </FormControl>

      <FormControl mb="3" isInvalid={!!errors?.price}>
        <FormLabel>Price</FormLabel>
        <Input
          type="number"
          step="0.01"
          {...register("price", {
            required: "Price is required",
          })}
        />
        <FormErrorMessage>{`${errors.price?.message}`}</FormErrorMessage>
      </FormControl>

      <FormControl mb="3">
        <FormLabel>Description</FormLabel>
        <Textarea {...register("description")} />
      </FormControl>
    </Create>
  );
};

Edit

Edit form with automatic data fetching:
pages/products/edit.tsx
import { Edit } from "@refinedev/chakra-ui";
import { useForm } from "@refinedev/react-hook-form";
import {
  FormControl,
  FormLabel,
  FormErrorMessage,
  Input,
} from "@chakra-ui/react";

export const ProductEdit = () => {
  const {
    refineCore: { queryResult, formLoading },
    saveButtonProps,
    register,
    formState: { errors },
  } = useForm();

  return (
    <Edit isLoading={formLoading} saveButtonProps={saveButtonProps}>
      <FormControl mb="3">
        <FormLabel>ID</FormLabel>
        <Input type="text" {...register("id")} disabled />
      </FormControl>

      <FormControl mb="3" isInvalid={!!errors?.name}>
        <FormLabel>Name</FormLabel>
        <Input
          type="text"
          {...register("name", {
            required: "Name is required",
          })}
        />
        <FormErrorMessage>{`${errors.name?.message}`}</FormErrorMessage>
      </FormControl>

      <FormControl mb="3" isInvalid={!!errors?.price}>
        <FormLabel>Price</FormLabel>
        <Input
          type="number"
          step="0.01"
          {...register("price", {
            required: "Price is required",
          })}
        />
        <FormErrorMessage>{`${errors.price?.message}`}</FormErrorMessage>
      </FormControl>
    </Edit>
  );
};

Show

Display single record:
pages/products/show.tsx
import {
  Show,
  TextField,
  NumberField,
  DateField,
} from "@refinedev/chakra-ui";
import { useShow } from "@refinedev/core";
import { Heading } from "@chakra-ui/react";

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

  return (
    <Show isLoading={isLoading}>
      <Heading as="h5" size="sm" mt={4}>
        ID
      </Heading>
      <TextField value={record?.id} />

      <Heading as="h5" size="sm" mt={4}>
        Name
      </Heading>
      <TextField value={record?.name} />

      <Heading as="h5" size="sm" mt={4}>
        Price
      </Heading>
      <NumberField
        value={record?.price}
        options={{
          style: "currency",
          currency: "USD",
        }}
      />

      <Heading as="h5" size="sm" mt={4}>
        Created At
      </Heading>
      <DateField value={record?.createdAt} />
    </Show>
  );
};

Field Components

Chakra UI field components for displaying data:
import {
  TextField,
  NumberField,
  DateField,
  EmailField,
  UrlField,
  BooleanField,
  TagField,
  MarkdownField,
} from "@refinedev/chakra-ui";
import { VStack } from "@chakra-ui/react";

function FieldExamples() {
  return (
    <VStack spacing={3} align="stretch">
      <TextField value="Simple text" />
      
      <NumberField
        value={1234.56}
        options={{ style: "currency", currency: "USD" }}
      />
      
      <DateField value="2024-01-15" format="LL" />
      
      <EmailField value="[email protected]" />
      
      <UrlField value="https://example.com" />
      
      <BooleanField value={true} />
      
      <TagField value="Active" colorScheme="green" />
      
      <MarkdownField value="# Hello\n\nThis is **markdown**" />
    </VStack>
  );
}

Button Components

Chakra UI styled action buttons:
import {
  CreateButton,
  EditButton,
  ShowButton,
  DeleteButton,
  ListButton,
  RefreshButton,
  SaveButton,
  CloneButton,
  ExportButton,
  ImportButton,
} from "@refinedev/chakra-ui";
import { HStack } from "@chakra-ui/react";

function ButtonExamples() {
  return (
    <HStack spacing={2}>
      <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 />
    </HStack>
  );
}

Advanced Features

import { CreateButton, SaveButton } from "@refinedev/chakra-ui";
import { useForm } from "@refinedev/react-hook-form";
import {
  Modal,
  ModalOverlay,
  ModalContent,
  ModalHeader,
  ModalBody,
  ModalFooter,
  ModalCloseButton,
  FormControl,
  FormLabel,
  Input,
  useDisclosure,
} from "@chakra-ui/react";

export const ProductList = () => {
  const { isOpen, onOpen, onClose } = useDisclosure();
  const {
    refineCore: { onFinish },
    register,
    handleSubmit,
  } = useForm();

  return (
    <>
      <CreateButton onClick={onOpen} />
      
      <Modal isOpen={isOpen} onClose={onClose}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Create Product</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <FormControl>
              <FormLabel>Name</FormLabel>
              <Input {...register("name")} />
            </FormControl>
          </ModalBody>
          <ModalFooter>
            <SaveButton onClick={handleSubmit(onFinish)} />
          </ModalFooter>
        </ModalContent>
      </Modal>
    </>
  );
};

Color Mode Toggle

import { IconButton, useColorMode } from "@chakra-ui/react";
import { IconSun, IconMoon } from "@tabler/icons-react";

function ColorModeToggle() {
  const { colorMode, toggleColorMode } = useColorMode();

  return (
    <IconButton
      aria-label="Toggle color mode"
      icon={colorMode === "light" ? <IconMoon /> : <IconSun />}
      onClick={toggleColorMode}
    />
  );
}

Toast Notifications

import { Button, useToast } from "@chakra-ui/react";

function CustomNotification() {
  const toast = useToast();

  const handleClick = () => {
    toast({
      title: "Success",
      description: "Operation completed successfully",
      status: "success",
      duration: 5000,
      isClosable: true,
      position: "top-right",
    });
  };

  return <Button onClick={handleClick}>Show Notification</Button>;
}

Auto-Save Indicator

import { AutoSaveIndicator } from "@refinedev/chakra-ui";
import { useForm } from "@refinedev/react-hook-form";
import { FormControl, FormLabel, Input } from "@chakra-ui/react";

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

  return (
    <>
      <AutoSaveIndicator {...autoSaveProps} />
      <FormControl>
        <FormLabel>Name</FormLabel>
        <Input {...register("name")} />
      </FormControl>
    </>
  );
};

Responsive Design

Chakra UI has excellent responsive utilities:
import { Box, Grid, GridItem, useBreakpointValue } from "@chakra-ui/react";

function ResponsiveLayout() {
  const columns = useBreakpointValue({ base: 1, md: 2, lg: 3 });

  return (
    <Grid
      templateColumns={`repeat(${columns}, 1fr)`}
      gap={6}
    >
      <GridItem>
        {/* Content */}
      </GridItem>
      <GridItem>
        {/* Content */}
      </GridItem>
    </Grid>
  );
}

Accessibility Features

Chakra UI is built with accessibility in mind:
import {
  Button,
  VisuallyHidden,
  useColorModeValue,
} from "@chakra-ui/react";

function AccessibleButton() {
  const bg = useColorModeValue("white", "gray.800");

  return (
    <Button
      bg={bg}
      aria-label="Save changes"
      _hover={{ bg: "blue.500" }}
      _focus={{
        boxShadow: "outline",
        outline: "none",
      }}
    >
      <VisuallyHidden>Save changes</VisuallyHidden>
      Save
    </Button>
  );
}

Style Props

Chakra UI’s style props make styling quick and easy:
import { Box } from "@chakra-ui/react";

function StyledBox() {
  return (
    <Box
      p={4}
      m={2}
      bg="blue.500"
      color="white"
      borderRadius="md"
      boxShadow="lg"
      _hover={{ bg: "blue.600" }}
      _active={{ bg: "blue.700" }}
    >
      Styled Box
    </Box>
  );
}

Next Steps

Chakra UI Docs

Official Chakra UI documentation

Examples

See complete Chakra UI examples

Accessibility

Learn about accessibility features

Theming

Customize your theme

Build docs developers (and LLMs) love