Skip to content
On this page

UI className 样式 AI 速查

本文档用于 AI 给动态 UI 的 DivPGroup 或少量表单组件追加 className。目标是让界面更清晰,而不是把页面写成复杂前端项目。

基础规则

className 是追加 CSS/Tailwind 类名的字符串:

lua
local tip = {
    P = {
        text = "请先填写参数,再保存配置。",
        className = "text-sm text-default-500",
        layout = { span = 12 },
    }
}

AI 生成规则:

  • 优先用于 DivP 这种展示/布局组件。
  • 不要把 className 当作业务参数,它不会进入 UICurrentValue
  • 不要依赖复杂定位类,例如 fixedabsolutetop-*left-*,除非用户明确要求。
  • 不要使用硬编码颜色,例如 text-red-500bg-blue-900。优先使用主题类:text-default-500bg-default-50border-default-200
  • 不要为了布局只堆 className。组件排列优先使用 Group.directionGroup.columnslayout.span

哪些组件支持 className

当前动态 UI 前端会把组件配置里的 className 透传给实际组件。推荐和支持情况如下:

组件是否支持推荐程度说明
Div支持强烈推荐最适合做卡片、分区、边框、背景、间距
P支持强烈推荐最适合控制说明文字大小、颜色、换行
Group支持推荐用于一组组件外层样式;排列仍优先用 direction / columns / gap
Alert支持可用通常优先用 colorvariant,必要时再加 className
Chip支持可用通常优先用 colorvariantsize
Divider支持可用可控制外边距、宽度
Image支持可用className 作用于图片组件,不是外层容器
Input支持可用简单宽度/外边距可以用;复杂内部样式用 classNames 更合适
NumberInput支持可用Input
Slider支持可用通常优先用 colorsizeshowTooltip
Select支持可用通常优先用 variantcolorsize
Autocomplete支持可用Select
Checkbox支持可用通常只做外层间距
Switch支持可用通常只做外层间距
CheckboxGroup支持可用排列优先用 orientation
RadioGroup支持可用排列优先用 orientation
Tabs部分支持谨慎普通 top/bottom Tabs 支持;placement = "start" / "end" 侧边 Tabs 是自定义渲染,顶层 className 不作为主要样式入口
Accordion支持可用适合控制整个手风琴外层;每个 ui.createTab 面板项也可加 className

AI 推荐:

  • 做布局和装饰时,优先给 DivPGroupclassName
  • 表单组件不要大量堆样式类,优先用组件自身属性:variantcolorsizeradiusisDisabled
  • 容器组件 TabsAccordion 更适合用自身属性控制,例如 variantcolorplacementselectionMode

className 与 classNames

className 是整体样式,最简单,适合小白和 AI 默认使用:

lua
nameInput.Input.className = "w-full"

部分 HeroUI 组件也支持 classNames,用于改内部插槽。AI 不要默认生成复杂 classNames,除非用户明确要求细调内部结构。

示例:普通 Tabs 可以使用 classNames

lua
local tabs = ui.createTabs({
    ui.createTab("参数", {
        { ui.createInput("name", "名称", "请输入", "") }
    })
})

tabs.Tabs.className = "w-full"
tabs.Tabs.classNames = {
    tabList = "flex-wrap",
    panel = "w-full min-w-0",
}

注意:placement = "start""end" 的侧边 Tabs 当前使用自定义侧边栏渲染,优先用 Tabs 的 placementvariantcolor 控制,不要依赖 className 精细控制侧边栏内部按钮。

常用文字样式

className用途
text-xs很小的辅助文字
text-sm说明文字
text-base普通正文
text-lg font-semibold小标题
font-medium轻强调
font-semibold标题强调
text-default-400弱说明文字
text-default-500普通说明文字
text-default-700较明显文字
text-primary主色强调
text-warning警告文字
text-danger错误文字
leading-5紧凑行高
leading-6常规行高
break-words长文本自动换行
whitespace-normal允许文本正常换行

示例:

lua
local desc = {
    P = {
        text = "这些设置会影响运行速度,请根据设备性能调整。",
        className = "text-sm leading-6 text-default-500 break-words",
        layout = { span = 12 },
    }
}

常用容器样式

className用途
p-2小内边距
p-3中小内边距
p-4常用内边距
px-4 py-3横向大、纵向中等内边距
rounded-small小圆角,推荐默认
rounded-medium中圆角
border border-default-200默认边框
bg-default-50很浅的背景
bg-default-100稍明显的背景
shadow-sm轻阴影
w-full占满宽度
overflow-hidden隐藏溢出内容

