Agent skill
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.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/design/ant-design-mgd34msu-goodvibes-plugin
SKILL.md
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="you@example.com" />
</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
- Use ConfigProvider - Wrap app for consistent theming
- Form.useForm() - Create form instance for programmatic control
- Design tokens - Use theme tokens instead of hardcoded values
- Icons package - Import from
@ant-design/icons - Context holders - Use hook-based APIs for message/notification
Reference Files
- references/components.md - Complete component list
- references/theming.md - Advanced theming patterns
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?