.agents/skills/ux/SKILL.md
How LobeHub products should feel, and concrete rules to get there. Use this when building or reviewing any user-facing flow. For component/styling choices see react, for wording see microcopy, for imperative modal wiring see modal.
LobeHub follows four product design values — 自然 Natural・意义感 Meaningful・ 确定性 Certainty・生长性 Growth. Read them before designing: references/design-values.md (definitions + conflict priority).
The checklists below are the execution layer. Each item is tagged with the value(s) it serves; for what those values mean, see the file above.
Every action chain must push the user forward, never dead-end or block the flow.
Every data surface has four states — design all of them, not just "has data".
A list/data page must be designed for its whole range of sizes, not just the demo data.
virtual flags, scope filters) and add them back.
✅ The default "LobeAI" (inbox) agent is virtual and excluded from the
sidebar list, so the move picker re-adds it. An empty picker must mean
"genuinely none", never "we filtered out the only option". (意义感)Never use antd Spin — it doesn't match the product's loading visual. Use a
project loader:
| Need | Component |
|---|---|
| Default loading (in-flight) | NeuralNetworkLoading from @/components/NeuralNetworkLoading (size prop) |
| Inline dots | DotsLoading / BubblesLoading from @/components |
| Branded full-page | Loading from @/components/Loading/BrandTextLoading |
| List / card placeholder | a skeleton (e.g. SkeletonList) |
When in doubt, reach for NeuralNetworkLoading — it's the default in-flight
indicator (e.g. modal "in progress" states).
The product should grow with the user — deeper power shows up as needs deepen.
The recurring trap: a feature ships only the display of a list, but edit / delete / management are never built — so the user can add something and then be stuck with it. For every entity a user can see, design its full lifecycle: create / read / update / delete, plus state transitions (enable/disable, connect/disconnect, install/uninstall). A read-only list the user can't manage breaks the flow.
The allowed operation set depends on the entity's source / ownership — decide it explicitly before building. Worked example, the tools/connectors list:
| Entity class | Add | Edit | Remove |
|---|---|---|---|
| Official / built-in (skills, tools) | — | — | ✗ not removable |
| Community (installed MCP) | install | configure | uninstall / remove |
| User-custom (custom connector) | create | edit | delete |
A feature can be fully built and still produce a broken result when the selected model — or its still-loading config — can't deliver the capability the feature depends on (for example, an agentic run on a model without tool calling). This is usually the user's configuration choice, not a defect; but if the product stays silent the user reads it as the product being broken. When a feature's success depends on a capability the current config may lack, the product owes a proactive, non-blocking reminder — a guardrail, not a gate.
Spin; use NeuralNetworkLoading / project loaders.createModal state-machine wiring for confirm/progress/done.Button usage, styling.