推荐普通分组卡片:

lua
local card = {
    Div = {
        className = "rounded-small border border-default-200 bg-default-50 p-4",
        item = {
            { nameInput, countInput },
            { speedSlider },
        },
        layout = { span = 12 },
    }
}

大小屏幕适配规则

动态 UI 通常显示在运行页或弹窗里,宽度可能变化很大。AI 生成布局时必须优先保证小屏不溢出。

硬性要求:制作任何动态 UI 时都必须考虑大小屏幕适配。不要只按当前电脑上的宽屏效果生成布局。

核心原则:

  • 默认按小屏写法生成,再用 sm:md:lg: 增强大屏。
  • 表单组件宽度优先用 layout.spanlayout.smlayout.mdlayout.lglayout.xl
  • 短输入组件优先使用 layout = { span = 6, lg = 3 },小屏最多 2 列,大屏最多 4 列。
  • Slider、长说明、图片、Alert、复杂分组优先使用 layout = { span = 12 }
  • 大小屏幕的样式变化使用 className 里的响应式前缀,例如 md:flex-rowmd:grid-cols-2
  • 长文字必须允许换行:使用 break-words whitespace-normal
  • 横向内容必须允许换行:使用 flex-wrap
  • 不要使用固定大宽度,例如 w-[800px]min-w-[600px]
  • 不要使用 h-screenmin-h-screen 撑开运行页。

常用断点:

前缀含义典型用途
无前缀默认,小屏优先手机、窄弹窗
sm:小屏以上稍宽弹窗
md:中屏以上普通桌面窗口
lg:大屏以上宽屏运行页

响应式 className 常用写法

小屏纵向,大屏横向

lua
className = "flex flex-col gap-3 md:flex-row md:items-center"

含义:

  • 小屏:上下排列。
  • 中屏以上:左右排列。

小屏一列,大屏两列

lua
className = "grid grid-cols-1 gap-3 md:grid-cols-2"

小屏一列,中屏两列,大屏三列

lua
className = "grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3"

宽度自适应容器

lua
className = "w-full max-w-full overflow-hidden"

长文本不撑破容器

lua
className = "text-sm leading-6 text-default-500 break-words whitespace-normal"

按钮或标签自动换行

lua
className = "flex flex-wrap items-center gap-2"

layout.span 宽度规则

表单组件的宽度优先用 layout 控制。span 是默认/小屏宽度,smmdlgxl 是响应式覆盖值。它们都按 12 栅格计算:

span效果
12占满一行
6半行,两个一行
4三分之一行,三个一行
3四分之一行,四个一行

响应式断点按当前容器宽度判断,不是按整个屏幕宽度判断:

字段生效条件
span默认,小屏
sm容器宽度 >= 480px
md容器宽度 >= 768px
lg容器宽度 >= 1024px
xl容器宽度 >= 1280px

正确写法:

lua
nameInput.Input.layout = { span = 6 }
countInput.NumberInput.layout = { span = 6 }
speed.Slider.layout = { span = 12 }

大屏 4 列、小屏最多 2 列:

lua
nameInput.Input.layout = { span = 6, lg = 3 }
countInput.NumberInput.layout = { span = 6, lg = 3 }
modeSelect.Select.layout = { span = 6, lg = 3 }
enableSwitch.Switch.layout = { span = 6, lg = 3 }
speedSlider.Slider.layout = { span = 12 }

AI 保守规则:

  • 面向小白示例时,优先 span = 12span = 6
  • 如果用户要求大屏更紧凑,使用 { span = 6, lg = 3 }
  • 输入框、下拉框、数字框在窄屏容易挤压,复杂表单优先 span = 6span = 12
  • 开关、短标签、Chip 可以用 span = 6span = 4span = 3
  • Slider 通常用 span = 12,避免滑杆太短。

响应式 Group 推荐写法

普通表单:

lua
local group = {
    Group = {
        title = "基础参数",
        direction = "grid",
        columns = 12,
        gap = 4,
        item = {
            { nameInput, countInput },
            { modeSelect, enableSwitch },
            { speedSlider },
        },
    }
}

组件 layout:

lua
nameInput.Input.layout = { span = 6, lg = 3 }
countInput.NumberInput.layout = { span = 6, lg = 3 }
modeSelect.Select.layout = { span = 6, lg = 3 }
enableSwitch.Switch.layout = { span = 6, lg = 3 }
speedSlider.Slider.layout = { span = 12 }

如果目标界面主要在小屏或窄弹窗显示,就改成全部单列:

