Skip to content
ant-design logo

Ant Design

ant-design

Builds enterprise React applications with Ant Design's comprehensive component library. Use when creating admin dashboards, data tables, complex forms, or enterprise UIs with consistent design language.

SKILL.md

Full skill instructions

Ant Design

Enterprise-class React UI library with comprehensive components for admin interfaces.

Quick Start

npm install antd
import React from 'react';
import { ConfigProvider, Button, Space } from 'antd';

function App() {
  return (
    <ConfigProvider
      theme={{
        token: {
          colorPrimary: '#1677ff',
        },
      }}
    >
      <Space>
        <Button type="primary">Primary</​Button>
        <Button>Default</​Button>
      </​Space>
    </​ConfigProvider>
  );
}

Core Components

Button

import { Button, Space } from 'antd';
import { SearchOutlined, DownloadOutlined } from '@ant-design/​icons';

// Types
<Button type="primary">Primary</​Button>
<Button type="default">Default</​Button>
<Button type="dashed">Dashed</​Button>
<Button type="text">Text</​Button>
<Button type="link">Link</​Button>

// Sizes
<Button size="large">Large</​Button>
<Button size="middle">Middle</​Button>
<Button size="small">Small</​Button>

// States
<Button loading>Loading</​Button>
<Button disabled>Disabled</​Button>
<Button danger>Danger</​Button>

// With icons
<Button type="primary" icon={<SearchOutlined />}>Search</​Button>
<Button icon={<DownloadOutlined />} />

Form

import { Form, Input, Select, Button, Checkbox, DatePicker } from 'antd';

function MyForm() {
  const [form] = Form.useForm();

  const onFinish = (values) => {
    console.log('Form values:', values);
  };

  return (
    <Form
      form={form}
      layout="vertical"
      onFinish={onFinish}
      initialValues={{ remember: true }}
    >
      <Form.Item
        label="Email"
        name="email"
        rules={[
          { required: true, message: 'Please input your email!' },
          { type: 'email', message: 'Invalid email format' },
        ]}
      >
        <Input placeholder="[email protected]" />
      </​Form.Item>

      <Form.Item
        label="Password"
        name="password"
        rules={[{ required: true, min: 8 }]}
      >
        <Input.Password />
      </​Form.Item>

      <Form.Item label="Role" name="role">
        <Select>
          <Select.Option value="admin">Admin</​Select.Option>
          <Select.Option value="user">User</​Select.Option>
        </​Select>
      </​Form.Item>

      <Form.Item label="Date" name="date">
        <DatePicker style={{ width: '100%' }} />
      </​Form.Item>

      <Form.Item name="remember" valuePropName="checked">
        <Checkbox>Remember me</​Checkbox>
      </​Form.Item>

      <Form.Item>
        <Button type="primary" htmlType="submit">Submit</​Button>
      </​Form.Item>
    </​Form>
  );
}

Table

import { Table, Tag, Space, Button } from 'antd';

const columns = [
  {
    title: 'Name',
    dataIndex: 'name',
    key: 'name',
    sorter: (a, b) => a.name.localeCompare(b.name),
    render: (text) => <a>{text}</​a>,
  },
  {
    title: 'Age',
    dataIndex: 'age',
    key: 'age',
    sorter: (a, b) => a.age - b.age,
  },
  {
    title: 'Status',
    dataIndex: 'status',
    key: 'status',
    filters: [
      { text: 'Active', value: 'active' },
      { text: 'Inactive', value: 'inactive' },
    ],
    onFilter: (value, record) => record.status === value,
    render: (status) => (
      <Tag color={status === 'active' ? 'green' : 'red'}>
        {status.toUpperCase()}
      </​Tag>
    ),
  },
  {
    title: 'Action',
    key: 'action',
    render: (_, record) => (
      <Space size="middle">
        <a>Edit</​a>
        <a>Delete</​a>
      </​Space>
    ),
  },
];

<Table
  columns={columns}
  dataSource={data}
  rowKey="id"
  pagination={{ pageSize: 10 }}
  rowSelection={{
    type: 'checkbox',
    onChange: (selectedRowKeys) => console.log(selectedRowKeys),
  }}
/>

Modal

import { Modal, Button } from 'antd';
import { useState } from 'react';
import { ExclamationCircleFilled } from '@ant-design/​icons';

function ModalDemo() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button onClick={() => setOpen(true)}>Open Modal</​Button>
      <Modal
        title="Modal Title"
        open={open}
        onOk={() => setOpen(false)}
        onCancel={() => setOpen(false)}
        okText="Confirm"
        cancelText="Cancel"
      >
        <p>Modal content here...</​p>
      </​Modal>
    </>
  );
}

