Claude-skill-registry 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
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/ant-design" ~/.claude/skills/majiayu000-claude-skill-registry-ant-design && rm -rf "$T"
manifest:
skills/data/ant-design/SKILL.mdsource content
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