mirror of
https://github.com/langgenius/dify.git
synced 2026-09-01 15:09:21 +08:00
docs(dify-ui): establish documentation hierarchy (#41044)
This commit is contained in:
+12
-7
@@ -8,12 +8,13 @@
|
||||
|
||||
- User-facing strings must use `web/i18n/en-US/` keys. When adding or renaming a key, update every supported locale with the correct localized value.
|
||||
- For new backend calls and migrated surfaces, use generated `consoleQuery` / `consoleClient` APIs from `@/service/client`. Do not add handwritten REST helpers or DTO mirrors, mock-backed app state, or direct edits to generated contracts.
|
||||
- Prefer `@langgenius/dify-ui/*` primitives, data attributes, and design tokens. Preserve a visible focus indicator on the final focusable element.
|
||||
- Use Dify UI `Input` for a standalone text control and `InputGroup` when a prefix, suffix, or action shares its visual surface. Reuse the Web `SearchInput` composite for its standard search, clear, and IME behavior instead of rebuilding it. See the canonical [form and input composition contract].
|
||||
- Use `Button` for actions with visible text and `IconButton` for icon-only actions. Every `IconButton` needs an `aria-label` or `aria-labelledby`, and its decorative glyph must be `aria-hidden`. Compose Menu, Popover, Toggle, and Collapsible through `render` so those primitives keep ownership of their state. See the canonical [IconButton contract].
|
||||
- Follow `docs/overlay.md` for overlay selection. Do not introduce a generic web wrapper that recreates Dify UI portal, backdrop, positioning, or z-index behavior.
|
||||
- Prefer `@langgenius/dify-ui/*` primitives, data attributes, and design tokens. Start from the [Dify UI package index] when choosing a primitive or shared contract. Preserve a visible focus indicator on the final focusable element.
|
||||
- Reuse the Web `SearchInput` composite when its search, clear, and IME contract matches the feature; otherwise follow the canonical [Input Group contract].
|
||||
- Give save and submit flows a real form boundary with visible labels and accessible errors. Use Dify UI `Form` when its structured submission and validation contract is the owner; otherwise use a native form. Follow the canonical [form contract].
|
||||
- Follow the canonical [Button contract] and [IconButton contract] for action semantics, loading, accessible names, and primitive composition. Do not add a Web wrapper that hides those contracts.
|
||||
- Follow the [Dify UI overlay contract] for primitive selection, portals, focus, and layering. Reuse the Web `Infotip` composite for an info glyph that opens explanatory content. Do not introduce a generic Web wrapper that recreates Dify UI overlay behavior.
|
||||
- For custom SVG icons, follow `../packages/iconify-collections/README.md`; do not add generated React icons under `app/components/base/icons/src/`.
|
||||
- `docs/test.md` is the single source of truth for frontend automated-test policy. Skills may route and execute that policy but must not redefine it.
|
||||
- `docs/test.md` is the single source of truth for Web automated-test policy. Skills may route and execute that policy but must not redefine it.
|
||||
|
||||
<!-- BEGIN:nextjs-agent-rules -->
|
||||
|
||||
@@ -25,5 +26,9 @@ This block is written and re-added by `next dev` — verify at `node_modules/nex
|
||||
|
||||
<!-- END:nextjs-agent-rules -->
|
||||
|
||||
[IconButton contract]: ../packages/dify-ui/README.md#icon-button-contract
|
||||
[form and input composition contract]: ../packages/dify-ui/README.md#form-contract
|
||||
[Button contract]: ../packages/dify-ui/src/button/README.md
|
||||
[Dify UI overlay contract]: ../packages/dify-ui/docs/overlays.md
|
||||
[Dify UI package index]: ../packages/dify-ui/README.md
|
||||
[IconButton contract]: ../packages/dify-ui/src/icon-button/README.md
|
||||
[Input Group contract]: ../packages/dify-ui/src/input-group/README.md
|
||||
[form contract]: ../packages/dify-ui/docs/forms.md
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
# Overlay Best Practices
|
||||
|
||||
Use `@langgenius/dify-ui/*` primitives for ordinary overlays in new and modified web code. Choose by interaction semantics, not visual shape. A feature may compose business content around a primitive, but it must not recreate generic portal, backdrop, positioning, focus, or z-index behavior.
|
||||
|
||||
## Primitive choice
|
||||
|
||||
- Use `Dialog` for modal surfaces that need focus containment, scroll locking, Escape handling, and outside-press dismissal.
|
||||
- Use `AlertDialog` only when a destructive or must-confirm decision requires an explicit response.
|
||||
- Use `Drawer` for side panels and setup or editor surfaces that follow the drawer interaction model.
|
||||
- Use `DropdownMenu` for a button-triggered action list and `ContextMenu` for pointer-context actions.
|
||||
- Choose `Select`, `Combobox`, or `Autocomplete` by the [Dify UI search and picker contract], not because each renders a popup.
|
||||
- Use `Popover` or the web `Infotip` wrapper for explanatory content, long help text, rich layout, or interactive content.
|
||||
- Use `Tooltip` only for a short, non-interactive visual label. Its trigger must already have an accessible name.
|
||||
- Use `PreviewCard` only as a non-interactive visual preview of a link destination. Essential information must remain available without the preview.
|
||||
|
||||
## Composition
|
||||
|
||||
- Prefer the most specific semantic primitive over styling a generic `Dialog`.
|
||||
- Use controlled `open` and `onOpenChange` when business state, analytics, or cleanup reacts to visibility; otherwise let the primitive own its state.
|
||||
- For a button-like overlay trigger, keep the state-owning primitive outside and use its `render` prop to render the final `Button` or `IconButton`. Do not mirror open, pressed, or expanded state in the button.
|
||||
- Use the primitive-owned content or portal part. Do not wrap a Dify UI overlay in another manual portal.
|
||||
- Keep shared overlay chrome in Dify UI and feature-specific content in the feature owner.
|
||||
|
||||
## Feature-owned exception
|
||||
|
||||
The Step-by-step Tour coachmark is a deliberate feature-owned overlay because it targets arbitrary route content and owns spotlight geometry, pointer blockers, and target interaction policy. Its manual portal belongs to `web/app/components/step-by-step-tour/coachmark.tsx`; it is not a general overlay primitive or a pattern for ordinary dialogs and popovers.
|
||||
|
||||
## Layering
|
||||
|
||||
Body-portalled Dify UI overlays use `z-50`; Toast uses `z-60`. The app root keeps an isolated stacking context, and overlays at the same layer rely on DOM order.
|
||||
|
||||
Do not add call-site z-index overrides such as `z-9999`. If an overlay is clipped or hidden, fix the owning overlay structure instead of raising a child primitive.
|
||||
|
||||
[Dify UI search and picker contract]: ../../packages/dify-ui/README.md#search-and-picker-selection
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
# Frontend Testing Guide
|
||||
|
||||
This document is the single source of truth for automated frontend tests under `web/` and `packages/dify-ui/`. Tests should protect product behavior and make refactoring safer. They are not a file-by-file completion exercise.
|
||||
This document is the single source of truth for automated frontend tests under `web/`. Tests should protect product behavior and make refactoring safer. They are not a file-by-file completion exercise. Dify UI owns its package-specific test boundary in the [Dify UI testing contract].
|
||||
|
||||
## Testing Mindset
|
||||
|
||||
@@ -37,7 +37,7 @@ Use the smallest boundary that includes the behavior owner and proves the produc
|
||||
- Use React Testing Library for component and feature behavior visible through the DOM or external side effects.
|
||||
- Use integration tests for behavior that crosses meaningful module boundaries.
|
||||
- Use a real browser for layout, responsive behavior, browser-specific APIs, animation, and focus behavior that `happy-dom` cannot represent faithfully.
|
||||
- Follow `packages/dify-ui/README.md` for the Storybook and Vitest boundary of Dify UI primitives.
|
||||
- Follow the [Dify UI testing contract] for the Storybook and Vitest boundary of Dify UI primitives.
|
||||
|
||||
Test the behavior owner. Barrel exports, pass-through wrappers, and purely presentational children do not need separate tests when the owning feature already proves their contract. Do not repeat generic behavior already owned by Base UI, React Aria, or the browser; test Dify's integration, overrides, and known regressions.
|
||||
|
||||
@@ -117,7 +117,6 @@ Mocks must preserve the public contract needed by the test. Do not mock interact
|
||||
|
||||
- Following [Vite+ testing configuration], tests under `web/` use two explicit projects in `web/vite.config.ts`. Supported commands and CI select one project explicitly: `unit` runs in `happy-dom` and loads `web/vitest.setup.ts`, while `browser` runs matching `app/**/*.browser.spec.{ts,tsx}` files in Playwright Chromium and loads `web/vitest.browser.setup.ts`. Bare `vp test` runs both registered projects.
|
||||
- Browser failures keep screenshots and Playwright traces under `web/.vitest-browser/`. CI uploads that directory only when failure artifacts exist; Browser Mode does not own coverage or report merging.
|
||||
- Tests under `packages/dify-ui/` use two Chromium Browser Mode projects: `unit` owns focused primitive contracts and loads the package styles through `vitest.setup.ts`; `storybook` owns story render, play, and accessibility contracts through `@storybook/addon-vitest`. The names identify behavior owners, not different runtimes.
|
||||
- New component and feature specs should generally use a sibling `__tests__/` directory. Existing colocated utility and hook specs may follow their owning module's convention. Cross-feature integration specs belong in `web/__tests__/`.
|
||||
- The shared `react-i18next` mock is loaded globally. Use `createReactI18nextMock` from `web/test/i18n-mock` only when a test needs custom translations.
|
||||
- For `nuqs` behavior, use the helpers in `web/test/nuqs-testing.tsx` and assert URL updates. Mock `nuqs` only when URL synchronization is explicitly outside the test contract.
|
||||
@@ -180,6 +179,7 @@ Always pass `--project unit` or `--project browser`. Bare `vp test` runs both re
|
||||
- [Testing Library query guidance]
|
||||
- [Testing Library user-event guidance]
|
||||
|
||||
[Dify UI testing contract]: ../../packages/dify-ui/docs/testing.md
|
||||
[React Testing Library documentation]: https://testing-library.com/docs/react-testing-library/intro
|
||||
[Storybook Vitest addon]: https://storybook.js.org/docs/writing-tests/integrations/vitest-addon
|
||||
[Testing Library guiding principles]: https://testing-library.com/docs/guiding-principles
|
||||
|
||||
Reference in New Issue
Block a user