// Confirmation modal
const { confirm } = Modal;

function showConfirm() {
  confirm({
    title: 'Do you want to delete these items?',
    icon: <ExclamationCircleFilled />,
    content: 'This action cannot be undone.',
    onOk() {
      return deleteItems();
    },
    onCancel() {},
  });
}

Notification & Message

import { notification, message, Button, Space } from 'antd';

// Notification (corner popup)
const [api, contextHolder] = notification.useNotification();

const openNotification = () => {
  api.success({
    message: 'Success',
    description: 'Your changes have been saved.',
    placement: 'topRight',
    duration: 4.5,
  });
};

<>
  {contextHolder}
  <Button onClick={openNotification}>Show Notification</​Button>
</>

// Message (top center toast)
const [messageApi, messageContextHolder] = message.useMessage();

const showMessage = () => {
  messageApi.success('Operation completed successfully');
  messageApi.error('Something went wrong');
  messageApi.warning('Please check your input');
  messageApi.loading('Loading...');
};

Menu and Navigation

import { Menu, Breadcrumb } from 'antd';
import {
  HomeOutlined,
  SettingOutlined,
  UserOutlined,
} from '@ant-design/​icons';

// Sidebar menu
const menuItems = [
  {
    key: 'home',
    icon: <HomeOutlined />,
    label: 'Home',
  },
  {
    key: 'users',
    icon: <UserOutlined />,
    label: 'Users',
    children: [
      { key: 'list', label: 'User List' },
      { key: 'add', label: 'Add User' },
    ],
  },
  {
    key: 'settings',
    icon: <SettingOutlined />,
    label: 'Settings',
  },
];

<Menu
  mode="inline"
  defaultSelectedKeys={['home']}
  defaultOpenKeys={['users']}
  items={menuItems}
  onClick={({ key }) => navigate(key)}
/>

// Breadcrumb
<Breadcrumb
  items={[
    { href: '/', title: <HomeOutlined /> },
    { href: '/​users', title: 'Users' },
    { title: 'John Doe' },
  ]}
/>

Tabs

import { Tabs } from 'antd';

<Tabs
  defaultActiveKey="1"
  items={[
    {
      key: '1',
      label: 'Tab 1',
      children: 'Content of Tab 1',
    },
    {
      key: '2',
      label: 'Tab 2',
      children: 'Content of Tab 2',
    },
    {
      key: '3',
      label: 'Tab 3',
      children: 'Content of Tab 3',
      disabled: true,
    },
  ]}
  onChange={(key) => console.log(key)}
/>

Card

import { Card, Avatar, Skeleton } from 'antd';
import { EditOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/​icons';

const { Meta } = Card;

<Card
  style={{ width: 300 }}
  cover={<img alt="cover" src="/​image.jpg" />}
  actions={[
    <SettingOutlined key="setting" />,
    <EditOutlined key="edit" />,
    <EllipsisOutlined key="ellipsis" />,
  ]}
>
  <Meta
    avatar={<Avatar src="/​avatar.jpg" />}
    title="Card title"
    description="This is the card description"
  />
</​Card>

// Loading state
<Card loading={true}>
  <Meta title="Card title" description="Description" />
</​Card>

Drawer

import { Drawer, Button, Form, Input, Select, Space } from 'antd';

function DrawerForm() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button type="primary" onClick={() => setOpen(true)}>
        Create User
      </​Button>
      <Drawer
        title="Create a new user"
        width={720}
        open={open}
        onClose={() => setOpen(false)}
        extra={
          <Space>
            <Button onClick={() => setOpen(false)}>Cancel</​Button>
            <Button type="primary">Submit</​Button>
          </​Space>
        }
      >
        <Form layout="vertical">
          <Form.Item label="Name" name="name" rules={[{ required: true }]}>
            <Input placeholder="Enter name" />
          </​Form.Item>
          <Form.Item label="Email" name="email">
            <Input placeholder="Enter email" />
          </​Form.Item>
        </​Form>
      </​Drawer>
    </>
  );
}

Theming

Design Tokens

import { ConfigProvider, theme } from 'antd';

// Custom theme
<ConfigProvider
  theme={{
    token: {
      colorPrimary: '#1677ff',
      colorSuccess: '#52c41a',
      colorWarning: '#faad14',
      colorError: '#ff4d4f',
      colorInfo: '#1677ff',
      borderRadius: 6,
      fontFamily: 'Inter, sans-serif',
    },
    components: {
      Button: {
        colorPrimary: '#00b96b',
        algorithm: true,
      },
      Input: {
        colorBorder: '#d9d9d9',
      },
    },
  }}
