diff --git a/frontend-ui/README.md b/frontend-ui/README.md index cb5877e4..17848033 100644 --- a/frontend-ui/README.md +++ b/frontend-ui/README.md @@ -39,8 +39,10 @@ interactions. `/ui-preview` remains the smaller foundation smoke-test page. See [`docs/ui-migration-standard.md`](docs/ui-migration-standard.md) for the reusable component migration, theming, responsive implementation and browser QA standard. -The current catalog covers Button, Badge, Panel, Input, NumberField, Checkbox, RadioGroup, Switch, -Rating, Select, Slider, Progress, Tabs, ItemSlot, DataTable, Tooltip, DropdownMenu and Dialog. +The current catalog covers 28 component families: Button, Badge, Panel, Input, NumberField, +Checkbox, RadioGroup, Switch, Rating, Select, Slider, Progress, Tabs, ItemSlot, DataTable, Tooltip, +DropdownMenu, Dialog, Autocomplete, Navigation, DataSection, ScrollArea, Settings, ShopItemRow, +TreeSelect, Cascader, Pagination and Popover. ## Migration rule diff --git a/frontend-ui/design-qa.md b/frontend-ui/design-qa.md index 32ee179e..13383845 100644 --- a/frontend-ui/design-qa.md +++ b/frontend-ui/design-qa.md @@ -18,6 +18,10 @@ The implementation keeps the source board's full-width dark surface, 46 px panel - NumberField: 30 px field, 23 px spinner, visible up/down arrows, and two 14 px `+10`/`-10` fast-step buttons match the source anatomy. - Tabs: 40 px list, 30 px triggers, glow layers, divider line, animated 39 × 5 px arrow marker, and line-marker variant are present. Marker movement follows Reka selection state and respects reduced motion. - Dialog: the titlebar uses the exact 45 raster frames from `windowheadereffect.img`, advances every 66 ms while focused, and hides the effect in the unfocused/reduced-motion state. +- TreeSelect: the Reka tree now opens the selected path, uses the source's flush 2 px row rhythm, + eight rarity colors, pixel branch glyph, selected border, and distinct hover/active/focus-visible + states. Desktop and 390 px evidence is captured at `tree-select-fixed-1440.png` and + `tree-select-fixed-390.png`. - Responsive: document overflow is absent at 1920, 1280, 768, and 390 widths. At 390 px, DataTable keeps a 328 px viewport with an intentional 560 px internal scroll surface. ## Required fidelity surfaces @@ -25,7 +29,10 @@ The implementation keeps the source board's full-width dark surface, 46 px panel - Fonts and typography: DCalc/SimSun control typography and Segoe UI/Chinese fallbacks retain the source hierarchy and compact line-height. - Spacing and layout rhythm: page gutters use `clamp()`, panels use container-relative padding, grids collapse at 1280/900/520 breakpoints, and atomic game-control sizes stay pixel-aligned. - Colors and tokens: blue action surfaces, brass edges, gold selection, blue focus, disabled gray, semantic status colors, and rarity colors map to DCalc CSS variables. -- Image quality and assets: stars, rarity frames, item icons, select arrow, dialog close icon, and all 45 title-effect frames use original raster assets with zero broken images. +- Image quality and assets: stars, rarity frames, item icons, dialog close icon, and all 45 + title-effect frames use original raster assets with zero broken images. Select, TreeSelect and + Autocomplete use the Design source's CSS gradient button and clipped arrow instead of a raster + arrow. - Copy and content: catalog copy differs only where it documents the Reka implementation or exposes live state; component labels and source examples remain representative. ## Interaction verification @@ -38,12 +45,32 @@ The implementation keeps the source board's full-width dark surface, 46 px panel - Select: 装备 → 材料. - DropdownMenu: `导出结果` updated live status. - Dialog: title frame changed from `4.PNG` to `5.PNG`; cancel restored focus to `打开 WindowDialog`. +- Dialog drag: the standard window moved by `120 × 66 px`; the complex window moved by + `-100 × 39 px`, while both title center deltas remained `0 px`. +- Dialog responsive boundary: at 390 px, reopening reset the desktop offset and dragging to the + upper-left stopped at the 8 px viewport margin. +- TreeSelect parent toggle: collapsing and reopening `所有稀有度` preserved the `稀有` leaf value; + the parent never received `data-selected`. +- TreeSelect keyboard: ArrowDown moved focus to `稀有` with a solid 1 px blue outline at -2 px + offset, without applying the hover brightness filter. +- TreeSelect responsive boundary: at 390 px the 319 px popup remained between x=30 and x=349, + rendered all nine rows, and retained the selected leaf. ## Comparison history - P1: NumberField step affordances were too small and FastStep was missing. Fixed with source-sized arrows and `+10`/`-10` controls. - P1: Tabs used a trigger-local pseudo marker and could not reproduce source movement. Fixed with a list-owned marker driven by active Reka tab geometry. - P1: Dialog titlebar had a static gradient only. Fixed with the exact focused 45-frame animation. +- P1: Dialog had no draggable window behavior and long header descriptions could offset the title. + Fixed with a bounded Pointer Events drag model, open/resize recentering, and title-only centered + header composition. +- P1: TreeSelect inherited native `ul` margin and padding, so rows were inset and narrowed; Portal + content also lost scoped rarity colors, and parent clicks replaced the selected leaf. Fixed with + a reset tree root, global rarity semantics, selected-path expansion, and prevented parent select + events while retaining Reka expansion. +- P2: Select, TreeSelect and Autocomplete imported the shared arrow PNG even though the Design + control anatomy is CSS-rendered. Replaced all three with one theme-aware CSS indicator contract; + retained raster assets only where the source treats them as game artwork. - P2: Button showcase omitted source state rows. Fixed with the complete three-row state matrix. - P2: shadcn-like radii, generic focus rings, menu surface, and tooltip transitions drifted from DNF styling. Replaced with source-specific square surfaces and state treatments. - P2: layout relied on fixed page spacing. Replaced page-level spacing and grids with fluid/container-responsive rules while preserving atomic raster dimensions. @@ -51,6 +78,10 @@ The implementation keeps the source board's full-width dark surface, 46 px panel ## Remaining intentional deviations - The catalog header includes theme switching and a component index that are not present on Design board 2. -- Components not yet migrated (CommandInput, TreeSelect, Cascader, navigation, ScrollArea, and complex product dialogs) are out of this comparison and must be covered in later migration batches. +- The cited full-page 1920 px comparison predates Cascader, Pagination and Popover. TreeSelect has + since received a focused Design/source-CSS comparison and browser verification; the other three + still require refreshed design-side screenshots before claiming pixel-level comparison evidence. +- SearchTree/CommandInput and domain-specific complex product dialogs remain outside this comparison. +- Navigation and ScrollArea are migrated; business call-site replacement remains a separate phase. final result: passed diff --git a/frontend-ui/docs/design-migration-matrix.md b/frontend-ui/docs/design-migration-matrix.md index c678b893..d3f5a560 100644 --- a/frontend-ui/docs/design-migration-matrix.md +++ b/frontend-ui/docs/design-migration-matrix.md @@ -15,26 +15,27 @@ mean recreating the effect from screenshots. ## Matrix -| Design source | Current target | Status | Migration notes | -| ----------------------- | --------------------------------------------------------- | ----------- | -------------------------------------------------------- | -| `foundations`, `shared` | `style/tokens`, `style/themes`, shared UI contract | Migrated | Semantic color and overridable geometry contracts | -| `button` | `ui/button` | Migrated | Preserved three-slice states; exposed density and width | -| `input` | `ui/input`, `ui/number-field` | Migrated | Removed forced inline width; normalized text metrics | -| `form-controls` | `ui/checkbox`, `ui/radio-group`, `ui/switch`, `ui/rating` | Migrated | Tokenized state colors and aligned label/control anatomy | -| `select` | `ui/select` | Migrated | Preserved popup anatomy and Reka keyboard behavior | -| `tabs` | `ui/tabs` | Migrated | Preserved list-owned animated marker | -| `slider` | `ui/slider` | Migrated | Preserved the Reka coordinate system | -| `data-table` | `ui/data-table` | Migrated | Ported hover, selected and density behavior | -| `dialog` | `ui/dialog` | Migrated | Preserved the focused title effect and focus management | -| `menu` | `ui/dropdown-menu` | Migrated | Ported source menu spacing and state tokens | -| `rarity` | `ui/item-slot` | Migrated | Retained rarity presentation as data-semantic tokens | -| `autocomplete` | `ui/autocomplete` | Migrated | Reka Combobox composition with source popup anatomy | -| `navigation` | `ui/navigation` | Migrated | Selectable navigation primitive with source assets | -| `scrollbar` | `ui/scroll-area` | Migrated | Reusable Reka viewport/scrollbar composition | -| `data-section` | `ui/data-section` | Migrated | Collapsible section and vertically centered data rows | -| `shop-item-row` | `ui/shop-item-row` | Migrated | Ported source row structure and selectable states | -| `complex-dialog` | `ui/dialog` + migrated primitives | Composition | Kept domain-independent by composing existing primitives | -| `settings` | `ui/settings` | Migrated | Responsive settings group, section and row primitives | +| Design source | Current target | Status | Migration notes | +| ----------------------- | --------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------- | +| `foundations`, `shared` | `style/tokens`, `style/themes`, shared UI contract | Migrated | Semantic color and overridable geometry contracts | +| `button` | `ui/button` | Migrated | Preserved three-slice states; exposed density and width | +| `input` | `ui/input`, `ui/number-field` | Migrated | Removed forced inline width; normalized text metrics | +| `form-controls` | `ui/checkbox`, `ui/radio-group`, `ui/switch`, `ui/rating` | Migrated | Tokenized state colors and aligned label/control anatomy | +| `select` | `ui/select`, `ui/tree-select`, `ui/cascader` | Migrated | Flat, hierarchical and two-level responsive selection; TreeSelect preserves parent-toggle and rarity states | +| `tabs` | `ui/tabs`, `ui/pagination` | Migrated | Animated list marker and compact result navigation | +| `slider` | `ui/slider` | Migrated | Preserved the Reka coordinate system | +| `data-table` | `ui/data-table` | Migrated | Ported hover, selected and density behavior | +| `dialog` | `ui/dialog` | Migrated | Preserved the focused title effect and focus management | +| `menu` | `ui/dropdown-menu` | Migrated | Ported source menu spacing and state tokens | +| `rarity` | `ui/item-slot` | Migrated | Retained rarity presentation as data-semantic tokens | +| `autocomplete` | `ui/autocomplete` | Partial | Combobox is migrated; domain SearchTree remains deferred | +| `navigation` | `ui/navigation` | Migrated | Selectable navigation primitive with source assets | +| `scrollbar` | `ui/scroll-area` | Migrated | Reusable Reka viewport/scrollbar composition | +| shared overlay help | `ui/popover`, rich `ui/tooltip` | Migrated | Portal z-index, collision and responsive width contract | +| `data-section` | `ui/data-section` | Migrated | Collapsible section and vertically centered data rows | +| `shop-item-row` | `ui/shop-item-row` | Migrated | Ported source row structure and selectable states | +| `complex-dialog` | `ui/dialog` + migrated primitives | Composition | Kept domain-independent by composing existing primitives | +| `settings` | `ui/settings` | Migrated | Responsive settings group, section and row primitives | ## Legacy replacement order @@ -45,3 +46,12 @@ Deferred: this component-library pass does not change business call sites. 3. Equipment dictionary filters, tree, cascader and pagination. 4. Skill tree, skill detail and VP controls. 5. Result tables and remaining domain-specific components. + +## Remaining gaps + +- SearchTree/CommandInput still requires a domain-neutral data and filtering contract before it can + join `src/components/ui`. +- Complex product dialogs are compositions, not a claim that every business dialog has reached + source-level visual parity. +- Existing `frontend` business call sites remain on their current components until each behavior + slice is migrated and browser-verified. diff --git a/frontend-ui/docs/ui-migration-standard.md b/frontend-ui/docs/ui-migration-standard.md index 015cf19a..557a21ad 100644 --- a/frontend-ui/docs/ui-migration-standard.md +++ b/frontend-ui/docs/ui-migration-standard.md @@ -99,6 +99,8 @@ Token 分成两层: - 建立完整状态矩阵:rest、hover、pressed、focus、disabled、selected/open。 - 动效需记录帧数、间隔、缓动、焦点条件和 reduced-motion 行为。 - 优先复用原始 PNG、字体、图标和 rarity frame,不用近似图标替代。 +- 先核对 Design 的真实实现方式:源组件使用 CSS 渐变、伪元素或 `clip-path` 构造的 + 控制图标继续使用 CSS;只有被 Design 明确作为像素素材引用的图标才引入图片。 ### 6.3 选择 Reka Primitive @@ -177,6 +179,10 @@ Reka 的 Select、Tooltip、DropdownMenu、Popover 等通常经过 Portal 和 Po - 使用确定的数字顺序加载帧,避免字符串排序造成 `10` 排在 `2` 前。 - 仅在 focused 状态推进和展示动效;unfocused 状态使用静态标题栏。 - 组件卸载时清理计时器,reduced-motion 下隐藏或静态化动效。 +- 可拖动窗口仅以标题栏空白区域作为手柄,关闭按钮和标题栏操作控件不得触发拖动。 +- 使用 Pointer Events 同时覆盖鼠标和触摸;拖动范围限制在当前视口安全边距内。 +- 每次重新打开或视口尺寸变化时恢复几何居中,避免桌面偏移泄漏到移动端。 +- 标题使用对称网格独立居中,长 Description 放入内容区,不参与标题栏宽度计算。 ### 7.5 NumberField 扩展操作 diff --git a/frontend-ui/src/components/ui/autocomplete/UiAutocomplete.vue b/frontend-ui/src/components/ui/autocomplete/UiAutocomplete.vue index a432eb0f..dd95d865 100644 --- a/frontend-ui/src/components/ui/autocomplete/UiAutocomplete.vue +++ b/frontend-ui/src/components/ui/autocomplete/UiAutocomplete.vue @@ -12,7 +12,6 @@ import { ComboboxTrigger, ComboboxViewport, } from 'reka-ui' -import selectArrow from '../../../../../design/src-web/shared/img/sprite_interface.NPK/windowcommon_2x.img/0.PNG' import { cn } from '@/lib/utils' export interface UiAutocompleteOption { @@ -56,12 +55,17 @@ function displayValue(value: string | undefined) { :display-value="displayValue" :placeholder="placeholder" /> - - + + - + {{ emptyText }} diff --git a/frontend-ui/src/components/ui/cascader/index.ts b/frontend-ui/src/components/ui/cascader/index.ts new file mode 100644 index 00000000..e62e9b1a --- /dev/null +++ b/frontend-ui/src/components/ui/cascader/index.ts @@ -0,0 +1 @@ +export { default as UiCascader, type UiCascaderGroup, type UiCascaderItem } from './UiCascader.vue' diff --git a/frontend-ui/src/components/ui/dialog/UiDialogContent.vue b/frontend-ui/src/components/ui/dialog/UiDialogContent.vue index 8fa0a092..f099be13 100644 --- a/frontend-ui/src/components/ui/dialog/UiDialogContent.vue +++ b/frontend-ui/src/components/ui/dialog/UiDialogContent.vue @@ -1,5 +1,5 @@