Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Frontend code review guidance from the Dify LLM application development platform repository.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/dify-ui.md
1# Dify UI Rules23Use these rules whenever a review touches `packages/dify-ui/` or code consuming `@langgenius/dify-ui/*`.45Before finalizing findings for those files, read the current local docs that apply:67- `packages/dify-ui/README.md`8- `packages/dify-ui/AGENTS.md`9- `web/docs/overlay.md` for floating UI10- `packages/dify-ui/src/<primitive>/index.tsx` for the primitive being changed or consumed1112## Package Boundary1314Flag in `packages/dify-ui`:1516- Imports from `web/`.17- Dependencies on Next.js, i18n, ky, Jotai, Zustand, TanStack Query, oRPC, or business APIs.18- Business-specific component behavior that belongs in `web/`.19- Multiple unrelated primitives in one component folder.2021`packages/dify-ui` is a primitive layer: Base UI headless components + `cva` + `cn` + Dify design tokens.2223## Imports And Exports2425Flag:2627- Consumer imports from `@langgenius/dify-ui` without a subpath.28- Missing `package.json#exports` entry for a new primitive.29- Internal package imports using workspace subpaths instead of relative paths.30- Exported props using internal-only types that consumers cannot import from the component subpath.3132Consumers use subpath exports such as `@langgenius/dify-ui/button`.3334## Props And State3536Flag:3738- Flattened props where related values need a discriminated union, such as `value` / `defaultValue`, `multiple` / `value`, or `clearable` / `onChange`.39- React state used only to mirror Base UI state for class names.40- JavaScript conditional class logic for visual states that the Dify UI/Base UI primitive already exposes through `data-*` attributes or CSS variables.41- Controlled props added when uncontrolled DOM state or CSS variables would be enough.42- Thin wrappers that rename Base UI parts without adding semantics.4344Prefer Base UI/Dify UI data attributes and CSS variables for visual state: `data-open`, `data-checked`, `data-disabled`, `data-highlighted`, `data-popup-open`, `group-data-*`, `peer-data-*`, `has-[:focus-visible]`, and primitive CSS variables such as anchor width or transform origin. Use JS conditional classes for product/business state that the primitive does not expose.4546## Forms4748Flag:4950- Form-like UI using unrelated `Input` and `Button` pieces without a submit boundary.51- Text-like fields not composed through `FieldRoot`, `FieldLabel`, and `FieldControl` when using Dify UI form semantics.52- Select fields using `FieldLabel` instead of `SelectLabel`.53- Slider fields using a generic label instead of `SliderLabel`.54- Checkbox/radio groups missing `FieldsetRoot` and `FieldsetLegend`.55- Field errors or descriptions rendered without `FieldDescription` / `FieldError` relationships.5657`Form` is the submit boundary. Dify UI form primitives are not a form state-management framework; business validation and schema-driven behavior belong in `web/`.5859## Overlay Contract6061Flag:6263- Legacy web overlay imports in new or modified code.64- Manual portals around Dify UI overlay primitives.65- Call-site `z-*` overrides on overlays.66- Missing root `isolation: isolate` assumptions when debugging overlay stacking.67- Repeated backdrop, z-index, or portal chrome at call sites.68- Tooltip used for infotips, long text, or interactive content.6970All Dify UI body-portalled overlays use `z-50`. Toast uses `z-60`. DOM order handles stacking between overlays.7172## Primitive Selection7374Flag:7576- `Tabs` used for simple mode/filter/view selection where `SegmentedControl` is the semantic primitive.77- `SegmentedControl` used where `tablist` / `tabpanel` semantics are required.78- `Select` used for searchable or free-form input.79- `Combobox` used for unrestricted search text where no selected option is remembered.80- `Autocomplete` used for closed-list selection.81- Tooltip or PreviewCard used for content that must be reachable on touch or by screen readers.8283Use:8485- `Autocomplete` for free-form text with optional suggestions.86- `Combobox` for searchable selected values from a collection.87- `Select` for closed, scannable option sets.88- `Popover` for infotips, help text, rich content, or interactions.8990## Bad Usage Patterns To Flag9192Flag:9394- Manually recreating UI behavior or chrome already owned by `@langgenius/dify-ui/*` or `web/app/components/base/*`, such as buttons, inputs, toggle groups, popovers, dropdown menus, alert dialogs, switches, avatars, scroll areas, toasts, borders, focus states, disabled states, segmented controls, or existing feature components.95- Styling a raw Base UI primitive directly in `web/` when a Dify UI primitive exists.96- Wrapping a Dify UI primitive in a feature component that hides its label, error, disabled, or focus contract.97- Replacing a semantic primitive with a generic `div` plus classes to match a screenshot.98- Using `Tooltip` because it is visually convenient when the content is actually help text or needs touch access.99- Adding a `z-*` override to make a child popup appear over a parent dialog.100- Adding a new app-level wrapper around Dialog, Drawer, Popover, Select, or Combobox that repeats portal/backdrop/positioner logic.101- Using dify-ui `Input` as a drop-in replacement for legacy inputs that include search, clear, copy, unit, localized placeholder, or number normalization behavior.102- Building a form row from loose text and controls instead of the matching Field/Form primitives.103- Adding component state only to style `data-open`, `data-checked`, `data-disabled`, or highlighted states that Base UI already exposes.104- Passing booleans down only so children can toggle classes already expressible with primitive `data-*` selectors.105106## Tokens, Radius, And Styling107108Flag:109110- `radius-*` class names.111- Custom Tailwind `borderRadius` extension for Figma radius values.112- Generic colors where semantic Dify tokens exist.113- Hardcoded design values where Dify tokens, component variants, or documented Figma radius mappings exist.114- `!` important modifiers used to fight primitive styles instead of fixing the variant, selector, or component composition.115- Manual class strings that duplicate primitive variants.116- `min-w-(--anchor-width)` on picker popups when it defeats viewport clamping.117118Use the Figma radius mapping from `packages/dify-ui/AGENTS.md`; for example `--radius/sm` maps to `rounded-md`, and `--radius/md` maps to `rounded-lg`.119120Use `!` only for a tightly scoped compatibility override after confirming the primitive API, data attributes, and selector structure cannot express the state.121122## Focus Details123124Flag focus rings attached to the wrong element. For example, Base UI `Slider.Thumb` focuses an internal `input[type=range]`, so the visible thumb wrapper needs `has-[:focus-visible]` rather than direct wrapper `focus-visible`.125126## Custom SVG Icons127128Flag:129130- New generated React icon components or JSON files under `web/app/components/base/icons/src/...` for custom SVG icons.131- Custom SVG icons consumed outside the Tailwind `i-custom-*` icon class pipeline.132- Generated `packages/iconify-collections/custom-*/icons.json` diffs where unrelated existing icons lost or changed intrinsic `width` or `height`.133134New custom SVG icons belong in `packages/iconify-collections/assets/...`. Regenerate with `pnpm --filter @dify/iconify-collections generate`, validate with `pnpm --filter @dify/iconify-collections check:dimensions`, and consume the generated icon with Tailwind `i-custom-*` classes.135