lua
nameInput.Input.layout = { span = 12 }
countInput.NumberInput.layout = { span = 12 }
modeSelect.Select.layout = { span = 12 }
enableSwitch.Switch.layout = { span = 12 }
speedSlider.Slider.layout = { span = 12 }

注意:className 适合控制容器外观、文字、间距、纯展示排版;表单组件在 Group.direction = "grid" 里的宽度优先使用 layout,不要只靠 className = "grid-cols-4" 硬排。

小屏适配禁忌

  • 不要生成 grid-cols-4 作为默认布局;默认应从 grid-cols-1 开始。
  • 不要生成 flex items-center 后忘记 flex-wrap,否则窄屏会横向溢出。
  • 不要给 P 文本使用 whitespace-nowrap
  • 不要给容器写固定宽度:w-[700px]min-w-[500px]
  • 不要给卡片写过大的内边距:小屏下避免 p-8p-10
  • 不要把很多输入组件塞进 span = 3,小屏会显示不全。

Flex 布局类

简单横向排列可使用 Flex,但表单栅格仍优先用 Group.direction = "grid"

className用途
flex开启横向布局
flex-col纵向布局
flex-wrap空间不足自动换行
items-center垂直居中
items-start顶部对齐
justify-between两端对齐
justify-center居中
gap-2小间距
gap-3中间距
gap-4常用间距

示例:标题和标签同行显示:

lua
local header = {
    Div = {
        className = "flex items-center justify-between gap-3",
        item = {
            {
                { P = { text = "基础参数", className = "text-lg font-semibold text-default-700" } },
                ui.createChip("推荐", "primary", "flat"),
            }
        },
        layout = { span = 12 },
    }
}

Grid 布局类

动态 UI 表单更推荐使用 Group

lua
local group = {
    Group = {
        title = "基础设置",
        direction = "grid",
        columns = 12,
        gap = 4,
        item = {
            { nameInput, countInput },
            { speedSlider },
        },
    }
}

只有在做纯展示排版时,才用 className 的 grid:

lua
local info = {
    Div = {
        className = "grid grid-cols-2 gap-3",
        item = {
            {
                { P = { text = "设备:已连接", className = "text-sm text-success" } },
                { P = { text = "延迟:12ms", className = "text-sm text-default-500" } },
            }
        },
        layout = { span = 12 },
    }
}

常用组合模板

普通说明文字

lua
className = "text-sm leading-6 text-default-500"

警告说明

lua
className = "text-sm font-medium text-warning"

标题

lua
className = "text-lg font-semibold text-default-700"

普通卡片

lua
className = "rounded-small border border-default-200 bg-default-50 p-4"

紧凑卡片

lua
className = "rounded-small border border-default-200 p-3"

横向工具栏

lua
className = "flex flex-wrap items-center gap-2"

两端对齐标题栏

lua
className = "flex items-center justify-between gap-3"

完整示例

lua
local ui = require("ui_builder")

local nameInput = ui.createInput("name", "名称", "请输入名称", "")
nameInput.Input.layout = { span = 6 }

local countInput = ui.createNumberInput("count", 1, "数量", 0, 100, 1, "1~100")
countInput.NumberInput.layout = { span = 6 }

local speed = ui.createSlider("speed", 50, "速度", 0, 100, 1)
speed.Slider.layout = { span = 12 }

local page = {
    Div = {
        className = "rounded-small border border-default-200 bg-default-50 p-4",
        item = {
            {
                {
                    P = {
                        text = "基础配置",
                        className = "text-lg font-semibold text-default-700",
                        layout = { span = 12 },
                    }
                }
            },
            {
                {
                    P = {
                        text = "这里的 className 只控制外观,不影响 name、count、speed 的取值。",
                        className = "text-sm leading-6 text-default-500",
                        layout = { span = 12 },
                    }
                }
            },
            {
                {
                    Group = {
                        direction = "grid",
                        columns = 12,
                        gap = 4,
                        item = {
                            { nameInput, countInput },
                            { speed },
                        },
                    }
                }
            }
        },
        layout = { span = 12 },
    }
}

ui.buildUI({ page }, 1)
StartUI()

function onUIChanged(values)
    print("name =", values.name)
    print("count =", values.count)
    print("speed =", values.speed)
end

AI 禁忌

  • 不要为了美观生成大量随机类名。
  • 不要使用项目未确认支持的自定义类名。
  • 不要用 className 控制业务取值。
  • 不要把 className 写成 table,必须是字符串。
  • 不要在小容器里使用过大的文字类,例如 text-4xl
  • 不要用 h-screenmin-h-screen 撑开动态 UI 弹窗或运行页。