frappe-ui

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

frappe-ui

frappe-ui

Build UIs that look and feel like Frappe products by composing frappe-ui components and styling with the library's semantic Tailwind tokens. Never hand-roll buttons, inputs, dialogs, dropdowns, etc. — pick the right component first.
通过组合frappe-ui组件并使用该库的语义化Tailwind令牌进行样式设置,构建外观和体验与Frappe产品一致的UI。切勿手动编写按钮、输入框、对话框、下拉菜单等组件——优先选择合适的组件。

Quick start

快速开始

vue
<script setup>
import { Button, Dialog, TextInput, FormControl } from 'frappe-ui'
import { ref } from 'vue'

const open = ref(false)
const name = ref('')
</script>

<template>
  <div class="p-4 bg-surface-white text-ink-gray-9">
    <Button variant="solid" theme="gray" @click="open = true">New Task</Button>
    <Dialog v-model:open="open" title="Create Task">
      <FormControl v-model="name" label="Title" required />
    </Dialog>
  </div>
</template>
vue
<script setup>
import { Button, Dialog, TextInput, FormControl } from 'frappe-ui'
import { ref } from 'vue'

const open = ref(false)
const name = ref('')
</script>

<template>
  <div class="p-4 bg-surface-white text-ink-gray-9">
    <Button variant="solid" theme="gray" @click="open = true">New Task</Button>
    <Dialog v-model:open="open" title="Create Task">
      <FormControl v-model="name" label="Title" required />
    </Dialog>
  </div>
</template>

Workflow

工作流程

  1. Pick the component, don't build one. Consult
    COMPONENTS.md
    — if any entry fits, use it. Only fall back to raw HTML for layout (grids, flex containers).
  2. Use semantic tokens, not raw colors. No
    bg-gray-100
    ,
    text-gray-900
    ,
    border-gray-300
    . Use
    bg-surface-*
    ,
    text-ink-*
    ,
    border-outline-*
    . See
    TOKENS.md
    .
  3. Follow the two-axis color rule. Component color =
    variant
    (
    solid | outline | subtle | ghost
    ) +
    theme
    (
    gray | blue | green | red | orange
    ). Never invent
    intent
    ,
    kind
    ,
    severity
    ,
    appearance
    .
  4. Wire two-way state with
    v-model
    .
    Overlays use
    v-model:open
    . Inputs use
    v-model
    . Comboboxes use
    v-model
    +
    v-model:query
    . Never
    :value
    +
    @change
    .
  5. Use the labeling contract on inputs. Every input control accepts
    label
    ,
    description
    ,
    error
    ,
    required
    — use these instead of placeholder hacks or separate
    <label>
    elements.
  6. Slot vocabulary is fixed.
    #prefix
    ,
    #suffix
    ,
    #trigger
    ,
    #empty
    ,
    #header
    ,
    #footer
    ,
    #default
    . Scoped per-item slots:
    #item-prefix
    ,
    #item-suffix
    . No
    #icon-left
    /
    #avatar-right
    .
  7. Icons are CSS classes. Render an icon as
    <span class="lucide-<name> size-4" aria-hidden="true" />
    . For frappe-ui props that accept an icon (e.g.
    Button.icon
    ,
    Dropdown
    option
    icon
    ), pass the namespaced string
    "lucide-edit"
    . Never import per-icon Vue components.
  8. Imperative for one-shot UI. Use
    dialog.confirm
    ,
    dialog.alert
    ,
    dialog.prompt
    ,
    toast.success/error/info
    — don't manually mount
    <Dialog>
    for confirmations.
  9. API calls go through
    useCall
    .
    Use the
    useCall
    composable (or
    useList
    /
    useDoc
    for higher-level shapes) for every Frappe API call. Never
    fetch
    /
    axios
    directly.
    immediate: false
    +
    submit(params)
    for writes; default behavior auto-fetches on mount. See
    COMPONENTS.md
    → Data & resources.
  1. 选择组件,而非手动构建。参考
    COMPONENTS.md
    ——如果有匹配的组件,就直接使用。仅在布局(网格、弹性容器)场景下才回退到原生HTML。
  2. 使用语义化令牌,而非原始颜色。禁止使用
    bg-gray-100
    text-gray-900
    border-gray-300
    这类原始颜色类,改用
    bg-surface-*
    text-ink-*
    border-outline-*
    。详见
    TOKENS.md
  3. 遵循双轴颜色规则。组件颜色由
    variant
    solid | outline | subtle | ghost
    ) +
    theme
    gray | blue | green | red | orange
    )决定。切勿自定义
    intent
    kind
    severity
    appearance
    这类属性。
  4. 使用
    v-model
    实现双向状态绑定
    。弹窗组件使用
    v-model:open
    ,输入组件使用
    v-model
    ,组合框使用
    v-model
    +
    v-model:query
    。禁止使用
    :value
    +
    @change
    的组合方式。
  5. 遵循输入组件的标签约定。所有输入控件都支持
    label
    description
    error
    required
    属性——使用这些属性,而非占位符技巧或单独的
    <label>
    元素。
  6. 插槽命名固定。可用插槽包括
    #prefix
    #suffix
    #trigger
    #empty
    #header
    #footer
    #default
    。针对列表项的作用域插槽:
    #item-prefix
    #item-suffix
    。禁止使用
    #icon-left
    /
    #avatar-right
    这类自定义命名插槽。
  7. 图标通过CSS类实现。使用
    <span class="lucide-<name> size-4" aria-hidden="true" />
    渲染图标。对于frappe-ui中接受图标的属性(如
    Button.icon
    Dropdown
    选项的
    icon
    ),传入带命名空间的字符串
    "lucide-edit"
    。禁止导入单个图标的Vue组件。
  8. 一次性UI使用命令式调用。使用
    dialog.confirm
    dialog.alert
    dialog.prompt
    toast.success/error/info
    ——不要为了确认操作手动挂载
    <Dialog>
    组件。
  9. API调用通过
    useCall
    实现
    。所有Frappe API调用都使用
    useCall
    组合式函数(或更高层级的
    useList
    /
    useDoc
    )。禁止直接使用
    fetch
    /
    axios
    。写入操作使用
    immediate: false
    +
    submit(params)
    ;默认行为会在组件挂载时自动获取数据。详见
    COMPONENTS.md
    → 数据与资源部分。

