# Modra 接入指南(面向 AI 编码助手) 本文件是给 AI 助手读取的权威接入规则。生成 Modra 相关代码前请先通读;组件 API 以 `/ai/components/.md` 为准,不要凭记忆猜测 props。 ## 0. AI 接入流程(只知道站点地址时从这里开始) 站点地址:`https://modra.feinian.net`。按顺序执行,每步完成后再进入下一步: 1. **识别项目类型**:读 `package.json`。有 `react` → React / Next.js 路线;没有 React(Django、Rails、Blade、纯静态页)→ HTML 路线(`@modra/website`),**不要**引入 React。 2. **检查 registry 认证**(见第 2 节):运行 `npm view @modra/react@dev --registry https://npm.feinian.net/`。失败(401/403/ENOTFOUND)→ **停止并告知用户**需要 `NPM_TOKEN`,不要自行尝试获取或把 token 写入仓库。 3. **安装包与 peer**(第 2 节)。 4. **配置样式入口**(第 3 节):Tailwind v4 + `@modra/tailwind-preset` + `@source`。 5. **写入 AI 约定文件**:把 `https://modra.feinian.net/AGENTS.md` 的内容写入项目根的 `AGENTS.md`(Claude Code 用 `CLAUDE.md`,Cursor 用 `.cursor/rules/modra.mdc`),已存在则追加,不覆盖。 6. **写代码前查 API**:读 `https://modra.feinian.net/ai/components/.md`,不要凭记忆写 props。 7. **验证**:运行项目的类型检查与构建;渲染一个 `Button` 确认样式生效(见第 7 节常见错误)。 可选:连接 MCP 服务器,让 AI 直接按需查询文档,免于逐个抓取文件。见第 9 节。 ## 1. 选包 | 场景 | 使用 | | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | React / Next.js 应用 | `@modra/react` + `@modra/tailwind-preset` + `@modra/tokens` | | 纯 HTML / 后端模板(Django、Rails、Blade…) | `@modra/tokens` CSS 变量,或 Tailwind 语义类,或 `@modra/website` 配方(`modra-` 前缀类名)。**不要**引入 React | | 图标(可选) | `@feinian/fontawesome-pro-react`(需授权)或 `@feinian/fontawesome-free-react`,两者 API 一致 | ## 2. 安装 ```bash pnpm add @modra/tokens@dev @modra/tailwind-preset@dev @modra/react@dev --registry https://npm.feinian.net/ ``` - 包来自内网 registry `https://npm.feinian.net/`,发布在 `dev` 通道(所以带 `@dev`)。 - **认证**:token 通过环境变量 `NPM_TOKEN` 提供,在**用户级** `~/.npmrc`(不是项目内文件)写入: ```ini //npm.feinian.net/:_authToken=${NPM_TOKEN} ``` - `NPM_TOKEN` 由团队的 registry 管理员发放;AI 无法也不应自行获取。 - 安装前检查:`echo "${NPM_TOKEN:+set}"` 输出 `set` 才算已配置。**未配置时停止并请用户设置**,不要把 token 写入项目的 `.npmrc`、`package.json`、CI 配置或任何会提交的文件。 - 在 CI / Docker 构建中通过构建密钥或环境变量注入,不要 `COPY` 含 token 的 `.npmrc` 进镜像。 - 验证:`npm view @modra/react@dev version --registry https://npm.feinian.net/` 能输出版本号。 - 只使用 `--registry` 参数或用户级 `.npmrc` 指向该 registry;不要修改全局默认 registry。 - 只在确实用到对应组件时才安装可选 peer(与组件同一个应用内安装): | 组件 | peer 依赖 | | ---------------------------------- | ----------------------------- | | `DataTable` | `@tanstack/react-table` | | `Calendar` / 日期类选择器 | `react-day-picker` `date-fns` | | `Command` | `cmdk` | | `Form` | `react-hook-form` | | `InputOTP` | `input-otp` | | `Resizable` | `react-resizable-panels` | | 虚拟化 `Tree` / `VirtualDataTable` | `@tanstack/react-virtual` | `Button` 等核心控件不需要任何额外 peer。 ## 3. 样式入口(必须) ```css /* app.css */ @import "tailwindcss"; @import "@modra/tailwind-preset"; /* 让 Tailwind 扫描组件库用到的工具类 */ @source "../node_modules/@modra/react/dist/**/*.{js,mjs}"; ``` 要求 Tailwind v4。缺少 `@source` 会导致组件样式丢失。 ## 4. 使用组件 ```tsx import { Button } from "@modra/react"; export default function Page() { return ; } ``` - 所有组件从包根 `@modra/react` 导入,不要深层导入内部路径。 - 复合组件按子组件组合(如 `Dialog` / `DialogContent` / `DialogHeader` / `DialogTitle`),导出清单见各组件的 md。 - 全局应用外层使用 `ConfigProvider`(默认 `zhCN`);需要同步 `` 时传 `syncDocumentLang`。 - 通知使用 `Toaster` + `toast()`,确认框使用 `confirm()` + `ConfirmDialogHost`。 ## 5. 样式与主题规则 - 使用**语义类**:`bg-primary`、`text-primary-foreground`、`text-muted-foreground`、`bg-background`、`rounded-md` 等。**不要**硬编码颜色、也不要用 `dark:` 去手写颜色分支——暗色由语义变量自动切换。 - 优先使用逻辑属性类(`ps-*`/`pe-*`/`ms-*`/`me-*`/`start-*`/`end-*`),以便 RTL;不要用 `pl-*`/`pr-*`/`left-*`/`right-*` 表达方向性间距。 - 暗色模式:给 `` 切换 `.dark`。品牌:``(`ids` 仅浅色)。密度:`data-density="compact"`。 - 运行时自定义主题使用 `ThemeProvider theme={{ color: { primary: "..." } }}`,不要手写覆盖 CSS 变量。 - 修改视觉应通过令牌(`@modra/tokens`)而不是改组件内部类名。 ## 6. 选型速查(同类组件怎么选) | 需求 | 选择 | | ------ | ------------------------------------------------------------------------------------------------------------------- | | 选择器 | `select`(少量)→ `combobox`(可搜索)→ `command`(命令面板)→ `tree-select` / `cascader` / `transfer`(层级/穿梭) | | 覆盖层 | `dialog`(通用)、`alert-dialog` / `popconfirm`(确认)、`sheet`(侧滑) | | 表格 | `table`(静态)、`data-table`(排序/筛选/分页)、`virtual-data-table`(海量数据) | | 反馈 | `alert`(页内)、`toast`(瞬时)、`empty`(空态)、`result`(结果页) | 完整的决策指引见 `/llms-full.txt`。 ## 7. 常见错误 1. 忘记 `@import "@modra/tailwind-preset"` 或 `@source` → 无样式。 2. 使用了 `DataTable`/`Form` 等但未安装对应 peer → 运行时找不到模块。 3. 编造不存在的 prop 或组件名 → 以 `/ai/components/.md` 的 props 与导出为准。 4. 在非 React 页面使用 `@modra/react` → 应改用 `@modra/website` 或令牌 CSS。 5. 浏览器最低要求:Chrome/Edge 111、Firefox 128、Safari 16.4。 ## 8. 延伸 - 组件站:`/components`、`/usage`、`/tokens`、`/website` - 非 SPA 接入:`/website` - 仓库文档:`docs/components.md`、`docs/website.md`、`docs/tokens.md` ## 9. MCP 服务器(可选,推荐) 远程 MCP(Streamable HTTP,无状态、只读、无需认证):`https://modra.feinian.net/mcp`。 ```bash # Claude Code claude mcp add --transport http modra https://modra.feinian.net/mcp ``` ```jsonc // Cursor:.cursor/mcp.json | VS Code:.vscode/mcp.json(顶层键为 "servers") { "mcpServers": { "modra": { "url": "https://modra.feinian.net/mcp" } } } ``` 工具: | 工具 | 用途 | | ----------------------- | ------------------------------------------------------ | | `get_integration_guide` | 返回本指南;可传 `scenario`:`react` / `next` / `html` | | `get_agents_md` | 返回已填好站点地址的 AGENTS.md,写入使用方项目 | | `list_components` | 列出全部组件(可按分组过滤) | | `get_component` | 返回单个组件的导出与 props(参数 `slug`) | | `search_components` | 按关键词搜索组件 | | `get_design_tokens` | 返回语义令牌清单与主题/品牌/密度切换方式 | 服务器描述文件:`/.well-known/mcp/server-card.json`。MCP 不可用时,退回读取 `/llms.txt` 与 `/ai/components/.md`,内容相同。 --- # 选型指引 - 选择器怎么选:select / combobox / command / tree-select / cascader / transfer - 覆盖层怎么选:dialog / alert-dialog / popconfirm / sheet - 表格怎么选:table / data-table / virtual-data-table - 日期时间怎么选:calendar / date-picker / date-range-picker / date-time-picker / time-picker / date-time-display - 反馈状态怎么选:alert / toast / empty / result - Badge 和 Tag 怎么选:badge / tag --- # alert - 分组:核心组件(Core) - 页面:/components/alert - 源码:packages/react/src/components/alert.tsx ## 导出 ```ts import { Alert, AlertDescription, AlertTitle, alertVariants } from "@modra/react"; ``` ## Props | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `variant` | 否 | `"default" \| "destructive" \| "success" \| "warning" \| "info"` | | --- # avatar - 分组:核心组件(Core) - 页面:/components/avatar - 源码:packages/react/src/components/avatar.tsx ## 导出 ```ts import { Avatar, AvatarFallback, AvatarImage } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # badge - 分组:核心组件(Core) - 页面:/components/badge - 源码:packages/react/src/components/badge.tsx ## 导出 ```ts import { Badge, badgeVariants } from "@modra/react"; ``` ## Props(BadgeProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `variant` | 否 | `"default" \| "secondary" \| "destructive" \| "success" \| "warning" \| "info" \| "outline"` | | --- # breadcrumb - 分组:核心组件(Core) - 页面:/components/breadcrumb - 源码:packages/react/src/components/breadcrumb.tsx ## 导出 ```ts import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # button - 分组:核心组件(Core) - 页面:/components/button - 源码:packages/react/src/components/button.tsx ## 导出 ```ts import { Button, buttonVariants } from "@modra/react"; ``` ## Props(ButtonProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `asChild` | 否 | `boolean` | 以子元素作为渲染根(用于包裹链接等)。 | | `loading` | 否 | `boolean` | 加载态:强制禁用并显示旋转图标,避免重复提交。 | | `variant` | 否 | `"default" \| "secondary" \| "destructive" \| "outline" \| "ghost" \| "link"` | | | `size` | 否 | `"sm" \| "md" \| "lg" \| "icon"` | | | `className` | 否 | `string` | | | `children` | 否 | `React.ReactNode` | | | `disabled` | 否 | `boolean` | | --- # card - 分组:核心组件(Core) - 页面:/components/card - 源码:packages/react/src/components/card.tsx ## 导出 ```ts import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, cardVariants } from "@modra/react"; ``` ## Props(CardProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `variant` | 否 | `"default" \| "elevated"` | | --- # checkbox - 分组:核心组件(Core) - 页面:/components/checkbox - 源码:packages/react/src/components/checkbox.tsx ## 导出 ```ts import { Checkbox } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # dialog - 分组:核心组件(Core) - 页面:/components/dialog - 源码:packages/react/src/components/dialog.tsx ## 导出 ```ts import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # dropdown-menu - 分组:核心组件(Core) - 页面:/components/dropdown-menu - 源码:packages/react/src/components/dropdown-menu.tsx ## 导出 ```ts import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@modra/react"; ``` ## Props(DropdownMenuItemProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `inset` | 否 | `boolean` | Indents the label to line up with checkbox and radio items. | | `variant` | 否 | `MenuItemVariant` | `destructive` colours the item (and its icon) with the destructive tokens. | --- # empty - 分组:核心组件(Core) - 页面:/components/empty - 源码:packages/react/src/components/empty.tsx ## 导出 ```ts import { Empty } from "@modra/react"; ``` ## Props(EmptyProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `image` | 否 | `React.ReactNode` | | | `description` | 否 | `React.ReactNode` | | --- # form - 分组:核心组件(Core) - 页面:/components/form - 源码:packages/react/src/components/form.tsx ## 导出 ```ts import { Form, FormControl, FormDescription, FormError, FormField, FormItem, FormLabel, FormList, FormMessage, useFormField } from "@modra/react"; ``` ## Props(FormProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `children` | 否 | `React.ReactNode` | | | `layout` | 否 | `FormLayout` | | | `labelWidth` | 否 | `string \| number` | | | `labelAlign` | 否 | `FormLabelAlign` | | | `disabled` | 否 | `boolean` | | | `scrollToFirstError` | 否 | `boolean \| FormScrollToFirstErrorOptions` | | | `validateMessages` | 否 | `FormValidateMessages` | Templates apply only when RHF/resolver errors have no explicit message. | --- # input - 分组:核心组件(Core) - 页面:/components/input - 源码:packages/react/src/components/input.tsx ## 导出 ```ts import { Input } from "@modra/react"; ``` ## Props(InputProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `size` | 否 | `ControlSize` | Control height; defaults to `md`. | | `className` | 否 | `string` | | | `children` | 否 | `React.ReactNode` | | | `disabled` | 否 | `boolean` | | --- # label - 分组:核心组件(Core) - 页面:/components/label - 源码:packages/react/src/components/label.tsx ## 导出 ```ts import { Label } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # pagination - 分组:核心组件(Core) - 页面:/components/pagination - 源码:packages/react/src/components/pagination.tsx ## 导出 ```ts import { Pagination } from "@modra/react"; ``` ## Props(PaginationProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `page` | 否 | `number` | | | `defaultPage` | 否 | `number` | | | `onPageChange` | 否 | `(page: number) => void` | | | `pageSize` | 否 | `number` | | | `defaultPageSize` | 否 | `number` | | | `onPageSizeChange` | 否 | `(pageSize: number) => void` | | | `total` | 是 | `number` | | | `pageSizeOptions` | 否 | `number[]` | | | `disabled` | 否 | `boolean` | | | `showSizeChanger` | 否 | `boolean` | | | `showQuickJumper` | 否 | `boolean` | | | `showTotal` | 否 | `boolean` | | | `hideOnSinglePage` | 否 | `boolean` | | --- # popover - 分组:核心组件(Core) - 页面:/components/popover - 源码:packages/react/src/components/popover.tsx ## 导出 ```ts import { Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # progress - 分组:核心组件(Core) - 页面:/components/progress - 源码:packages/react/src/components/progress.tsx ## 导出 ```ts import { Progress } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # radio-group - 分组:核心组件(Core) - 页面:/components/radio-group - 源码:packages/react/src/components/radio-group.tsx ## 导出 ```ts import { RadioGroup, RadioGroupItem } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # select - 分组:核心组件(Core) - 页面:/components/select - 源码:packages/react/src/components/select.tsx ## 导出 ```ts import { Select, SelectClearButton, SelectContent, SelectEmpty, SelectGroup, SelectItem, SelectLabel, SelectLoading, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue } from "@modra/react"; ``` ## Props(SelectClearButtonProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `onClear` | 是 | `() => void` | | | `disabled` | 否 | `boolean` | | --- # separator - 分组:核心组件(Core) - 页面:/components/separator - 源码:packages/react/src/components/separator.tsx ## 导出 ```ts import { Separator } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # sheet - 分组:核心组件(Core) - 页面:/components/sheet - 源码:packages/react/src/components/sheet.tsx ## 导出 ```ts import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # skeleton - 分组:核心组件(Core) - 页面:/components/skeleton - 源码:packages/react/src/components/skeleton.tsx ## 导出 ```ts import { Skeleton } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # switch - 分组:核心组件(Core) - 页面:/components/switch - 源码:packages/react/src/components/switch.tsx ## 导出 ```ts import { Switch } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # table - 分组:核心组件(Core) - 页面:/components/table - 源码:packages/react/src/components/table.tsx ## 导出 ```ts import { Table, TableBody, TableCaption, TableCell, TableCellStack, TableFooter, TableHead, TableHeader, TableRow } from "@modra/react"; ``` ## Props(TableProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `scrollHint` | 否 | `boolean` | Shows an edge shadow on the side(s) that have more content to scroll to, and hides it once the edge is reached. On by default; the shadow follows the writing direction. | | `containerClassName` | 否 | `string` | Internal wrapper class for consumers that provide their own scrollport. | | `wrapperClassName` | 否 | `string` | Class for the outer positioning wrapper around the scrollport and its scroll hints. | | `containerStyle` | 否 | `React.CSSProperties` | | | `scrollRegionLabel` | 否 | `string` | Accessible name for the keyboard-scrollable table region. | | `className` | 否 | `string` | | | `children` | 否 | `React.ReactNode` | | --- # tabbar - 分组:核心组件(Core) - 页面:/components/tabbar - 源码:packages/react/src/components/tabbar.tsx ## 导出 ```ts import { Tabbar } from "@modra/react"; ``` ## Props(TabbarProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `items` | 是 | `TabbarItem[]` | | | `value` | 是 | `string` | | | `onChange` | 否 | `(key: string) => void` | | | `renderItem` | 否 | `(item: TabbarItem, state: { active: boolean }) => React.ReactNode` | Render an item with a custom link component (e.g. a router Link). | | `aria-label` | 否 | `string` | | --- # tabs - 分组:核心组件(Core) - 页面:/components/tabs - 源码:packages/react/src/components/tabs.tsx ## 导出 ```ts import { Tabs, TabsCloseButton, TabsContent, TabsList, TabsTrigger } from "@modra/react"; ``` ## Props(TabsProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `variant` | 否 | `TabsVariant` | `pill` (default) is the segmented control look. `line` is the admin look: a 1px bottom border on the list and a 2px primary underline on the active tab. | | `className` | 否 | `string` | | | `children` | 否 | `React.ReactNode` | | | `disabled` | 否 | `boolean` | | --- # textarea - 分组:核心组件(Core) - 页面:/components/textarea - 源码:packages/react/src/components/textarea.tsx ## 导出 ```ts import { Textarea } from "@modra/react"; ``` ## Props(TextareaProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `className` | 否 | `string` | | | `children` | 否 | `React.ReactNode` | | --- # tooltip - 分组:核心组件(Core) - 页面:/components/tooltip - 源码:packages/react/src/components/tooltip.tsx ## 导出 ```ts import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # layout - 分组:核心组件(Core) - 页面:/components/layout - 源码:packages/react/src/components/layout.tsx ## 导出 ```ts import { AuthLayout, Col, Flex, LAYOUT_BREAKPOINTS, Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider, Row, SiderThemeProvider, Space, useBreakpoint, useSiderCollapsed, useSiderTheme } from "@modra/react"; ``` ## Props(LayoutSiderProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `breakpoint` | 否 | `Breakpoint` | | | `collapsed` | 否 | `boolean` | | | `collapsedWidth` | 否 | `number \| string` | Width when collapsed. Defaults to the `--component-layout-sider-collapsed-width` token (80px; 56px in the admin density). | | `collapsible` | 否 | `boolean` | | | `defaultCollapsed` | 否 | `boolean` | | | `onBreakpoint` | 否 | `(broken: boolean) => void` | | | `onCollapse` | 否 | `(collapsed: boolean, type: SiderCollapseType) => void` | | | `reverseArrow` | 否 | `boolean` | | | `trigger` | 否 | `React.ReactNode` | | | `width` | 否 | `number \| string` | Expanded width. Defaults to the `--component-layout-sider-width` token (256px; 224px in the admin density). | | `zeroWidthTriggerStyle` | 否 | `React.CSSProperties` | | | `theme` | 否 | `"light" \| "dark"` | | --- # accordion - 分组:组合组件(Composite) - 页面:/components/accordion - 源码:packages/react/src/components/accordion.tsx ## 导出 ```ts import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # calendar - 分组:组合组件(Composite) - 页面:/components/calendar - 源码:packages/react/src/components/calendar.tsx ## 导出 ```ts import { Calendar } from "@modra/react"; ``` ## Props(CalendarProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `mode` | 否 | `"single" \| "range"` | | | `selected` | 否 | `Date \| DateRange` | | | `onSelect` | 否 | `(value: Date \| DateRange \| undefined) => void` | | | `disabled` | 否 | `Matcher \| Matcher[]` | | | `className` | 否 | `string` | | --- # cascader - 分组:组合组件(Composite) - 页面:/components/cascader - 源码:packages/react/src/components/cascader.tsx ## 导出 ```ts import { Cascader } from "@modra/react"; ``` ## Props(CascaderProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `options` | 是 | `TreeNode[]` | | | `value` | 否 | `string[]` | | | `defaultValue` | 否 | `string[]` | | | `onValueChange` | 否 | `(value: string[]) => void` | | | `loadData` | 否 | `(path: TreeNode[]) => Promise \| TreeNode[] \| void` | Load children for a non-leaf node before entering its child level. | | `changeOnSelect` | 否 | `boolean` | Emit the selected path even when the selected node has children. | | `placeholder` | 否 | `string` | | | `disabled` | 否 | `boolean` | | | `className` | 否 | `string` | | | `data-form-control` | 否 | `boolean \| string` | Internal marker applied by FormControl for status styling. | --- # collapsible - 分组:组合组件(Composite) - 页面:/components/collapsible - 源码:packages/react/src/components/collapsible.tsx ## 导出 ```ts import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@modra/react"; ``` ## Props 无独立的 props 接口(组合式组件,参考组件页示例,或沿用原生元素属性)。 --- # combobox - 分组:组合组件(Composite) - 页面:/components/combobox - 源码:packages/react/src/components/combobox.tsx ## 导出 ```ts import { Combobox, useAsyncOptions } from "@modra/react"; ``` ## Props(ComboboxProps) | 名称 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | | `options` | 是 | `ComboboxOption[]` | | | `value` | 否 | `string` | | | `defaultValue` | 否 | `string` | | | `onValueChange` | 否 | `(value: string) => void` | | | `open` | 否 | `boolean` | | | `defaultOpen` | 否 | `boolean` | | | `onOpenChange` | 否 | `(open: boolean) => void` | | | `onSearchChange` | 否 | `(search: string) => void` | Called with the search text. The input itself updates immediately; this callback is debounced by `searchDebounce` and is not fired while an IME composition is in progress. | | `searchDebounce` | 否 | `number` | Milliseconds to wait before `onSearchChange`. Defaults to 300 when `filter` is `false`, else 0. | | `filter` | 否 | `boolean \| ComboboxFilter` | `true` (default) filters locally, `false` shows `options` as-is (remote search), or pass a custom filter function. | | `loading` | 否 | `boolean` | Keeps the previous options on screen and shows an inline indicator while true. | | `selectedOption` | 否 | `ComboboxOption` | Option shown on the trigger when the selected value is not in the current `options`. | | `disabled` | 否 | `boolean` | | | `placeholder` | 否 | `string` | | | `searchPlaceholder` | 否 | `string` | | | `emptyText` | 否 | `string` | | | `className` | 否 | `string` | | | `contentClassName` | 否 | `string` | | | `id` | 否 | `string` | Id of the trigger button, so an external `