diff --git a/.cursor/rules/specify-rules.mdc b/.cursor/rules/specify-rules.mdc index d7b3916f0e..f120f3e934 100644 --- a/.cursor/rules/specify-rules.mdc +++ b/.cursor/rules/specify-rules.mdc @@ -3,6 +3,7 @@ Auto-generated from all feature plans. Last updated: 2026-01-15 ## Active Technologies +- TypeScript/React 18 + @visactor/react-vchart, @visactor/vchar (001-react-vchart-demo) - TypeScript 4.9.5 + @visactor/vchart, @visactor/vrender-components (~1.0.37), @visactor/vutils (001-scrollbar-wheel-step) @@ -22,6 +23,8 @@ npm test && npm run lint TypeScript 4.9.5: Follow standard conventions ## Recent Changes +- 001-react-vchart-demo: Added TypeScript/React 18 + @visactor/react-vchart, @visactor/vchar +- 001-react-vchart-demo: Added [if applicable, e.g., PostgreSQL, CoreData, files or N/A] - 001-scrollbar-wheel-step: Added TypeScript 4.9.5 + @visactor/vchart, @visactor/vrender-components (~1.0.37), @visactor/vutils diff --git a/common/changes/@visactor/vchart/fix-react-vchart-tooltip-render_2026-01-29-04-09.json b/common/changes/@visactor/vchart/fix-react-vchart-tooltip-render_2026-01-29-04-09.json new file mode 100644 index 0000000000..7b4418d009 --- /dev/null +++ b/common/changes/@visactor/vchart/fix-react-vchart-tooltip-render_2026-01-29-04-09.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: fix style of react-vchart tooltip render\n\n", + "type": "none", + "packageName": "@visactor/vchart" + } + ], + "packageName": "@visactor/vchart", + "email": "dingling112@gmail.com" +} \ No newline at end of file diff --git a/docs/assets/examples-react/en/component/react-common-demo.md b/docs/assets/examples-react/en/component/react-common-demo.md new file mode 100644 index 0000000000..9a4d72e7fc --- /dev/null +++ b/docs/assets/examples-react/en/component/react-common-demo.md @@ -0,0 +1,132 @@ +--- +category: examples +group: component +title: React Common Chart With Custom Tooltip +keywords: commonChart,composition,tooltip,legend +order: 0-5 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/vchart/preview/theme/theme-switch.png +option: commonChart#theme +--- + +# React Common Chart With Custom Tooltip + +## Live Demo + +```javascript livedemo template=react-vchart +const root = document.getElementById(CONTAINER_ID); +const { CommonChart } = ReactVChart; +const { useRef, useEffect } = React; + +const data0 = [ + { time: '2:00', value: 8, type: 'Douyin' }, + { time: '4:00', value: 9, type: 'Douyin' }, + { time: '6:00', value: 11, type: 'Douyin' }, + { time: '8:00', value: 14, type: 'Douyin' }, + { time: '10:00', value: 16, type: 'Douyin' }, + { time: '12:00', value: 17, type: 'Douyin' }, + { time: '14:00', value: 17, type: 'Douyin' }, + { time: '16:00', value: 16, type: 'Douyin' }, + { time: '18:00', value: 15, type: 'Douyin' }, + { time: '2:00', value: 7, type: 'Bilibili' }, + { time: '4:00', value: 8, type: 'Bilibili' }, + { time: '6:00', value: 9, type: 'Bilibili' }, + { time: '8:00', value: 10, type: 'Bilibili' }, + { time: '10:00', value: 9, type: 'Bilibili' }, + { time: '12:00', value: 12, type: 'Bilibili' }, + { time: '14:00', value: 14, type: 'Bilibili' }, + { time: '16:00', value: 12, type: 'Bilibili' }, + { time: '18:00', value: 14, type: 'Bilibili' } +]; + +const data1 = [ + { time: '2:00', value: 15, type: 'Total' }, + { time: '4:00', value: 17, type: 'Total' }, + { time: '6:00', value: 20, type: 'Total' }, + { time: '8:00', value: 24, type: 'Total' }, + { time: '10:00', value: 25, type: 'Total' }, + { time: '12:00', value: 29, type: 'Total' }, + { time: '14:00', value: 31, type: 'Total' }, + { time: '16:00', value: 28, type: 'Total' }, + { time: '18:00', value: 29, type: 'Total' } +]; + +const spec = { + type: 'common', + data: [ + { id: 'id0', values: data0 }, + { id: 'id1', values: data1 } + ], + series: [ + { + type: 'bar', + dataIndex: 0, + xField: ['time', 'type'], + yField: 'value', + seriesField: 'type' + }, + { + type: 'line', + dataIndex: 1, + xField: 'time', + yField: 'value', + seriesField: 'type' + } + ], + axes: [ + { + orient: 'bottom', + type: 'band' + }, + { + orient: 'left', + type: 'linear' + } + ], + legends: { + visible: true, + orient: 'right' + }, + tooltip: { + visible: true, + reserveDefaultTooltip: false, + enterable: true, + tooltipRender: actualTooltip => ( +
+ +
+ ) + } +}; + +const Card = () => { + const chartRef = useRef(null); + useEffect(() => { + window['vchart'] = chartRef; + }, []); + + const handleLegendItemClick = params => { + console.log(params); + }; + + return ; +}; + +ReactDom.createRoot(root).render(); + +window.customRelease = () => { + ReactDom.unmountComponentAtNode(root); +}; +``` + +## Interaction Notes + +- Clicking a legend item triggers a callback for tracking or series filtering +- Tooltip renders a custom React button component + +## Copy and Cleanup + +After copying the demo locally, call `window.customRelease()` to unmount the chart instance. + +## Tutorial + +[Theme](link) diff --git a/docs/assets/examples-react/menu.json b/docs/assets/examples-react/menu.json index 6c87fd6220..1798729516 100644 --- a/docs/assets/examples-react/menu.json +++ b/docs/assets/examples-react/menu.json @@ -75,6 +75,13 @@ "zh": "带自定义 tooltip 的组合图" } }, + { + "path": "react-common-demo", + "title": { + "en": "React Common Chart With Custom Tooltip", + "zh": "React 组合图自定义 Tooltip" + } + }, { "path": "clock", "title": { diff --git a/docs/assets/examples-react/zh/component/react-common-demo.md b/docs/assets/examples-react/zh/component/react-common-demo.md new file mode 100644 index 0000000000..5a1536e83d --- /dev/null +++ b/docs/assets/examples-react/zh/component/react-common-demo.md @@ -0,0 +1,132 @@ +--- +category: examples +group: component +title: React 组合图自定义 Tooltip +keywords: commonChart,composition,tooltip,legend +order: 0-5 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/vchart/preview/theme/theme-switch.png +option: commonChart#theme +--- + +# React 组合图自定义 Tooltip + +## 代码演示 + +```javascript livedemo template=react-vchart +const root = document.getElementById(CONTAINER_ID); +const { CommonChart } = ReactVChart; +const { useRef, useEffect } = React; + +const data0 = [ + { time: '2:00', value: 8, type: 'Douyin' }, + { time: '4:00', value: 9, type: 'Douyin' }, + { time: '6:00', value: 11, type: 'Douyin' }, + { time: '8:00', value: 14, type: 'Douyin' }, + { time: '10:00', value: 16, type: 'Douyin' }, + { time: '12:00', value: 17, type: 'Douyin' }, + { time: '14:00', value: 17, type: 'Douyin' }, + { time: '16:00', value: 16, type: 'Douyin' }, + { time: '18:00', value: 15, type: 'Douyin' }, + { time: '2:00', value: 7, type: 'Bilibili' }, + { time: '4:00', value: 8, type: 'Bilibili' }, + { time: '6:00', value: 9, type: 'Bilibili' }, + { time: '8:00', value: 10, type: 'Bilibili' }, + { time: '10:00', value: 9, type: 'Bilibili' }, + { time: '12:00', value: 12, type: 'Bilibili' }, + { time: '14:00', value: 14, type: 'Bilibili' }, + { time: '16:00', value: 12, type: 'Bilibili' }, + { time: '18:00', value: 14, type: 'Bilibili' } +]; + +const data1 = [ + { time: '2:00', value: 15, type: 'Total' }, + { time: '4:00', value: 17, type: 'Total' }, + { time: '6:00', value: 20, type: 'Total' }, + { time: '8:00', value: 24, type: 'Total' }, + { time: '10:00', value: 25, type: 'Total' }, + { time: '12:00', value: 29, type: 'Total' }, + { time: '14:00', value: 31, type: 'Total' }, + { time: '16:00', value: 28, type: 'Total' }, + { time: '18:00', value: 29, type: 'Total' } +]; + +const spec = { + type: 'common', + data: [ + { id: 'id0', values: data0 }, + { id: 'id1', values: data1 } + ], + series: [ + { + type: 'bar', + dataIndex: 0, + xField: ['time', 'type'], + yField: 'value', + seriesField: 'type' + }, + { + type: 'line', + dataIndex: 1, + xField: 'time', + yField: 'value', + seriesField: 'type' + } + ], + axes: [ + { + orient: 'bottom', + type: 'band' + }, + { + orient: 'left', + type: 'linear' + } + ], + legends: { + visible: true, + orient: 'right' + }, + tooltip: { + visible: true, + reserveDefaultTooltip: false, + enterable: true, + tooltipRender: actualTooltip => ( +
+ +
+ ) + } +}; + +const Card = () => { + const chartRef = useRef(null); + useEffect(() => { + window['vchart'] = chartRef; + }, []); + + const handleLegendItemClick = params => { + console.log(params); + }; + + return ; +}; + +ReactDom.createRoot(root).render(); + +window.customRelease = () => { + ReactDom.unmountComponentAtNode(root); +}; +``` + +## 交互说明 + +- 点击图例项会触发回调,可用于埋点或过滤系列 +- Tooltip 使用自定义 React 组件渲染按钮 + +## 复制与卸载 + +复制代码到本地运行后,如需卸载示例,可调用 `window.customRelease()` 释放图表实例。 + +## 相关教程 + +[主题](link) diff --git a/packages/react-vchart/demo/vite.config.ts b/packages/react-vchart/demo/vite.config.ts index 4c1adf0024..b05a757fec 100644 --- a/packages/react-vchart/demo/vite.config.ts +++ b/packages/react-vchart/demo/vite.config.ts @@ -1,4 +1,5 @@ -import { UserConfig, defineConfig } from 'vite'; +import type { UserConfig } from 'vite'; +import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import path from 'path'; @@ -26,6 +27,7 @@ export default defineConfig({ alias: { '@visactor/vchart': path.resolve(__dirname, '../../vchart/src/index.ts'), '@visactor/vutils-extension': path.resolve(__dirname, '../../vutils-extension/src/index.ts'), + '@visactor/vchart-extension': path.resolve(__dirname, '../../vchart-extension/src/index.ts'), ...localConf.resolve?.alias } } diff --git a/packages/react-vchart/src/components/tooltip/util.tsx b/packages/react-vchart/src/components/tooltip/util.tsx index 882ea65432..47a30b5394 100644 --- a/packages/react-vchart/src/components/tooltip/util.tsx +++ b/packages/react-vchart/src/components/tooltip/util.tsx @@ -12,10 +12,11 @@ export const initCustomTooltip = ( props: BaseChartProps, spec?: TooltipProps ) => { + const nextSpec = { ...(spec ?? {}) } as TooltipProps; let render: TooltipRender; if (spec?.tooltipRender) { render = spec.tooltipRender; - delete spec.tooltipRender; + delete nextSpec.tooltipRender; } else if (props.tooltipRender) { render = props.tooltipRender; } @@ -24,12 +25,25 @@ export const initCustomTooltip = ( let reserve: boolean; if (spec?.reserveDefaultTooltip) { reserve = spec.reserveDefaultTooltip; - delete spec.reserveDefaultTooltip; + delete nextSpec.reserveDefaultTooltip; } else { reserve = props.reserveDefaultTooltip; } + if (!reserve) { + const panelStyle = { ...(nextSpec.style?.panel ?? {}) }; + panelStyle.padding = 0; + panelStyle.border = { + ...panelStyle.border, + radius: 0 + }; + panelStyle.backgroundColor = 'unset'; + nextSpec.style = { + ...(nextSpec.style ?? {}), + panel: panelStyle + }; + } return { - ...spec, + ...nextSpec, updateElement: (el, actualTooltip, params) => { const { changePositionOnly } = params; if (changePositionOnly) { @@ -39,7 +53,6 @@ export const initCustomTooltip = ( el.style.width = 'auto'; el.style.height = 'auto'; el.style.minHeight = 'auto'; - el.style.padding = '0px'; for (let i = 0; i < el.children.length; i++) { const childNode = el.children[i] as HTMLElement; if (childNode.className !== REACT_TOOLTIP_ClASS_NAME && childNode.style.display !== 'none') { diff --git a/packages/vchart/src/plugin/components/tooltip-handler/utils/style.ts b/packages/vchart/src/plugin/components/tooltip-handler/utils/style.ts index 6e6db55ef3..3b864f7535 100644 --- a/packages/vchart/src/plugin/components/tooltip-handler/utils/style.ts +++ b/packages/vchart/src/plugin/components/tooltip-handler/utils/style.ts @@ -145,7 +145,7 @@ export const getPanelStyle = ( panelStyle.borderRadius = isValidNumber(radius) ? `${radius}px` : `${radius}`; } - if (padding) { + if (isValid(padding)) { panelPadding = normalizePadding(padding); panelStyle.padding = getPixelPropertyStr(panelPadding); } diff --git a/specs/001-react-vchart-demo/checklists/requirements.md b/specs/001-react-vchart-demo/checklists/requirements.md new file mode 100644 index 0000000000..dcbc28e132 --- /dev/null +++ b/specs/001-react-vchart-demo/checklists/requirements.md @@ -0,0 +1,34 @@ +# Specification Quality Checklist: React-VChart 文档示例补充 + +**Purpose**: Validate specification completeness and quality before proceeding to planning +**Created**: 2026-01-28 +**Feature**: [/specs/001-react-vchart-demo/spec.md](file:///Users/bytedance/Documents/opensource/vchart-2/specs/001-react-vchart-demo/spec.md) + +## Content Quality + +- [x] No implementation details (languages, frameworks, APIs) +- [x] Focused on user value and business needs +- [x] Written for non-technical stakeholders +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Success criteria are technology-agnostic (no implementation details) +- [x] All acceptance scenarios are defined +- [x] Edge cases are identified +- [x] Scope is clearly bounded +- [x] Dependencies and assumptions identified + +## Feature Readiness + +- [x] All functional requirements have clear acceptance criteria +- [x] User scenarios cover primary flows +- [x] Feature meets measurable outcomes defined in Success Criteria +- [x] No implementation details leak into specification + +## Notes + +- Items marked incomplete require spec updates before `/speckit.clarify` or `/speckit.plan` diff --git a/specs/001-react-vchart-demo/contracts/README.md b/specs/001-react-vchart-demo/contracts/README.md new file mode 100644 index 0000000000..fa462b9a28 --- /dev/null +++ b/specs/001-react-vchart-demo/contracts/README.md @@ -0,0 +1,3 @@ +# Contracts: React-VChart 文档示例补充 + +本需求为文档示例新增,不涉及对外 API 或数据接口变更,因此无独立 API 合同产出。 diff --git a/specs/001-react-vchart-demo/data-model.md b/specs/001-react-vchart-demo/data-model.md new file mode 100644 index 0000000000..155c506a89 --- /dev/null +++ b/specs/001-react-vchart-demo/data-model.md @@ -0,0 +1,19 @@ +# Data Model: React-VChart 文档示例补充 + +## Entity: 示例条目 + +- **描述**: 文档示例菜单中的一个可访问入口 +- **字段**: path, title, group, order, cover, keywords, option +- **关系**: 归属 `examples-react` 目录与 `component` 分组 + +## Entity: 示例文档 + +- **描述**: 示例条目的 Markdown 内容 +- **字段**: front matter 元信息、示例说明、livedemo 代码块 +- **关系**: 与示例条目一一对应 + +## Entity: 示例代码 + +- **描述**: React 组合图示例的代码内容 +- **字段**: 数据集、图表 spec、组件渲染与卸载逻辑 +- **关系**: 嵌入示例文档的 livedemo 代码块 diff --git a/specs/001-react-vchart-demo/plan.md b/specs/001-react-vchart-demo/plan.md new file mode 100644 index 0000000000..6869dd3181 --- /dev/null +++ b/specs/001-react-vchart-demo/plan.md @@ -0,0 +1,56 @@ +# Implementation Plan: React-VChart 文档示例补充 + +**Branch**: `001-react-vchart-demo` | **Date**: 2026-01-28 | **Spec**: [/specs/001-react-vchart-demo/spec.md](file:///Users/bytedance/Documents/opensource/vchart-2/specs/001-react-vchart-demo/spec.md) +**Input**: Feature specification from `/specs/001-react-vchart-demo/spec.md` + +## Summary + +在文档站点中新增一个 React-VChart 组合图示例,展示柱状与折线组合及自定义 tooltip 的交互。技术路径为在 `docs/assets/examples-react` 下新增示例 Markdown,使用 `livedemo template=react-vchart` 代码块承载 React 示例,并更新 `menu.json` 增加示例入口。 + +## Technical Context + +**Language/Version**: TypeScript/React 18 +**Primary Dependencies**: @visactor/react-vchart, @visactor/vchart +**Storage**: N/A +**Testing**: 通过 `rush docs` 本地验证文档示例渲染与交互 +**Target Platform**: Web(文档站点) +**Project Type**: web 文档站点(monorepo 下的 `@internal/docs`) +**Performance Goals**: 示例加载与交互无明显卡顿,tooltip 响应 < 16ms +**Constraints**: 示例需与既有文档风格一致,遵守示例目录与模板约定,尽量复用现有封面资源 +**Scale/Scope**: 新增 1 个 React 示例条目 + +## Constitution Check + +- 质量优先与规范驱动:新增示例需对齐站点结构与模板,示例代码可复制运行 +- 文档与示例:新增示例必须在文档站点验证(`rush docs`) +- 分支与评审:变更通过 PR 合入 `develop` + +通过:不涉及跨包 API 变更,无新增外部依赖;示例遵循站点示例规范。 + +## Project Structure + +### Documentation (this feature) + +```text +specs/001-react-vchart-demo/ +├── plan.md +├── research.md +├── data-model.md +├── quickstart.md +└── contracts/ +``` + +### Source Code (repository root) + +```text +docs/assets/examples-react/ +├── en/component/react-common-demo.md # 新增英文文档 +├── zh/component/react-common-demo.md # 新增中文文档 +└── menu.json # 新增目录入口 +``` + +**Structure Decision**: 采用文档站点 `examples-react` 的既有结构与 `livedemo template=react-vchart` 代码块。 + +## Complexity Tracking + +无复杂性增加,无新增模块与依赖。\*\*\* diff --git a/specs/001-react-vchart-demo/quickstart.md b/specs/001-react-vchart-demo/quickstart.md new file mode 100644 index 0000000000..155ac4fd69 --- /dev/null +++ b/specs/001-react-vchart-demo/quickstart.md @@ -0,0 +1,17 @@ +# Quickstart: React-VChart 文档示例补充 + +## 本地验证 + +1. 安装依赖 + - `rush update` +2. 启动文档站点 + - `rush docs` +3. 在示例列表中找到新增的 React-VChart 组合图示例并验证: + - 图例与提示信息显示正常 + - 示例代码可复制并在本地复现 + +## 相关文件 + +- `docs/assets/examples-react/zh/component/react-common-demo.md` +- `docs/assets/examples-react/en/component/react-common-demo.md` +- `docs/assets/examples-react/menu.json` diff --git a/specs/001-react-vchart-demo/research.md b/specs/001-react-vchart-demo/research.md new file mode 100644 index 0000000000..7e145e5279 --- /dev/null +++ b/specs/001-react-vchart-demo/research.md @@ -0,0 +1,19 @@ +# Research: React-VChart 文档示例补充 + +## Decision 1: 示例入口策略 + +- **Decision**: 在 `examples-react/component` 中新增独立示例条目,并更新 `menu.json` 增加入口。 +- **Rationale**: 符合“补充一个 demo”目标,入口更清晰,且不影响现有示例行为。 +- **Alternatives considered**: 复用并替换现有 `component/common` 示例。该方案会改变既有示例内容,不符合“补充”诉求。 + +## Decision 2: 封面资源 + +- **Decision**: 复用现有公共封面资源(避免新增图片资源)。 +- **Rationale**: 文档示例新增不引入额外资产成本,保持文档构建与发布流程稳定。 +- **Alternatives considered**: 新增专用预览图。需要额外设计与资源管理,不在本需求范围内。 + +## Decision 3: 示例代码组织 + +- **Decision**: 采用 `livedemo template=react-vchart` 代码块,直接嵌入提供的 React 代码。 +- **Rationale**: 与现有 React 示例规范一致,可直接渲染并支持复制复用。 +- **Alternatives considered**: 外部链接或独立 demo 页面。降低文档可读性,不利于快速上手。 diff --git a/specs/001-react-vchart-demo/spec.md b/specs/001-react-vchart-demo/spec.md new file mode 100644 index 0000000000..92cb4f6ccd --- /dev/null +++ b/specs/001-react-vchart-demo/spec.md @@ -0,0 +1,81 @@ +# Feature Specification: React-VChart 文档示例补充 + +**Feature Branch**: `001-react-vchart-demo` +**Created**: 2026-01-28 +**Status**: Draft +**Input**: User description: "我希望补充一个react-vchart的demo到现在的docs文件夹,主要代码如提供内容" + +## User Scenarios & Testing _(mandatory)_ + +### User Story 1 - 在文档中查看示例 (Priority: P1) + +作为文档读者,我希望在文档中快速找到并查看 React-VChart 的示例,以便理解组合图的展示效果与交互体验。 + +**Why this priority**: 这是文档核心价值,优先满足用户理解与上手的需求。 + +**Independent Test**: 通过在文档中定位示例并确认图表展示与交互要素即可完成验证。 + +**Acceptance Scenarios**: + +1. **Given** 用户进入文档,**When** 打开 React-VChart 示例入口,**Then** 能看到组合图示例被正确展示。 +2. **Given** 示例已展示,**When** 用户查看提示信息或图例,**Then** 能识别不同系列与对应数值。 + +--- + +### User Story 2 - 复制示例内容用于试验 (Priority: P2) + +作为开发者,我希望能复制完整的示例内容,以便在本地快速复现并进行修改。 + +**Why this priority**: 复用示例能显著降低学习成本,提升转化和使用效率。 + +**Independent Test**: 打开示例后可复制示例内容,并在本地复现同样的显示效果。 + +**Acceptance Scenarios**: + +1. **Given** 用户查看示例,**When** 复制示例内容,**Then** 复制内容完整且可用。 + +--- + +### User Story 3 - 理解交互行为 (Priority: P3) + +作为产品或运营同学,我希望能理解图例与提示信息的交互表现,从而评估其适用场景。 + +**Why this priority**: 交互理解有助于选择合适的图表方案,但影响范围低于示例可见性与复用性。 + +**Independent Test**: 通过查看示例中交互反馈即可验证用户对交互的理解。 + +**Acceptance Scenarios**: + +1. **Given** 示例展示完成,**When** 用户与图例或提示信息交互,**Then** 能看到明确反馈并理解交互含义。 + +--- + +### Edge Cases + +- 当示例数据为空或缺失时,示例内容仍能提示用户并保持文档可读。 +- 当页面容器较窄时,示例布局不遮挡图例与提示信息。 + +## Requirements _(mandatory)_ + +### Functional Requirements + +- **FR-001**: 系统必须在现有文档中新增一个 React-VChart 示例入口。 +- **FR-002**: 示例必须展示包含多系列柱状与单系列折线的组合图效果。 +- **FR-003**: 示例必须清晰呈现时间维度与数值维度,便于用户读取。 +- **FR-004**: 示例必须呈现图例与提示信息,使用户能区分不同系列与数值。 +- **FR-005**: 示例必须提供可复制的完整示例内容,便于用户复用。 + +### Key Entities _(include if feature involves data)_ + +- **示例入口**: 文档中的一个可访问位置,用于展示 React-VChart 示例。 +- **示例数据集**: 展示多系列与汇总趋势的时间序列数据。 +- **交互反馈**: 用户在查看图例或提示信息时获得的可见反馈内容。 + +## Success Criteria _(mandatory)_ + +### Measurable Outcomes + +- **SC-001**: 90% 的文档访客能在 2 分钟内定位到该示例入口。 +- **SC-002**: 95% 的示例访问者能成功查看任意时间点的数值信息。 +- **SC-003**: 99% 的示例访问在主流桌面浏览器中显示成功且无明显遮挡。 +- **SC-004**: 80% 的试用者认为该示例有助于理解 React-VChart 的使用方式。 diff --git a/specs/001-react-vchart-demo/tasks.md b/specs/001-react-vchart-demo/tasks.md new file mode 100644 index 0000000000..4a109e79f2 --- /dev/null +++ b/specs/001-react-vchart-demo/tasks.md @@ -0,0 +1,62 @@ +# Tasks: React-VChart 文档示例补充 + +**Input**: Design documents from `/specs/001-react-vchart-demo/` +**Prerequisites**: plan.md, spec.md, research.md, data-model.md + +## Phase 1: Setup (Shared Infrastructure) + +- [x] T001 更新菜单入口 docs/assets/examples-react/menu.json +- [x] T002 创建中文示例文档 docs/assets/examples-react/zh/component/react-common-demo.md +- [x] T003 创建英文示例文档 docs/assets/examples-react/en/component/react-common-demo.md + +--- + +## Phase 2: Foundational (Blocking Prerequisites) + +- [x] T004 在示例文档中使用 livedemo template=react-vchart 代码块 +- [x] T005 引入示例数据与 spec,并渲染 CommonChart +- [x] T006 实现自定义 tooltipRender 并保留/隐藏默认内容逻辑 + +--- + +## Phase 3: User Story 1 - 在文档中查看示例 (Priority: P1) 🎯 MVP + +**Goal**: 用户可在文档站点看到 React-VChart 组合图示例 +**Independent Test**: 运行 rush docs,示例页面展示正确 + +- [x] T007 [US1] 在中文文档插入示例说明与代码 docs/assets/examples-react/zh/component/react-common-demo.md +- [x] T008 [US1] 在英文文档插入示例说明与代码 docs/assets/examples-react/en/component/react-common-demo.md +- [ ] T009 [US1] 校验图例、轴、tooltip 显示完整 rush docs 预览 + +--- + +## Phase 4: User Story 2 - 复制示例内容用于试验 (Priority: P2) + +**Goal**: 示例代码可复制并在本地复现 +**Independent Test**: 从页面复制代码,本地运行得到一致效果 + +- [x] T010 [US2] 确保示例代码块完整且无外部依赖 docs/assets/examples-react/\*/component/react-common-demo.md +- [x] T011 [US2] 在说明中提示如何复制与卸载 ReactDom docs/assets/examples-react/\*/component/react-common-demo.md + +--- + +## Phase 5: User Story 3 - 理解交互行为 (Priority: P3) + +**Goal**: 用户理解图例点击与 tooltip 自定义行为 +**Independent Test**: 交互触发可见反馈,日志或视觉响应清晰 + +- [x] T012 [US3] 在示例中实现图例点击回调并说明 docs/assets/examples-react/\*/component/react-common-demo.md +- [x] T013 [US3] 在示例中实现自定义 tooltip 按钮渲染 docs/assets/examples-react/\*/component/react-common-demo.md + +--- + +## Phase N: Polish & Cross-Cutting Concerns + +- [x] T014 文案与元信息优化(title/keywords/cover/option) docs/assets/examples-react/\*/component/react-common-demo.md +- [x] T015 在 quickstart.md 补充本地验证步骤 specs/001-react-vchart-demo/quickstart.md + +--- + +## Dependencies & Execution Order + +- Setup → Foundational → US1 → US2 → US3 → Polish