>
  <App />
</​ConfigProvider>

// Dark mode
<ConfigProvider
  theme={{
    algorithm: theme.darkAlgorithm,
  }}
>
  <App />
</​ConfigProvider>

// Compact mode
<ConfigProvider
  theme={{
    algorithm: theme.compactAlgorithm,
  }}
>
  <App />
</​ConfigProvider>

// Combined algorithms
<ConfigProvider
  theme={{
    algorithm: [theme.darkAlgorithm, theme.compactAlgorithm],
  }}
>
  <App />
</​ConfigProvider>

Using Theme Tokens

import { theme } from 'antd';

function MyComponent() {
  const { token } = theme.useToken();

  return (
    <div
      style={{
        backgroundColor: token.colorBgContainer,
        color: token.colorText,
        padding: token.padding,
        borderRadius: token.borderRadius,
      }}
    >
      Styled with tokens
    </​div>
  );
}

Layout

import { Layout, Menu } from 'antd';

const { Header, Sider, Content, Footer } = Layout;

function AppLayout() {
  const [collapsed, setCollapsed] = useState(false);

  return (
    <Layout style={{ minHeight: '100vh' }}>
      <Sider
        collapsible
        collapsed={collapsed}
        onCollapse={setCollapsed}
      >
        <div className="logo" />
        <Menu theme="dark" mode="inline" items={menuItems} />
      </​Sider>
      <Layout>
        <Header style={{ padding: 0, background: '#fff' }} />
        <Content style={{ margin: '24px 16px' }}>
          <div style={{ padding: 24, background: '#fff', minHeight: 360 }}>
            Content here
          </​div>
        </​Content>
        <Footer style={{ textAlign: 'center' }}>
          My App 2024
        </​Footer>
      </​Layout>
    </​Layout>
  );
}

Data Entry

Select with Search

import { Select } from 'antd';

<Select
  showSearch
  placeholder="Select a user"
  optionFilterProp="label"
  options={[
    { value: '1', label: 'John Doe' },
    { value: '2', label: 'Jane Smith' },
  ]}
  filterOption={(input, option) =>
    option.label.toLowerCase().includes(input.toLowerCase())
  }
/>

// Multiple select
<Select
  mode="multiple"
  allowClear
  placeholder="Select tags"
  options={tags}
  maxTagCount="responsive"
/>

// With grouping
<Select
  options={[
    {
      label: 'Manager',
      options: [
        { label: 'Jack', value: 'jack' },
        { label: 'Lucy', value: 'lucy' },
      ],
    },
    {
      label: 'Engineer',
      options: [
        { label: 'Tom', value: 'tom' },
      ],
    },
  ]}
/>

Upload

import { Upload, Button } from 'antd';
import { UploadOutlined, InboxOutlined } from '@ant-design/​icons';

// Basic upload
<Upload
  action="/​api/​upload"
  listType="text"
  maxCount={1}
>
  <Button icon={<UploadOutlined />}>Upload File</​Button>
</​Upload>

// Drag and drop
const { Dragger } = Upload;

<Dragger
  name="file"
  multiple
  action="/​api/​upload"
  onChange={(info) => {
    if (info.file.status === 'done') {
      message.success(`${info.file.name} uploaded successfully`);
    }
  }}
>
  <p className="ant-upload-drag-icon">
    <InboxOutlined />
  </​p>
  <p className="ant-upload-text">Click or drag file to upload</​p>
</​Dragger>

DatePicker and TimePicker

import { DatePicker, TimePicker, Space } from 'antd';
import dayjs from 'dayjs';

const { RangePicker } = DatePicker;

// Single date
<DatePicker
  format="YYYY-MM-DD"
  disabledDate={(current) => current && current < dayjs().startOf('day')}
/>

// Date range
<RangePicker
  format="YYYY-MM-DD"
  presets={[
    { label: 'Last 7 Days', value: [dayjs().subtract(7, 'd'), dayjs()] },
    { label: 'Last 30 Days', value: [dayjs().subtract(30, 'd'), dayjs()] },
  ]}
/>

// Time picker
<TimePicker format="HH:mm" minuteStep={15} />

Best Practices

  1. Use ConfigProvider - Wrap app for consistent theming
  2. Form.useForm() - Create form instance for programmatic control
  3. Design tokens - Use theme tokens instead of hardcoded values
  4. Icons package - Import from @ant-design/​icons
  5. Context holders - Use hook-based APIs for message/​notification

Reference Files

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View