Skip to Content
UI playbookOverview

UI playbook — ProComponents

Also served to coding agents as MCP framework_docs("pro"). Read before building screens. Sources: the official demos of @ant-design/pro-components@2.8.10 (exactly our runtime) and the page compositions of ant-design-pro (src/pages/*), adapted to Manh (antd v6, react-router, no umi/less/CSS). Every pattern below runs on manh.run — reference app: the Duyệt mua sắm template (templates/purchase-requests/, live at duyet-mua-sam.manh.run).

Why apps look “plastic”: hand-rolled shells (Layout + Menu), plain Card + Statistic dashboards, Table with no search/tabs/badges, forms in bare Modals, every screen the same grey box. The fix is not more CSS — it is using the Pro component that already encodes the polished pattern, with its semantic props filled in.


Every pattern has a runnable example: open it in the Playground, edit, copy the code or a ready-made prompt for your agent.

Rules (apply to every screen)

  1. Pick by job (decision table):
    • app shell → ProLayout · page header → PageContainer
    • list of records → ProTable (columns with valueType/valueEnum) · cards/feed → ProList (metas)
    • KPIs → StatisticCard.Group · panels/grids → ProCard (split, gutter, colSpan, ghost)
    • read-only record → ProDescriptions (reuse the table columns)
    • form on a page → ProForm (+ FooterToolbar) · in overlay → ModalForm / DrawerForm · wizard → StepsForm
    • filters above a list → ProTable search (or QueryFilter) · compact pills → LightFilter in toolbar.filter
    • login/register → LoginForm · empty/success/error → Result
  2. Fill the semantic props — they are what makes it look finished: title/subTitle/tooltip, headerBordered, cardBordered, extra, content/extraContent, valueEnum with status, valueType="money"|"dateTime"|"percent", showTotal, Badge counts on tabs, footer toolbars.
  3. One rhythm: 24px between sections (ProCard direction="column" ghost gutter={[0, 16|24]}), 16px inside dense rows. Sections sit on colorBgLayout grey; content in white cards. No extra margins.
  4. Color only from tokens — pick a preset in app/layout.tsx (PRESETS / BRAND / DARK in the auth starter), never invent hex colors (code.hardcoded-color warns); read colors with theme.useToken(); brand via ConfigProvider theme.token (set colorPrimary and colorPrimaryBg/colorInfoBg explicitly if the generated light shade looks muddy). ProLayout brand via its token={{ header, sider, pageContainer }}.
  5. Status = Badge semantics everywhere (table, list, detail): { text, status: "Success" | "Error" | "Processing" | "Warning" | "Default" }.
  6. Never onBack on PageContainer/PageHeader in this runtime (crashes, React #130 — gate code.no-pagecontainer-onback); use header.breadcrumb.

Polish checklist (run before deploy)

  • Shell is ProLayout; menu per role; selected item highlights on detail routes.
  • Every list: search fields chosen deliberately, status as Badge, money right-aligned and formatted, tab counts for the main status, empty text that says what to do.
  • Every dashboard number has a secondary line; the role’s to-do is first.
  • Detail page: summary in header, key number in extraContent, progress Steps, history Timeline, decisions in footer.
  • Forms in Drawer/Modal with submitText in the user’s language, tooltips on non-obvious fields, ProFormMoney/DatePicker with VN formats.
  • No hard-coded colors; brand + colorPrimaryBg set once in ConfigProvider.
  • Walk each role’s main flow against the deployed API (a token per role), confirm DB effects with db_query and logs, then run screenshot({ path, audit: true }) on each main screen (phone + desktop score: blank page, console errors, sideways scroll, broken images, icons standing in for photos, tap targets, contrast, placeholder copy, SEO head) and fix until clean — then ask the user to look at the deployed URL against Page recipes.
Last updated on