Reference files

参考文档

  • SETUP.md — scaffolding a fresh Vite + Vue 3 + frappe-ui project: version pinning,
    vite.config.js
    , Tailwind, PostCSS, CSS entry, plugin vs provider. Read this first when bootstrapping from scratch.
  • COMPONENTS.md — component catalog: when to reach for each one, key props, common pitfalls.
  • TOKENS.md — semantic color tokens (
    ink-*
    ,
    surface-*
    ,
    outline-*
    ), typography, spacing, radii.
  • PATTERNS.md — recipes: form pages, list pages, settings panels, empty states, confirmation flows.
  • SETUP.md —— 搭建全新的Vite + Vue 3 + frappe-ui项目:版本锁定、
    vite.config.js
    配置、Tailwind、PostCSS、CSS入口、插件与提供者。从零开始搭建项目时请先阅读此文档。
  • COMPONENTS.md —— 组件目录:各组件的适用场景、关键属性、常见陷阱。
  • TOKENS.md —— 语义化颜色令牌(
    ink-*
    surface-*
    outline-*
    )、排版、间距、圆角。
  • PATTERNS.md —— 实现方案:表单页面、列表页面、设置面板、空状态、确认流程。

Authoritative upstream docs

官方上游文档

When the bundled refs don't answer a specific API question, fetch the official LLM-friendly index:
  • https://ui.frappe.io/llms.txt — curated index of every component doc, design-system tokens page, and data-fetching guide. Always current with the published library; follow the links inside for full details on a specific component.
Prefer the upstream
llms.txt
over guessing — it lists every component's docs page and the canonical design-system / data-fetching pages.
如果本地参考文档无法解答特定API问题,请查阅官方LLM友好型索引:
  • https://ui.frappe.io/llms.txt —— 整理了所有组件文档、设计系统令牌页面和数据获取指南的索引。始终与已发布的库保持同步;如需了解特定组件的详细信息,请点击索引内的链接。
优先参考上游的
llms.txt
,而非自行猜测——它列出了每个组件的文档页面以及规范的设计系统/数据获取页面。

Anti-patterns to flag

