Skip to content

Conversation

@vaebe
Copy link
Owner

@vaebe vaebe commented Nov 13, 2025

feat: 新增 Timeline 时间线组件

功能特性

新增组件

  • 新增 Timeline 时间线容器组件
  • 新增 TimelineItem 时间线项目组件

🎨 样式特性

  • 支持多种节点类型:primarysuccesswarningdangerinfo
  • 支持自定义节点颜色和尺寸(normallarge
  • 支持空心节点样式(hollow
  • 支持自定义图标和节点内容
  • 支持时间戳位置调整(topbottom
  • 支持垂直居中对齐

🌙 主题支持

  • 完整支持深色/浅色主题切换
  • 使用项目统一的主题变量系统

📚 完整文档

  • 提供 5 个详细的使用示例
  • 完整的 API 文档说明
  • 遵循项目文档规范

🧪 测试覆盖

  • 完整的单元测试覆盖
  • 测试各种 props 和功能场景

技术实现

  • 使用 JSX + TypeScript 开发
  • 遵循项目 BEM 命名规范
  • 支持插槽自定义(defaultdot
  • 完整的类型定义和验证

文件变更

packages/ccui/ui/timeline/
├── index.ts                 # 组件导出
├── src/
│   ├── timeline.tsx         # Timeline 主组件
│   ├── timeline-item.tsx    # TimelineItem 子组件
│   ├── timeline-types.ts    # 类型定义
│   └── timeline.scss        # 样式文件
└── test/
    └── timeline.test.ts     # 单元测试

packages/docs/components/timeline/
└── index.md                 # 组件文档

Summary by CodeRabbit

  • New Features

    • Added Timeline and TimelineItem components with customizable appearance, placement, colors, sizes, icons, and custom dot support.
    • Added an installable plugin entry for easy registration of Timeline components.
    • Added a namespace helper that generates semantic "is-*" class names.
  • Documentation

    • Timeline documentation and usage examples added; minor docs anchor fix.
  • Tests

    • Added comprehensive unit tests for Timeline and TimelineItem.

@coderabbitai
Copy link

coderabbitai bot commented Nov 13, 2025

Walkthrough

Adds a Timeline Vue 3 component and TimelineItem with props, styles, tests, and docs; registers both as a plugin export. Also augments the shared useNamespace hook with a new is(name) helper that returns "is-".

Changes

Cohort / File(s) Summary
Timeline components
packages/ccui/ui/timeline/src/timeline.tsx, packages/ccui/ui/timeline/src/timeline-item.tsx
New CTimeline and CTimelineItem Vue 3 components: renders timeline container and items, uses useNamespace('timeline'), and implements rendering, icon/dot slots, timestamp placement, size/type/color/hollow behavior.
Types / props
packages/ccui/ui/timeline/src/timeline-types.ts
New timelineProps, timelineItemProps, TimelineProps, TimelineItemProps, and TimelineItemType exports with validators and defaults for timestamp, hideTimestamp, center, placement, type, color, size, icon, and hollow.
Styles
packages/ccui/ui/timeline/src/timeline.scss
Full SCSS for .ccui-timeline and nested item rules: layout, tail/line, node/dot variants, size/type/color/hollow modifiers, center alignment, and timestamp positioning.
Plugin & exports
packages/ccui/ui/timeline/index.ts
Adds component install handlers, assigns Timeline.install and TimelineItem.install, named exports Timeline, TimelineItem, and a default plugin-like export with install(app) delegating to Timeline.install.
Tests
packages/ccui/ui/timeline/test/timeline.test.ts
Unit tests covering rendering, slots, timestamp visibility/placement, type/color/size/hollow variants, center alignment, icon support, and custom dot slot.
Hook enhancement
packages/ccui/ui/shared/hooks/use-namespace.ts
Adds is(name: string): string to UseNamespace and returns is from useNamespace; is returns is-<name>.
Docs & minor fix
packages/docs/components/timeline/index.md, packages/docs/components/divider/index.md
New Timeline documentation with examples and API; small anchor-case correction in Divider docs.

Sequence Diagram(s)

sequenceDiagram
    participant App as Vue App
    participant Plugin as Timeline Plugin
    participant Timeline as CTimeline
    participant Item as CTimelineItem
    participant NS as useNamespace

    App->>Plugin: install(app)
    Plugin->>App: app.component('CTimeline'), app.component('CTimelineItem')

    App->>Timeline: render (slot content includes TimelineItem)
    Timeline->>NS: useNamespace('timeline')
    Timeline->>Timeline: render <ul> wrapper with slot children
    Item->>NS: useNamespace('timeline') for class helpers
    Item->>Item: compute classes, node, timestamp based on props/slots
    Item-->>Timeline: rendered <li> element
    Timeline-->>App: rendered <ul> with children
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

  • Files needing extra attention:
    • packages/ccui/ui/timeline/src/timeline-item.tsx (render logic, slots, icon handling)
    • packages/ccui/ui/timeline/src/timeline-types.ts (prop validators and types)
    • packages/ccui/ui/timeline/src/timeline.scss (naming, specificity)
    • packages/ccui/ui/timeline/index.ts (install/export wiring)
    • packages/ccui/ui/shared/hooks/use-namespace.ts (public API addition)

Poem

🐰 I hopped along a dotted line,

Tails and nodes arranged in time.
I stamp each state with "is-" so spry,
Little markers marching by.
Hooray — a timeline made to try!

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'feat: timeline' is a generic, vague prefix-style title that doesn't convey the specific change. While it references 'timeline', it lacks concrete detail about what was added or changed. Use a more descriptive title like 'feat: add Timeline and TimelineItem components' to clearly summarize the main change for reviewers scanning history.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-timeline

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b0c527 and 87313d2.

📒 Files selected for processing (3)
  • packages/ccui/ui/timeline/index.ts (1 hunks)
  • packages/ccui/ui/timeline/src/timeline.tsx (1 hunks)
  • packages/ccui/ui/timeline/test/timeline.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/ccui/ui/timeline/index.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/ccui/ui/timeline/src/timeline.tsx (2)
packages/ccui/ui/timeline/src/timeline-types.ts (2)
  • timelineProps (4-6)
  • TimelineProps (8-8)
packages/ccui/ui/shared/hooks/use-namespace.ts (1)
  • useNamespace (31-47)
🔇 Additional comments (6)
packages/ccui/ui/timeline/src/timeline.tsx (1)

1-22: LGTM! Clean and correct implementation.

The Timeline component is well-structured and follows Vue 3 TSX patterns correctly. The use of useNamespace for BEM naming and proper slot handling with conditional checks are appropriate. The component serves as a simple container, which aligns with the PR objectives.

packages/ccui/ui/timeline/test/timeline.test.ts (5)

6-28: Comprehensive Timeline container tests.

The tests properly validate the Timeline component's rendering, element type (UL), and ability to contain multiple TimelineItem children with correct timestamp rendering. Good coverage of the basic container functionality.


31-73: Well-structured basic TimelineItem tests.

These tests effectively validate core TimelineItem functionality including timestamp rendering, content slots, the hideTimestamp prop behavior, and type variants. The assertions are clear and appropriate.


75-116: Thorough styling variant coverage.

The tests for custom color, size variants, and hollow style are comprehensive and correct. The color test appropriately validates the inline style attribute with the browser's RGB representation. Good use of class-based assertions for size and hollow variants.


118-144: Placement and alignment tests are accurate.

These tests properly verify timestamp placement options (top) and center alignment functionality, matching the features described in the PR objectives. The class-based assertions are appropriate.


146-196: Excellent coverage of icon and slot customization.

The tests comprehensively validate both string-based and component-based icons, as well as custom dot slot rendering. The test suite covers all the slot support mentioned in the PR objectives (default and dot slots). Well done!


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
packages/ccui/ui/timeline/src/timeline.tsx (1)

17-18: Consider whether the provide() call is needed.

The code provides the Timeline's slots to child components via TIMELINE_INJECTION_KEY, but the TimelineItem component doesn't appear to inject or use this data. If this is for future extensibility, consider adding a comment explaining the intent. Otherwise, this line could be removed.

packages/ccui/ui/timeline/test/timeline.test.ts (2)

12-23: Consider verifying item rendering in this test.

The test renders TimelineItem components via slots but only asserts that the container is a UL element. Consider adding assertions to verify that the items were actually rendered (e.g., checking for .ccui-timeline-item elements).


26-141: Good prop coverage, but consider adding tests for icon and dot slot.

The existing tests cover most TimelineItem props well. However, tests for the icon prop (both string and Component variants) and the custom dot slot are missing. These are important features mentioned in the documentation.

Consider adding tests like:

it('should render with string icon', () => {
  const wrapper = mount(TimelineItem, {
    props: {
      icon: 'icon-class-name',
    },
  })
  expect(wrapper.find('.ccui-timeline-item__icon').exists()).toBe(true)
})

it('should render with custom dot slot', () => {
  const wrapper = mount(TimelineItem, {
    slots: {
      dot: '<div class="custom-dot">Custom</div>',
    },
  })
  expect(wrapper.find('.ccui-timeline-item__dot').exists()).toBe(true)
  expect(wrapper.find('.custom-dot').exists()).toBe(true)
})
packages/ccui/ui/timeline/index.ts (1)

16-24: Refactor to eliminate code duplication.

The install method in the default export (lines 21-22) duplicates the logic from Timeline.install (lines 6-7). This violates the DRY principle and makes maintenance more difficult.

Apply this diff to reuse Timeline.install:

 export default {
   title: 'Timeline 时间线',
   category: '数据展示',
   status: '100%',
   install(app: App): void {
-    app.component(Timeline.name || 'CTimeline', Timeline)
-    app.component(TimelineItem.name || 'CTimelineItem', TimelineItem)
+    Timeline.install(app)
   },
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce8709a and c05e39c.

📒 Files selected for processing (9)
  • packages/ccui/ui/shared/hooks/use-namespace.ts (2 hunks)
  • packages/ccui/ui/timeline/index.ts (1 hunks)
  • packages/ccui/ui/timeline/src/timeline-item.tsx (1 hunks)
  • packages/ccui/ui/timeline/src/timeline-types.ts (1 hunks)
  • packages/ccui/ui/timeline/src/timeline.scss (1 hunks)
  • packages/ccui/ui/timeline/src/timeline.tsx (1 hunks)
  • packages/ccui/ui/timeline/test/timeline.test.ts (1 hunks)
  • packages/docs/components/divider/index.md (1 hunks)
  • packages/docs/components/timeline/index.md (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
packages/ccui/ui/timeline/test/timeline.test.ts (1)
packages/ccui/ui/timeline/index.ts (2)
  • Timeline (14-14)
  • TimelineItem (14-14)
packages/ccui/ui/timeline/src/timeline.tsx (2)
packages/ccui/ui/timeline/src/timeline-types.ts (2)
  • timelineProps (4-6)
  • TimelineProps (8-8)
packages/ccui/ui/shared/hooks/use-namespace.ts (1)
  • useNamespace (31-47)
packages/ccui/ui/timeline/src/timeline-item.tsx (2)
packages/ccui/ui/timeline/src/timeline-types.ts (2)
  • timelineItemProps (13-79)
  • TimelineItemProps (81-81)
packages/ccui/ui/shared/hooks/use-namespace.ts (1)
  • useNamespace (31-47)
🔇 Additional comments (25)
packages/docs/components/divider/index.md (1)

85-85: LGTM! Anchor link case correction.

The anchor reference has been corrected to lowercase, which is standard for HTML anchors in Markdown documentation.

packages/ccui/ui/shared/hooks/use-namespace.ts (1)

6-6: LGTM! Useful semantic helper for state classes.

The new is() helper follows the existing BEM naming pattern and provides a clean way to generate semantic state classes (e.g., is-hollow, is-top). The implementation is straightforward and consistent with the existing API.

Also applies to: 39-39, 45-45

packages/ccui/ui/timeline/src/timeline-item.tsx (5)

14-21: LGTM! Clean class composition.

The computed property correctly builds the node's CSS classes using BEM naming conventions, with appropriate conditional logic for optional modifiers.


32-43: LGTM! Flexible icon rendering.

Correctly handles both string-based icon classes and Vue component icons, with appropriate use of the h() render function for component icons.


46-63: LGTM! Well-structured node rendering.

The rendering logic correctly prioritizes the custom dot slot over the default node, and properly applies custom colors via inline styles when provided.


66-75: LGTM! Clean timestamp rendering.

The timestamp rendering logic is straightforward and correctly respects the hideTimestamp prop with appropriate early return.


77-101: LGTM! Well-structured timeline item.

The render function creates a proper timeline item structure with tail, node, and content wrapper. The conditional timestamp placement logic correctly handles both top and bottom positions.

packages/ccui/ui/timeline/src/timeline.scss (5)

3-14: LGTM! Standard timeline container styling.

The base styles properly reset list defaults and correctly hide the tail line on the last timeline item for a clean appearance.


16-57: LGTM! Thoughtful center alignment implementation.

The center alignment styling uses flexbox and transforms effectively, with appropriate special cases for first and last items to ensure the connecting line appears correctly at boundaries.


60-95: LGTM! Solid timeline item foundation.

The base item structure with relative/absolute positioning and the tail implementation using border-left for the connecting line are standard and effective approaches.


97-155: LGTM! Comprehensive node styling system.

The node variants cover all the required states with appropriate sizing, hollow styling, and type-based colors. The positioning adjustments for different sizes ensure proper alignment with the tail line.


157-187: LGTM! Complete styling coverage.

The custom dot, content, and timestamp styles provide full flexibility for timeline item customization, with appropriate placement-specific margins for timestamps.

packages/ccui/ui/timeline/src/timeline.tsx (1)

10-28: LGTM! Clean container component.

The Timeline component provides a simple, well-structured container with proper namespace-based styling. The render logic is straightforward and appropriate for a container component.

packages/ccui/ui/timeline/src/timeline-types.ts (3)

4-10: LGTM! Well-defined type foundation.

The empty timelineProps with explanatory comment and the TimelineItemType union (including empty string for the default case) are appropriate.


13-42: LGTM! Well-documented and validated props.

The timestamp, hideTimestamp, center, and placement props have clear documentation, appropriate types, sensible defaults, and proper validation for the placement prop.


43-81: LGTM! Complete prop definitions.

The remaining props (type, color, size, icon, hollow) are properly typed with appropriate validators that match the type constraints. The icon prop correctly supports both string and Component types for flexibility.

packages/docs/components/timeline/index.md (6)

1-47: LGTM! Clear introduction and basic usage.

The introduction and basic usage example provide a clear starting point for understanding the Timeline component.


49-89: LGTM! Comprehensive styling examples.

The custom node styling demo effectively showcases the various ways to customize timeline nodes (type, color, size, hollow).


91-137: LGTM! Practical timestamp placement example.

The custom timestamp demo with placement="top" clearly illustrates when and how to position timestamps above content.


139-179: LGTM! Clear center alignment demo.

The vertical center example effectively demonstrates the center prop functionality.


181-220: LGTM! Helpful custom node example.

The custom node demo using the dot slot provides a practical example of how to fully customize the timeline node appearance.


230-242: LGTM! Accurate API documentation.

The Timeline-Item Props table accurately reflects all the props defined in the implementation, with correct types, options, and defaults.

packages/ccui/ui/timeline/index.ts (3)

1-3: LGTM!

The imports are clean and follow standard Vue plugin patterns.


10-12: LGTM!

The TimelineItem.install method correctly registers only the TimelineItem component, allowing for standalone usage.


5-8: Code is correct—no action needed.

Both Timeline and TimelineItem components have their name property properly defined ('CTimeline' and 'CTimelineItem' respectively). The fallback names in the install method are defensive programming; they won't be used since the component names are already set.

@vaebe vaebe merged commit 1723410 into main Nov 13, 2025
4 checks passed
@vaebe vaebe deleted the feat-timeline branch November 13, 2025 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants