refactor: RouteLine hover 跟随封装为组件自带能力——自动监听场景内 a[data-comp=course-card](章 id 取自 href),消费方零接线;演示场景从样例页移入组件页(两 app 同步);E2E 契约随迁 components 页(站点断言改场景内定位),27/27 绿

This commit is contained in:
cqh963852 committed 2026-10-08 16:07:56 +08:00
1 parent 3c9aaf5faf
commit 061b16cf79
12 files changed
+842 -87

No files matched your search

+5 -29
View File
@@ -1,30 +1,19 @@
/** 组合场景=大部分组件拿出来的真实使用,不做解释性标注:
* 入口画像 → 课程卡与关系线 → 进度票券 → 指派块;形状散落于卡片附近空当。 */
import { Page } from '../../lib/ui'
import { ASSIGNMENT, CHAPTERS, EDGES, PROFILES } from '../../lib/chapters'
import { useState } from 'react'
import type { ChapterId } from '@stack/design-system'
import { ASSIGNMENT, CHAPTERS, PROFILES } from '../../lib/chapters'
import { MemphisCard } from '@stack/design-system'
import { RouteLine } from '@stack/design-system'
import { AssignBlock, Ticket } from '@stack/design-system'
import { EntryGuide } from '@stack/design-system'
import { Scatter } from '@stack/design-system'
import { Cross, Ring, Tremble, Tri, Wave } from '@stack/design-system'
/* 场景坐标(节点=卡描边真实边缘):卡1(40,110,250) 卡2(380,44,250,rot) 卡3(700,44,140) */
const nodes = {
1: { id: 1, borderLeft: 40, right: 290, y: 180 },
2: { id: 2, borderLeft: 380, right: 630, y: 108 },
5: { id: 5, borderLeft: 700, right: 840, y: 108 },
} as const
export function App() {
const [hovered, setHovered] = useState<ChapterId | null>(null)
return (
<Page
tag="<Examples />"
title="样例 · 组合场景"
desc="大部分组件同台真实使用:入口画像 → 课程卡与关系线 → 进度票券 → 指派块;hover 卡片,线与站点跟随浮起;形状散落于卡片附近空当。"
desc="大部分组件同台真实使用:入口画像 → 课程卡与关系线 → 进度票券 → 指派块;形状散落于卡片附近空当。"
>
<EntryGuide chapters={CHAPTERS} profiles={PROFILES} />
<div className="relative mt-8 h-[600px] overflow-hidden rounded-2xl bg-paper">
@@ -38,26 +27,13 @@ export function App() {
<Tremble size={20} key="tremble" />,
]}
/>
<RouteLine edges={EDGES} nodes={nodes} width={1160} height={600} hovered={hovered} />
<div
className="absolute left-[40px] top-[110px] w-[250px]"
onMouseEnter={() => setHovered(1)}
onMouseLeave={() => setHovered(null)}
>
<div className="absolute left-[40px] top-[110px] w-[250px]">
<MemphisCard chapter={CHAPTERS[1]} entry={1} />
</div>
<div
className="absolute left-[380px] top-[44px] w-[250px] -rotate-1"
onMouseEnter={() => setHovered(2)}
onMouseLeave={() => setHovered(null)}
>
<div className="absolute left-[380px] top-[44px] w-[250px] -rotate-1">
<MemphisCard chapter={CHAPTERS[2]} entry={2} />
</div>
<div
className="absolute left-[700px] top-[44px] w-[140px]"
onMouseEnter={() => setHovered(5)}
onMouseLeave={() => setHovered(null)}
>
<div className="absolute left-[700px] top-[44px] w-[140px]">
<MemphisCard chapter={CHAPTERS[5]} compact />
</div>
<div className="absolute left-[820px] top-[320px]"><AssignBlock {...ASSIGNMENT} /></div>