需要规避的反模式

  • Scaffolding a fresh project with
    npm create vite
    and using whatever versions it gives you — current defaults (Vite 8 + Tailwind v4) are incompatible with frappe-ui 0.1.x. See SETUP.md.
  • Importing
    'frappe-ui/tailwind/preset'
    or
    'frappe-ui/src/style.css'
    — these paths are not in the package's
    exports
    map. Use
    'frappe-ui/tailwind'
    and
    'frappe-ui/style.css'
    .
  • Omitting
    optimizeDeps.exclude: ['frappe-ui']
    — esbuild's prebundler will choke on the package's
    ~icons/lucide/*
    virtual imports before any Vite plugin runs.
  • Forgetting
    app.use(FrappeUI)
    because you only saw
    <FrappeUIProvider>
    mentioned — both are required. Plugin handles app-level injections; provider mounts the imperative dialog/toast portals.
  • Skipping
    vue-router
    for single-page prototypes —
    <Button>
    injects
    Symbol(router)
    and warns on every render without it.
  • Hand-rolled
    <button class="bg-blue-500 ...">
    instead of
    <Button>
    .
  • Raw Tailwind palette colors (
    gray-
    ,
    blue-
    ) outside the semantic tokens.
  • intent="warning"
    /
    appearance="primary"
    /
    kind="success"
    props — collapse to
    variant
    +
    theme
    .
  • Class-injection props (
    triggerClass
    ,
    contentClass
    ). Use the component's
    data-slot
    /
    data-state
    attributes from CSS instead.
  • Manually mounting
    <Dialog>
    just to ask "are you sure?" — use
    dialog.confirm
    .
  • Bare
    v-model
    on
    <Dialog>
    for visibility — use
    v-model:open
    .
  • Placeholder-as-label on
    TextInput
    /
    Select
    /
    DatePicker
    — pass
    label
    .
  • Raw
    fetch
    /
    axios
    for API calls — use
    useCall
    (or
    useList
    /
    useDoc
    ).
  • createResource
    /
    createListResource
    /
    createDocumentResource
    in new code — those are legacy v1 APIs; the v3 composables (
    useCall
    ,
    useList
    ,
    useDoc
    ) are the recommended path.
When in doubt about an API, start at https://ui.frappe.io/llms.txt and follow the link for the component or topic in question. Source lives in the
frappe/frappe-ui
GitHub repo (
src/components/<Name>/
, plus
PHILOSOPHY.md
and
CONTEXT.md
at the repo root).
  • 使用
    npm create vite
    搭建新项目并采用默认版本——当前默认版本(Vite 8 + Tailwind v4)与frappe-ui 0.1.x不兼容。详见SETUP.md
  • 导入
    'frappe-ui/tailwind/preset'
    'frappe-ui/src/style.css'
    ——这些路径不在包的
    exports
    映射中。请使用
    'frappe-ui/tailwind'
    'frappe-ui/style.css'
  • 省略
    optimizeDeps.exclude: ['frappe-ui']
    ——esbuild预打包器会在Vite插件运行前,因包内的
    ~icons/lucide/*
    虚拟导入而报错。
  • 因只看到
    <FrappeUIProvider>
    的说明而忘记
    app.use(FrappeUI)
    ——两者都是必需的。插件负责应用级别的注入;提供者负责挂载命令式对话框/提示框的入口。
  • 单页原型不使用
    vue-router
    ——
    <Button>
    会注入
    Symbol(router)
    ,如果没有则会在每次渲染时发出警告。
  • 手动编写
    <button class="bg-blue-500 ...">
    而非使用
    <Button>
    组件。
  • 在语义化令牌之外使用原始Tailwind调色板颜色(
    gray-
    blue-
    )。
  • 使用
    intent="warning"
    /
    appearance="primary"
    /
    kind="success"
    这类属性——应简化为
    variant
    +
    theme
  • 使用类注入属性(
    triggerClass
    contentClass
    )。改用CSS中组件的
    data-slot
    /
    data-state
    属性。
  • 仅为了询问“确定吗?”而手动挂载
    <Dialog>
    ——使用
    dialog.confirm
    即可。
  • <Dialog>
    上使用裸
    v-model
    控制可见性——应使用
    v-model:open
  • TextInput
    /
    Select
    /
    DatePicker
    上用占位符代替标签——传入
    label
    属性。
  • 使用原生
    fetch
    /
    axios
    进行API调用——使用
    useCall
    (或
    useList
    /
    useDoc
    )。
  • 在新代码中使用
    createResource
    /
    createListResource
    /
    createDocumentResource
    ——这些是旧版v1 API;推荐使用v3组合式函数(
    useCall
    useList
    useDoc
    )。
如果对API有疑问,请从https://ui.frappe.io/llms.txt开始,点击对应组件或主题的链接。源代码位于`frappe/frappe-ui` GitHub仓库(
src/components/<Name>/
,以及仓库根目录的
PHILOSOPHY.md
CONTEXT.md
)。