Skip to content

Conversation

@Killusions
Copy link
Member

@Killusions Killusions commented Dec 19, 2025

feat(chat-messages): add ai-welcome-screen component

Rebased onto #1158 (could rebase to main though)

Uses forked version of @simpl/brand for development until it ships the key visual

The OSS theme uses only the white/black icon as the key visual


Summary

This PR adds an AI welcome screen to chat-messages and broad AI chat support.

  • New components

    • SiAiWelcomeScreenComponent: welcome header, categorized prompt chips, clickable prompt suggestions.
    • SiAiChatContainerComponent: AI chat container with auto-scroll, loading-message injection, per-message action caching, markdown renderer integration, prompt suggestion wiring, and programmatic focus/scroll APIs.
    • SiToolMessageComponent: tool-call message UI with collapsible input/output panels.
    • SiAiMessageComponent / SiUserMessageComponent / SiAttachmentListComponent updates and tests.
  • Models & types

    • Consolidated chat types in chat-message.model.ts: BaseChatMessage, UserChatMessage, AiChatMessage, ToolChatMessage, TemplateChatMessage, Attachment, MessageAction (moved into chat-message.model).
    • PromptCategory and PromptSuggestion interfaces added.
  • Markdown renderer

    • getMarkdownRenderer now accepts MarkdownRendererOptions (syntaxHighlighter, latexRenderer, copy/download labels, translateSync).
    • SiMarkdownRendererComponent exposes inputs for syntaxHighlighter, latexRenderer, copy/download labels and buttons.
  • Other notable changes

    • SiChatInputComponent: signal-based wiring, implements OnDestroy, new registerParent API.
    • SiChatContainerComponent: added public scrollToBottom/scrollToTop and debounced streaming scroll logic.
    • Theme: added $element-ai-key-visual token and theme map entries; styles for welcome screen and markdown enhancements (HLJS theme, KaTeX/CSS).
    • Tests & snapshots: extensive unit tests and Playwright snapshots added for AI chat components.
    • Examples: new example pages showing syntax highlighting and KaTeX usage; dev uses a forked @simpl/brand for the key visual until upstream ships it.
  • Notes / open items

    • PR rebased onto PR feat: add experimental tool message #967 and will be merged after that.
    • Review comments mention a responsive bug: summary chips wrap individually instead of stacking and the key visual sometimes missing at large breakpoints — these should be checked.

@Killusions Killusions force-pushed the feat/add-ai-welcome-screen branch 5 times, most recently from 4d544d1 to 3228016 Compare December 22, 2025 11:39
@Killusions Killusions marked this pull request as ready for review December 22, 2025 11:39
@Killusions Killusions requested a review from a team as a code owner December 22, 2025 11:39
@coderabbitai
Copy link

coderabbitai bot commented Dec 22, 2025

📝 Walkthrough

Walkthrough

Adds a new AI chat feature set: message model interfaces (BaseChatMessage, AiChatMessage, ToolChatMessage, TemplateChatMessage, ChatMessage union), components (SiAiChatContainerComponent, SiAiWelcomeScreenComponent, SiToolMessageComponent, SiAttachmentListComponent, updated SiChatInput/SiChatContainer behaviors), and example apps/tests. Enhances markdown renderer with MarkdownRendererOptions, optional syntax highlighting and LaTeX rendering, and new translation keys. Introduces helper utilities for sanitized HTML and element/string caching, theme tokens for AI visuals, and multiple unit/playwright tests and example pages demonstrating the new chat UI and interactions.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ChatInput as SiChatInput
    participant ChatContainer as SiAiChatContainer
    participant ActionCache as MsgActionCache
    participant Renderer as MarkdownRenderer
    participant MsgComponent as MessageComponents

    User->>ChatInput: submit message / select prompt
    ChatInput->>ChatContainer: emit messageSent
    ChatContainer->>ChatContainer: append user message
    ChatContainer->>ChatContainer: shouldInjectLoadingMessage?
    ChatContainer->>ChatContainer: inject AI loading message (if needed)
    ChatContainer->>ActionCache: getMessageActions(message)
    alt cached
        ActionCache-->>ChatContainer: cached actions
    else not cached
        ActionCache->>ActionCache: compute primary/secondary actions
        ActionCache-->>ChatContainer: return actions
    end
    ChatContainer->>Renderer: render message content (syntax/LaTeX/translate options)
    Renderer-->>ChatContainer: rendered Node
    ChatContainer->>MsgComponent: route message to appropriate component (user/ai/tool/template)
    MsgComponent-->>User: display content, actions, attachments, collapsible tool panels
Loading

Possibly related PRs

Suggested labels

released

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(chat-messages): add ai-welcome-screen component' accurately and concisely describes the primary change in the pull request, which adds a new ai-welcome-screen component to the chat-messages module.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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: 16

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c0f171 and 3228016.

⛔ Files ignored due to path filters (11)
  • package-lock.json is excluded by !**/package-lock.json
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-light-linux.png is excluded by !**/*.png
📒 Files selected for processing (68)
  • .npmrc
  • api-goldens/element-ng/chat-messages/index.api.md
  • api-goldens/element-ng/markdown-renderer/index.api.md
  • api-goldens/element-ng/translate/index.api.md
  • docs/components/chat-messages/chat-message.md
  • docs/patterns/ai/ai-chat.md
  • package.json
  • playwright/e2e/element-examples/static.spec.ts
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yaml
  • projects/dashboards-demo/src/styles.scss
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/message-action.model.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-chat-input.component.ts
  • projects/element-ng/chat-messages/si-chat-message.component.scss
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • projects/element-ng/link/si-link.directive.ts
  • projects/element-ng/markdown-renderer/markdown-renderer.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts
  • projects/element-ng/status-bar/si-status-bar.component.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • projects/element-theme/src/styles/components/_markdown-hljs-theme.scss
  • projects/element-theme/src/styles/components/_markdown.scss
  • projects/element-theme/src/styles/variables/_semantic-tokens.scss
  • projects/element-theme/src/theme/_theme-element.scss
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • src/app/examples/si-chat-messages/si-ai-message.ts
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.html
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.ts
  • src/app/examples/si-chat-messages/si-chat-container.html
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • src/app/examples/si-chat-messages/si-chat-input.html
  • src/app/examples/si-chat-messages/si-tool-message.html
  • src/app/examples/si-chat-messages/si-tool-message.ts
  • src/app/examples/si-chat-messages/si-user-message.ts
  • src/app/examples/si-markdown-renderer/si-markdown-renderer.html
  • src/app/examples/si-markdown-renderer/si-markdown-renderer.ts
  • src/assets/sample-markdown.md
  • src/styles.scss
💤 Files with no reviewable changes (3)
  • projects/element-ng/status-bar/si-status-bar.component.ts
  • projects/element-ng/link/si-link.directive.ts
  • projects/element-ng/chat-messages/message-action.model.ts
🧰 Additional context used
🧠 Learnings (26)
📚 Learning: 2025-12-09T14:31:33.543Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:14-50
Timestamp: 2025-12-09T14:31:33.543Z
Learning: In projects/element-ng/chat-messages/si-ai-chat-container.component.html, message IDs can change, so tracking by message.id is not appropriate. The component uses `track message` (object identity) which is the correct approach for this use case.

Applied to files:

  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • docs/components/chat-messages/chat-message.md
  • src/app/examples/si-chat-messages/si-ai-message.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • src/app/examples/si-chat-messages/si-tool-message.html
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-chat-message.component.scss
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • src/app/examples/si-chat-messages/si-user-message.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • src/app/examples/si-chat-messages/si-tool-message.ts
  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/index.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • src/app/examples/si-chat-messages/si-chat-container.html
  • projects/element-ng/chat-messages/si-chat-input.component.ts
📚 Learning: 2025-11-18T12:37:30.510Z
Learnt from: Killusions
Repo: siemens/element PR: 1040
File: projects/element-ng/chat-messages/si-chat-input.component.ts:338-349
Timestamp: 2025-11-18T12:37:30.510Z
Learning: In projects/element-ng/chat-messages/si-chat-input.component.ts, the interrupt behavior is intentionally different for button clicks vs Enter key: the button can emit interrupt even without content, but pressing Enter requires content or attachments (canSend() must be true) to emit interrupt.

Applied to files:

  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • src/app/examples/si-chat-messages/si-chat-input.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • src/app/examples/si-chat-messages/si-chat-container.html
  • projects/element-ng/chat-messages/si-chat-input.component.ts
📚 Learning: 2025-12-15T10:05:59.100Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1193
File: projects/element-ng/search-bar/si-search-bar.component.spec.ts:21-28
Timestamp: 2025-12-15T10:05:59.100Z
Learning: In tests that rely on Jasmine's fake clock to control time-based RxJS operators (e.g., debounceTime), use jasmine.clock().install() together with jasmine.clock().mockDate() to enable precise timing control. Without mockDate, scheduler-based operators may not respond to the fake clock. Apply this guidance to spec files (e.g., any file named *.spec.ts or *.spec.js) that test time-sensitive behavior, ensuring you install and mockDate before advancing time in tests.

Applied to files:

  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • playwright/e2e/element-examples/static.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-17T04:34:55.597Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1173
File: src/app/examples/si-charts/interactive/interactive.ts:5-5
Timestamp: 2025-12-17T04:34:55.597Z
Learning: Guideline: In Angular projects using OnPush change detection (zoneless mode), you only need to call ChangeDetectorRef.markForCheck() for asynchronous operations (e.g., setTimeout, setInterval, Promises, Observables) where a change is not automatically detected. Event handlers triggered by Angular template bindings (click, input, etc.) will trigger change detection automatically and do not require explicit markForCheck() calls. Apply this broadly to TS files within Angular components/services that use OnPush; use markForCheck() selectively for async work where change detection wouldn’t run otherwise.

Applied to files:

  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-message.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • playwright/e2e/element-examples/static.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • src/app/examples/si-markdown-renderer/si-markdown-renderer.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts
  • src/app/examples/si-chat-messages/si-user-message.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/markdown-renderer/markdown-renderer.ts
  • src/app/examples/si-chat-messages/si-tool-message.ts
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • projects/element-ng/chat-messages/si-chat-input.component.ts
📚 Learning: 2025-12-09T14:33:54.441Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: src/app/examples/si-chat-messages/si-ai-message.ts:24-43
Timestamp: 2025-12-09T14:33:54.441Z
Learning: In src/app/examples/ (example/demo code) directories, allow and expect code duplication. Treat duplication as acceptable for demonstration code that aims to illustrate usage rather than enforce DRY. Do not enforce refactoring to remove duplication in example files; focus on readability and clarity of examples. This applies to all TypeScript files under src/app/examples (including nested subdirectories like si-chat-messages).

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-message.ts
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.ts
  • src/app/examples/si-markdown-renderer/si-markdown-renderer.ts
  • src/app/examples/si-chat-messages/si-user-message.ts
  • src/app/examples/si-chat-messages/si-tool-message.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-09T14:32:34.036Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:21-47
Timestamp: 2025-12-09T14:32:34.036Z
Learning: In projects/element-ng/chat-messages, nested if blocks are preferred over switch statements for branching on message types in Angular templates.

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-chat-message.component.scss
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/index.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • src/app/examples/si-chat-messages/si-chat-container.html
📚 Learning: 2025-12-04T11:54:31.132Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1133
File: projects/element-ng/tour/si-tour.service.spec.ts:21-26
Timestamp: 2025-12-04T11:54:31.132Z
Learning: In the siemens/element repository, all components are standalone by default and do not require the explicit `standalone: true` flag. Components should be added to the `imports` array in TestBed configuration, not the `declarations` array.

Applied to files:

  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
📚 Learning: 2025-12-15T07:16:53.762Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:92-105
Timestamp: 2025-12-15T07:16:53.762Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits must be used instead of fixture.whenStable() to avoid injector destroyed errors during mount/unmount operations in zoneless mode. The GridStack timing-dependent operations require actual async delays.

Applied to files:

  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-01T04:01:27.365Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1099
File: projects/element-ng/accordion/si-accordion.component.spec.ts:39-43
Timestamp: 2025-12-01T04:01:27.365Z
Learning: With Angular 20 and esbuild, synchronous `TestBed.configureTestingModule(...).compileComponents()` calls work correctly even when components use external templates (templateUrl), because esbuild pre-compiles templates at build time. The async/await pattern is not required in this scenario.

Applied to files:

  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
📚 Learning: 2025-12-11T10:09:01.564Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1151
File: projects/element-ng/auto-collapsable-list/si-auto-collapsable-list.directive.spec.ts:83-104
Timestamp: 2025-12-11T10:09:01.564Z
Learning: In the auto-collapsable-list directive tests (projects/element-ng/auto-collapsable-list/si-auto-collapsable-list.directive.spec.ts), jasmine.clock() successfully controls the directive's setTimeout-based layout logic in zoneless mode. Mock timers work fine here, unlike in select component overflow tests where real setTimeout waits are required.

Applied to files:

  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-17T14:01:05.705Z
Learnt from: dauriamarco
Repo: siemens/element PR: 908
File: projects/element-ng/side-panel/si-side-panel.component.ts:70-74
Timestamp: 2025-12-17T14:01:05.705Z
Learning: In the Element side-panel component (projects/element-ng/side-panel/si-side-panel.component.ts), the `xxxlMinimum` breakpoint (1920px) is intentionally hardcoded as a private static constant rather than being part of the configurable `Breakpoints` interface. This design preserves full Bootstrap compatibility (which only defines breakpoints up to xxl/1400px) while allowing Element to handle ultra-wide screens explicitly without affecting the standard breakpoint configuration.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-chat-container.component.scss
📚 Learning: 2025-12-09T14:32:26.166Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:21-47
Timestamp: 2025-12-09T14:32:26.166Z
Learning: In Angular templates, prefer using nested *ngIf blocks over *ngSwitch for branching on message types within the chat-messages components. Use *ngIf with else branches to handle distinct cases and avoid complex switch logic in HTML templates. This guideline applies to all HTML templates under projects/element-ng/chat-messages.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
📚 Learning: 2025-12-15T07:17:06.981Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts:37-49
Timestamp: 2025-12-15T07:17:06.981Z
Learning: In widget-instance-editor-dialog component tests (projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing component initialization. This is likely due to the component's lifecycle behavior or modal initialization timing that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-15T07:16:32.082Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:69-80
Timestamp: 2025-12-15T07:16:32.082Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing grid item rendering and initialization. This is likely due to gridstack library's initialization timing or lifecycle behavior that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-08T11:25:51.584Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/si-select.component.spec.ts:511-516
Timestamp: 2025-12-08T11:25:51.584Z
Learning: In the select component overflow tests (projects/element-ng/select/si-select.component.spec.ts), jasmine.clock() cannot be used to control the timing for overflow item detection. Real setTimeout waits must be used instead, likely due to ResizeObserver or debounced layout calculations that jasmine.clock() cannot control in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-08T11:25:20.861Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/si-select.component.spec.ts:204-205
Timestamp: 2025-12-08T11:25:20.861Z
Learning: In zoneless Angular tests (using provideZonelessChangeDetection), calling fixture.changeDetectorRef.markForCheck() before fixture.detectChanges() is required even for components using the default change detection strategy (not OnPush). This differs from zone.js-based testing where markForCheck is primarily needed only for OnPush components.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-04T05:50:17.637Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1135
File: projects/element-ng/tree-view/si-tree-view.component.spec.ts:953-964
Timestamp: 2025-12-04T05:50:17.637Z
Learning: In the siemens/element repository, when making tree-view tests zoneless-ready, jasmine.clock() should be used to mimic setTimeouts even in zoneless mode, as the component implementation relies on setTimeout calls that need to be controlled in tests.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
📚 Learning: 2025-12-08T11:24:45.272Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/options/si-select-lazy-options.directive.spec.ts:67-85
Timestamp: 2025-12-08T11:24:45.272Z
Learning: In select lazy options tests (projects/element-ng/select/options/si-select-lazy-options.directive.spec.ts), jasmine.clock() cannot control RxJS debounceTime in zoneless mode. Real setTimeout waits must be used instead for tests involving search debouncing.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
📚 Learning: 2025-12-04T05:50:38.735Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1135
File: projects/element-ng/tree-view/si-tree-view.component.spec.ts:1244-1245
Timestamp: 2025-12-04T05:50:38.735Z
Learning: In zoneless Angular tests with OnPush components, calling `await runOnPushChangeDetection(fixture)` followed by `await fixture.whenStable()` is NOT redundant. The `runOnPushChangeDetection` helper forces change detection to run for OnPush components, while `whenStable()` waits for all async operations to complete. Both are necessary and serve different purposes.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-09T14:19:34.846Z
Learnt from: Killusions
Repo: siemens/element PR: 967
File: package.json:153-153
Timestamp: 2025-12-09T14:19:34.846Z
Learning: In library projects like element-ng, optional features that are provided through callback/function parameters (e.g., syntaxHighlighter in markdown renderer) should not have their implementation dependencies (e.g., highlight.js) listed in the library's dependencies. These should remain in devDependencies for demo/example purposes, and consuming applications should install them directly if they choose to use those features.

Applied to files:

  • src/app/examples/si-markdown-renderer/si-markdown-renderer.ts
📚 Learning: 2025-12-16T16:19:17.950Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1207
File: playwright/snapshots/si-filtered-search.spec.ts-snapshots/si-filtered-search--si-filtered-search-playground--data-entered.yaml:38-38
Timestamp: 2025-12-16T16:19:17.950Z
Learning: Do not review files in the playwright/snapshots directory, as they contain auto-generated test artifacts. Exclude any YAML snapshot files under playwright/snapshots from code reviews in the siemens/element repository. If a YAML file is not an auto-generated snapshot, verify its origin before skipping.

Applied to files:

  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yaml
📚 Learning: 2025-12-03T13:29:01.075Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1058
File: docs/components/pages/landing-page.md:34-36
Timestamp: 2025-12-03T13:29:01.075Z
Learning: In Markdown blockquotes with numbered sequences, escaping only the first number (e.g., `\1.`) is sufficient to prevent auto-numbering for the entire sequence. Subsequent numbers (2., 3., etc.) do not need individual escaping.

Applied to files:

  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yaml
  • src/assets/sample-markdown.md
📚 Learning: 2025-12-05T08:00:38.407Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1151
File: projects/element-ng/typeahead/si-typeahead.directive.spec.ts:114-121
Timestamp: 2025-12-05T08:00:38.407Z
Learning: In the typeahead test suite (projects/element-ng/typeahead/si-typeahead.directive.spec.ts), jasmine.clock() must be installed in beforeAll and uninstalled in afterAll (not beforeEach/afterEach) because using per-test clock installation causes schedulerFunction-related issues in these specific tests.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
📚 Learning: 2025-12-04T10:35:45.465Z
Learnt from: Killusions
Repo: siemens/element PR: 1147
File: docs/fundamentals/ux-text-style-guide/dialogs-and-buttons.md:81-84
Timestamp: 2025-12-04T10:35:45.465Z
Learning: In docs/fundamentals/ux-text-style-guide/dialogs-and-buttons.md, the Clear content section's Do's intentionally contains four identical "Delete Wittelsbacherplatz München?" entries to show that the same simple, direct question is the appropriate alternative for multiple different incorrect phrasings (overly wordy questions, generic terms, unnecessary disclaimers, and redundant words).

Applied to files:

  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yaml
📚 Learning: 2025-12-01T14:12:11.111Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1104
File: projects/element-ng/datepicker/components/si-day-selection.component.spec.ts:198-202
Timestamp: 2025-12-01T14:12:11.111Z
Learning: In zoneless Angular tests (using provideZonelessChangeDetection), prefer `await fixture.whenStable()` over `fixture.detectChanges()` after dispatching events or triggering async operations, as `whenStable()` waits for all asynchronous operations to complete and better mimics the production environment.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-09T14:19:26.605Z
Learnt from: Killusions
Repo: siemens/element PR: 967
File: package.json:153-153
Timestamp: 2025-12-09T14:19:26.605Z
Learning: In library projects (e.g., element-ng), do not list implementation dependencies for optional features in the main dependencies. Move those into devDependencies (used for demos/examples) and have consuming apps install them separately if they enable the feature. This avoids bloating library consumers with unnecessary packages and clarifies that optional features are not guaranteed to work without extra installs. If a feature is truly optional, consider documenting it and, if appropriate, using optionalDependencies to reflect optional runtime usage.

Applied to files:

  • package.json
🧬 Code graph analysis (8)
playwright/e2e/element-examples/static.spec.ts (1)
playwright/support/test-helpers.ts (1)
  • test (286-296)
src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (1)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (3)
  • Component (37-96)
  • PromptCategory (11-13)
  • PromptSuggestion (15-17)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (1)
src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (1)
  • Component (13-42)
src/app/examples/si-chat-messages/si-user-message.ts (2)
projects/element-translate-ng/translate/si-translate.inject.ts (1)
  • injectSiTranslateService (11-20)
projects/element-ng/markdown-renderer/markdown-renderer.ts (1)
  • getMarkdownRenderer (53-287)
projects/element-ng/chat-messages/si-tool-message.component.ts (2)
projects/element-ng/chat-messages/si-chat-container.component.ts (1)
  • Component (40-208)
projects/element-translate-ng/translate/t.ts (1)
  • t (38-51)
src/app/examples/si-chat-messages/si-chat-container.ts (4)
projects/element-translate-ng/translate/si-translate.inject.ts (1)
  • injectSiTranslateService (11-20)
projects/element-ng/markdown-renderer/markdown-renderer.ts (1)
  • getMarkdownRenderer (53-287)
projects/element-ng/chat-messages/chat-message.model.ts (2)
  • ChatMessage (157-157)
  • MessageAction (18-31)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (2)
  • PromptCategory (11-13)
  • PromptSuggestion (15-17)
projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts (1)
projects/element-ng/chat-messages/chat-message.model.ts (2)
  • ChatMessage (157-157)
  • MessageAction (18-31)
src/app/examples/si-chat-messages/si-ai-chat-container.ts (5)
projects/element-ng/chat-messages/si-ai-chat-container.component.ts (1)
  • Component (74-581)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (2)
  • Component (37-96)
  • PromptSuggestion (15-17)
projects/element-ng/chat-messages/si-chat-input.component.ts (1)
  • ChatInputAttachment (47-54)
projects/element-ng/chat-messages/chat-message.model.ts (4)
  • ChatMessage (157-157)
  • UserChatMessage (77-86)
  • AiChatMessage (95-102)
  • MessageAction (18-31)
projects/element-ng/file-uploader/si-file-upload.directive.ts (1)
  • FileUploadError (18-21)
🪛 ast-grep (0.40.0)
projects/element-ng/markdown-renderer/markdown-renderer.ts

[warning] 87-87: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(newlinePlaceholder, 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 93-93: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(placeholder, 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 94-94: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(newlinePlaceholder, 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 208-208: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: div.innerHTML = html
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)


[warning] 208-208: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: div.innerHTML = html
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)

projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts

[warning] 93-93: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: containerEl.innerHTML = ''
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build

Comment on lines +63 to +53
// @public (undocumented)
export interface PromptCategory {
// (undocumented)
label: string;
}

// @public (undocumented)
export interface PromptSuggestion {
// (undocumented)
text: string;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for PromptCategory and PromptSuggestion interface definitions with context
rg -n -B5 -A10 'export interface (PromptCategory|PromptSuggestion)' projects/

Repository: siemens/element

Length of output: 2202


🏁 Script executed:

#!/bin/bash
# Check if PromptCategory and PromptSuggestion are exported from public index files
rg -n 'PromptCategory|PromptSuggestion' projects/element-ng/chat-messages/public-api.ts projects/element-ng/chat-messages/index.ts 2>/dev/null || echo "Checking alternate locations..."
# Also check the index file mentioned in the review
head -80 projects/element-ng/chat-messages/index.ts | tail -20

Repository: siemens/element

Length of output: 780


🏁 Script executed:

#!/bin/bash
# Check the full si-ai-welcome-screen.component.ts file to see what's exported
cat -n projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts | head -50

Repository: siemens/element

Length of output: 2179


🏁 Script executed:

#!/bin/bash
# Check the golden file to see how these interfaces are documented
cat -n projects/element-ng/chat-messages/api-goldens/element-ng/chat-messages/index.api.md | sed -n '60,80p'

Repository: siemens/element

Length of output: 174


🏁 Script executed:

#!/bin/bash
# Find the actual golden file
find . -name "index.api.md" -path "*chat-messages*" 2>/dev/null

Repository: siemens/element

Length of output: 110


🏁 Script executed:

#!/bin/bash
# Check lines 63-73 in the golden file as mentioned in the review
cat -n ./api-goldens/element-ng/chat-messages/index.api.md | sed -n '60,80p'

Repository: siemens/element

Length of output: 737


🏁 Script executed:

#!/bin/bash
# Verify that these interfaces are indeed exported from the component file
cat -n projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts | grep -A2 -B2 "export interface"

Repository: siemens/element

Length of output: 305


Add JSDoc documentation to PromptCategory and PromptSuggestion interfaces.

These public API types are currently exported without documentation in si-ai-welcome-screen.component.ts (lines 11-17), which causes them to be marked as undocumented in the generated API golden. Adding JSDoc comments to the source interfaces will automatically improve the generated API documentation and provide better IDE support for consumers.

🤖 Prompt for AI Agents
api-goldens/element-ng/chat-messages/index.api.md around lines 63 to 73: the
PromptCategory and PromptSuggestion types are undocumented in the public API;
add JSDoc comments in the source file (si-ai-welcome-screen.component.ts around
lines 11–17) immediately above each interface and above each property—provide a
brief one-line description for PromptCategory and its label property, and for
PromptSuggestion and its text property—so the generated API docs include
descriptive entries and IDEs surface helpful tooltips.

Comment on lines 110 to 120
private messageActionsCache = new WeakMap<
ChatMessage,
{ primary: MessageAction[]; secondary: MenuItem[]; version: number }
>();

private messageVersions = new WeakMap<ChatMessage, number>();

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for messageVersions usage and WeakMap references in the component
find projects/element-ng/chat-messages -name "*.ts" -type f | head -20 | while read file; do
  if grep -q "messageVersions\|messageActionsCache" "$file" 2>/dev/null; then
    echo "File: $file"
    grep -n "messageVersions\|messageActionsCache" "$file" | head -15
  fi
done

Repository: siemens/element

Length of output: 430


🏁 Script executed:

#!/bin/bash
# Get the full getMessageActions method (approximately lines 396-432)
sed -n '396,432p' projects/element-ng/chat-messages/si-ai-chat-container.component.ts | cat -n

Repository: siemens/element

Length of output: 1439


🏁 Script executed:

#!/bin/bash
# Search for any messageVersions.set calls in the entire file
rg -n 'messageVersions\.set' projects/element-ng/chat-messages/si-ai-chat-container.component.ts

Repository: siemens/element

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Search for any version-related assignments in the messageVersions context
rg -n 'messageVersions' projects/element-ng/chat-messages/si-ai-chat-container.component.ts -A 2 -B 2

Repository: siemens/element

Length of output: 349


messageVersions WeakMap is never updated, breaking cache invalidation.

The code retrieves a version number from messageVersions on line 408 but only calls messageVersions.get(), never messageVersions.set(). Since get() returns undefined for any message, the version defaults to 0 and remains constant. Once the first cache entry is created with version: 0, the check on line 417 (cached?.version === version) will always pass, preventing cache invalidation when message actions change.

🤖 Prompt for AI Agents
In projects/element-ng/chat-messages/si-ai-chat-container.component.ts (around
lines 110-116 and code paths at ~408 and ~417), messageVersions is declared but
never updated, so version stays undefined/0 and cache never invalidates; fix by
calling messageVersions.set(message, newVersion) whenever you create or update
the cached actions: when building the cache entry set the stored version to the
current numeric value (e.g., increment the existing value: const v =
(messageVersions.get(message) ?? 0) + 1; messageVersions.set(message, v); and
use that v in the cache object), and whenever message actions change explicitly
increment/set the message's version so subsequent lookups see a different
version and force recomputation.

Comment on lines 165 to 171
it('should handle signal output', () => {
const outputSignal = signal('{"result": 20}');
fixture.componentRef.setInput('output', outputSignal);
fixture.detectChanges();

expect((component as any).hasOutput()).toBe(true);
});
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Strengthen the signal output test.

The test verifies hasOutput() returns true when a signal is provided, but doesn't verify that the component correctly unwraps the signal value when formatting/displaying output.

🔎 Suggested enhancement
  it('should handle signal output', () => {
    const outputSignal = signal('{"result": 20}');
    fixture.componentRef.setInput('output', outputSignal);
    fixture.detectChanges();

    expect((component as any).hasOutput()).toBe(true);
+   // Verify signal value is correctly unwrapped
+   const formatted = (component as any).formatData(outputSignal());
+   expect(formatted).toBe('{"result": 20}');
  });

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 123 to 130
protected hasInputArguments(): boolean {
return this.inputArguments() !== undefined && this.inputArguments() !== null;
}

protected hasOutput(): boolean {
const outputValue = this.output();
return outputValue !== undefined && outputValue !== null;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Multiple signal reads in boolean checks; consider caching the value.

hasInputArguments() and hasOutput() each invoke their respective signal twice. While not critical, caching the value in a local variable is cleaner and avoids redundant reads.

🔎 Proposed fix
 protected hasInputArguments(): boolean {
-  return this.inputArguments() !== undefined && this.inputArguments() !== null;
+  const value = this.inputArguments();
+  return value !== undefined && value !== null;
 }

 protected hasOutput(): boolean {
   const outputValue = this.output();
   return outputValue !== undefined && outputValue !== null;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
protected hasInputArguments(): boolean {
return this.inputArguments() !== undefined && this.inputArguments() !== null;
}
protected hasOutput(): boolean {
const outputValue = this.output();
return outputValue !== undefined && outputValue !== null;
}
protected hasInputArguments(): boolean {
const value = this.inputArguments();
return value !== undefined && value !== null;
}
protected hasOutput(): boolean {
const outputValue = this.output();
return outputValue !== undefined && outputValue !== null;
}
🤖 Prompt for AI Agents
In projects/element-ng/chat-messages/si-tool-message.component.ts around lines
123 to 130, both hasInputArguments() and hasOutput() call their respective
signal twice; cache the signal result into a local const (e.g., const args =
this.inputArguments(); const out = this.output();) and perform the
undefined/null checks against that variable, returning the boolean from the
cached value to avoid redundant signal reads.

Comment on lines 144 to 147
protected getOutputValue(): string | object | undefined {
const outputValue = this.output();
return outputValue as string | object | undefined;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Redundant type assertion in getOutputValue.

The cast as string | object | undefined matches the declared return type and serves no purpose. The method could simply return this.output() directly.

🔎 Proposed simplification
 protected getOutputValue(): string | object | undefined {
-  const outputValue = this.output();
-  return outputValue as string | object | undefined;
+  return this.output();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
protected getOutputValue(): string | object | undefined {
const outputValue = this.output();
return outputValue as string | object | undefined;
}
protected getOutputValue(): string | object | undefined {
return this.output();
}
🤖 Prompt for AI Agents
In projects/element-ng/chat-messages/si-tool-message.component.ts around lines
144-147, the method getOutputValue contains a redundant type assertion that
duplicates its declared return type; remove the unnecessary cast and return
this.output() directly (i.e., replace the body to simply return this.output()),
ensuring the method signature remains unchanged.

Comment on lines 227 to 840
navigator.clipboard.writeText(code).catch(() => {
// Clipboard API may fail if not in a secure context or permissions denied
console.warn('Failed to copy code to clipboard');
});
});
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adding user feedback for clipboard operations.

The clipboard copy catches errors and logs a warning, which is good for debugging. However, users receive no visual feedback on success or failure. Consider adding a brief visual indicator (e.g., changing button icon/text temporarily) to improve UX.

This is optional as it may be out of scope for this PR.

🤖 Prompt for AI Agents
In projects/element-ng/markdown-renderer/markdown-renderer.ts around lines 227
to 231, the clipboard writeText success/failure is only logged to console and
provides no user-visible feedback; update the click handler to give brief UI
feedback by setting a transient state (e.g., toggling a "copied" or "error" flag
or changing button text/icon) on success and on failure, clear it after a short
timeout (e.g., 1.5–2s), and ensure any existing timeout is cleared before
setting a new one so the indicator behaves consistently.

Comment on lines 262 to 297
setTimeout(() => {
this.sending.set(false);
this.loading.set(true);

setTimeout(() => {
const response = `Thanks for your message: "${userInput}". I can help with that!`;

messagesSignal.update((current: ChatMessage[]) => [
...current,
{
type: 'ai',
content: response,
actions: this.aiActions
}
]);
this.loading.set(false);
}, 2000);
}, 1000);
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if other examples implement OnDestroy for timeout cleanup
rg -n 'ngOnDestroy|clearTimeout' src/app/examples/si-chat-messages/ --type=ts

Repository: siemens/element

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Check if the file exists and get surrounding context
fd "si-ai-chat-container" src/app/examples/ --type=ts

# Check broader examples directory for any cleanup patterns
echo "=== Checking all examples for timeout cleanup patterns ==="
rg -n 'ngOnDestroy|clearTimeout' src/app/examples/ --type=ts | head -20

Repository: siemens/element

Length of output: 1948


🏁 Script executed:

#!/bin/bash
# Check the chat example file directly for OnDestroy
cat -n src/app/examples/si-chat-messages/si-ai-chat-container.ts | grep -A 10 -B 5 "ngOnDestroy\|setTimeout"

# Also check one example to see what ngOnDestroy cleanup patterns look like
echo "=== Example ngOnDestroy pattern ==="
rg -A 5 'ngOnDestroy' src/app/examples/si-charts/cartesian/line-live.ts

Repository: siemens/element

Length of output: 890


Nested setTimeout calls lack cleanup on component destroy.

If the component is destroyed mid-simulation, these timeouts will still fire and attempt to update signals. Other examples in this codebase implement ngOnDestroy for lifecycle cleanup, so consider adding it here to manage these timeouts, or add a comment noting this simplification.

🤖 Prompt for AI Agents
In src/app/examples/si-chat-messages/si-ai-chat-container.ts around lines
262–279 the nested setTimeouts simulate an AI response but do not get cleaned up
on component destroy; store the returned timeout IDs on the class (e.g.
this._sendTimer, this._responseTimer), implement Angular's OnDestroy (import and
add ngOnDestroy), and clear any pending timers with
clearTimeout(this._sendTimer) / clearTimeout(this._responseTimer) in ngOnDestroy
(and null them afterward); alternatively, if you prefer to keep the
simplification, add a clear comment above the simulation explaining there is no
lifecycle cleanup on purpose.

Comment on lines +30 to +37
readonly allSuggestions: PromptSuggestion[] = [
{ text: 'How do I optimize performance for large datasets?' },
{ text: 'What are the best practices for data validation?' },
{ text: 'Help me troubleshoot this error message' },
{ text: 'Explain the difference between async and sync operations' }
];

readonly promptSuggestions = signal<PromptSuggestion[]>(this.allSuggestions);
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

promptSuggestions signal doesn't leverage category filtering.

The component has promptCategories defined but promptSuggestions is a flat array. To demonstrate the category filtering feature of SiAiWelcomeScreenComponent, consider using the Record<string, PromptSuggestion[]> format.

This is optional since the example may intentionally demonstrate the simple array format.

🤖 Prompt for AI Agents
In src/app/examples/si-chat-messages/si-ai-welcome-screen.ts around lines 30 to
37, promptSuggestions is a flat array and doesn't show category filtering;
instead, change promptSuggestions to a Record<string, PromptSuggestion[]> keyed
by category (e.g., map each prompt in allSuggestions into categories from
promptCategories or create categorized arrays like { General: [...],
Troubleshooting: [...], BestPractices: [...] }) and initialize the signal with
that record (signal<Record<string, PromptSuggestion[]>>(categorizedSuggestions))
so the component can demonstrate category-based filtering.

Comment on lines 226 to 253
readonly selectedCategory = signal<string>('all');

readonly allPromptSuggestions: PromptSuggestion[] = [
{ text: 'How do I optimize performance for large datasets?' },
{ text: 'What are the best practices for data validation?' },
{ text: 'Help me troubleshoot this error message' },
{ text: 'Explain the difference between async and sync operations' }
];

readonly filteredPromptSuggestions = signal<PromptSuggestion[]>(this.allPromptSuggestions);
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider implementing category-based filtering.

filteredPromptSuggestions is initialized with all suggestions but never updates when selectedCategory changes. If filtering is intended, consider using a computed signal:

🔎 Suggested implementation
-  readonly filteredPromptSuggestions = signal<PromptSuggestion[]>(this.allPromptSuggestions);
+  readonly filteredPromptSuggestions = computed(() => {
+    const category = this.selectedCategory();
+    if (category === 'all') {
+      return this.allPromptSuggestions;
+    }
+    // Add filtering logic based on category
+    return this.allPromptSuggestions;
+  });

If this is intentionally a placeholder for demonstration purposes, consider adding a comment to clarify.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/app/examples/si-chat-messages/si-chat-container.ts around lines 226 to
235, filteredPromptSuggestions is initialized to the full list but never updates
when selectedCategory changes; replace the static signal with a computed signal
that derives from selectedCategory and returns either allPromptSuggestions or a
filtered array (e.g., check category value 'all' vs specific categories and
filter by a category property on PromptSuggestion), or if no filtering is
required add a clarifying comment indicating this is intentionally static for
the demo.

@Killusions Killusions force-pushed the feat/add-ai-welcome-screen branch from 3228016 to 912a98e Compare December 22, 2025 18:06
@Killusions Killusions requested a review from a team as a code owner December 22, 2025 18:06
@Killusions Killusions force-pushed the feat/add-ai-welcome-screen branch from 912a98e to 60b0a60 Compare December 22, 2025 20:24
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: 14

♻️ Duplicate comments (12)
projects/element-ng/chat-messages/si-tool-message.component.spec.ts (1)

165-171: Past review comment remains valid.

A previous review suggested enhancing this test to verify that the component correctly unwraps the signal value when formatting/displaying output, not just that hasOutput() returns true. Consider addressing that feedback.

projects/element-ng/chat-messages/si-chat-container.component.scss (1)

23-29: Remove the unnecessary ::ng-deep pseudo-class.

The ::ng-deep &:has(si-ai-welcome-screen) selector makes the rule global when likely not intended. Since the & refers to .chat-container within the component's own template, the ::ng-deep is unnecessary. Simply use &:has(si-ai-welcome-screen) to scope the styles to the component.

🔎 Proposed fix
-  ::ng-deep &:has(si-ai-welcome-screen) {
+  &:has(si-ai-welcome-screen) {
     inline-size: 100%;
     // stylelint-disable-next-line declaration-no-important
     padding-inline-start: 0 !important;
     // stylelint-disable-next-line declaration-no-important
     padding-inline-end: 0 !important;
   }
projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss (1)

36-38: Refactor away from the deprecated ::ng-deep selector.

The ::ng-deep selector is deprecated and should be avoided. Consider using CSS custom properties, adding a CSS class directly to the button elements, or setting ViewEncapsulation.None if cross-component styling is required.

src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (2)

21-28: Mismatch between selectedCategory and category labels (previously flagged).

As noted in previous reviews, the selectedCategory is initialized to 'all' but the category labels use 'All prompts'. This mismatch means no category will be pre-selected initially.


30-37: Flat array format doesn't demonstrate category filtering (previously noted).

As noted in previous reviews, using a flat array for promptSuggestions is valid but doesn't demonstrate the category filtering capability. This is acceptable for a simple example.

src/app/examples/si-chat-messages/si-chat-container.ts (1)

236-252: Static prompt suggestions don't react to category changes (previously flagged).

As noted in previous reviews, filteredPromptSuggestions is initialized as a static signal and doesn't update when selectedCategory changes. For demonstration purposes showing the simple pattern, this is acceptable, though a computed() signal would better demonstrate the filtering feature.

projects/element-ng/markdown-renderer/markdown-renderer.ts (2)

265-269: Document the purpose of duplicate table tag removal.

This regex is complex and its purpose may not be clear to future maintainers.


342-346: Consider adding user feedback for clipboard operations.

projects/element-ng/chat-messages/si-tool-message.component.ts (4)

109-121: Signal detection is fragile; prefer isSignal from Angular core.

The check typeof data === 'function' && 'call' in data is unreliable since all functions have a call property. Angular provides isSignal() for this purpose.


123-130: Multiple signal reads in boolean checks; consider caching the value.

hasInputArguments() invokes the signal twice. Cache the value in a local variable.


132-142: getLoadingState contains dead code path.

The comment on line 140 mentions showing loading for empty string output, but the method just returns false. This appears to be leftover from incomplete logic.


144-147: Redundant type assertion in getOutputValue.

The cast as string | object | undefined matches the declared return type and serves no purpose.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3228016 and 60b0a60.

⛔ Files ignored due to path filters (11)
  • package-lock.json is excluded by !**/package-lock.json
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-light-linux.png is excluded by !**/*.png
📒 Files selected for processing (70)
  • .npmrc
  • angular.json
  • api-goldens/element-ng/chat-messages/index.api.md
  • api-goldens/element-ng/markdown-renderer/index.api.md
  • api-goldens/element-ng/translate/index.api.md
  • docs/components/chat-messages/chat-message.md
  • docs/patterns/ai/ai-chat.md
  • package.json
  • playwright/e2e/element-examples/static.spec.ts
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yaml
  • projects/dashboards-demo/src/styles.scss
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/message-action.model.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-chat-input.component.ts
  • projects/element-ng/chat-messages/si-chat-message.component.scss
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • projects/element-ng/link/si-link.directive.ts
  • projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts
  • projects/element-ng/markdown-renderer/markdown-renderer.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts
  • projects/element-ng/status-bar/si-status-bar.component.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • projects/element-theme/src/styles/components/_markdown-hljs-theme.scss
  • projects/element-theme/src/styles/components/_markdown.scss
  • projects/element-theme/src/styles/variables/_semantic-tokens.scss
  • projects/element-theme/src/theme/_theme-element.scss
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • src/app/examples/si-chat-messages/si-ai-message.ts
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.html
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.ts
  • src/app/examples/si-chat-messages/si-chat-container.html
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • src/app/examples/si-chat-messages/si-chat-input.html
  • src/app/examples/si-chat-messages/si-tool-message.html
  • src/app/examples/si-chat-messages/si-tool-message.ts
  • src/app/examples/si-chat-messages/si-user-message.ts
  • src/app/examples/si-markdown-renderer/si-markdown-renderer.html
  • src/app/examples/si-markdown-renderer/si-markdown-renderer.ts
  • src/assets/sample-markdown.md
  • src/styles.scss
💤 Files with no reviewable changes (3)
  • projects/element-ng/status-bar/si-status-bar.component.ts
  • projects/element-ng/link/si-link.directive.ts
  • projects/element-ng/chat-messages/message-action.model.ts
🧰 Additional context used
🧠 Learnings (29)
📚 Learning: 2025-12-09T14:31:33.543Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:14-50
Timestamp: 2025-12-09T14:31:33.543Z
Learning: In projects/element-ng/chat-messages/si-ai-chat-container.component.html, message IDs can change, so tracking by message.id is not appropriate. The component uses `track message` (object identity) which is the correct approach for this use case.

Applied to files:

  • src/app/examples/si-chat-messages/si-tool-message.html
  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • src/app/examples/si-chat-messages/si-tool-message.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/chat-messages/si-chat-message.component.scss
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • src/app/examples/si-chat-messages/si-chat-container.html
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-chat-input.component.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
📚 Learning: 2025-12-15T10:05:59.100Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1193
File: projects/element-ng/search-bar/si-search-bar.component.spec.ts:21-28
Timestamp: 2025-12-15T10:05:59.100Z
Learning: In tests that rely on Jasmine's fake clock to control time-based RxJS operators (e.g., debounceTime), use jasmine.clock().install() together with jasmine.clock().mockDate() to enable precise timing control. Without mockDate, scheduler-based operators may not respond to the fake clock. Apply this guidance to spec files (e.g., any file named *.spec.ts or *.spec.js) that test time-sensitive behavior, ensuring you install and mockDate before advancing time in tests.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • playwright/e2e/element-examples/static.spec.ts
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
📚 Learning: 2025-12-17T04:34:55.597Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1173
File: src/app/examples/si-charts/interactive/interactive.ts:5-5
Timestamp: 2025-12-17T04:34:55.597Z
Learning: Guideline: In Angular projects using OnPush change detection (zoneless mode), you only need to call ChangeDetectorRef.markForCheck() for asynchronous operations (e.g., setTimeout, setInterval, Promises, Observables) where a change is not automatically detected. Event handlers triggered by Angular template bindings (click, input, etc.) will trigger change detection automatically and do not require explicit markForCheck() calls. Apply this broadly to TS files within Angular components/services that use OnPush; use markForCheck() selectively for async work where change detection wouldn’t run otherwise.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • src/app/examples/si-markdown-renderer/si-markdown-renderer.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • src/app/examples/si-chat-messages/si-tool-message.ts
  • playwright/e2e/element-examples/static.spec.ts
  • projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/chat-message.model.ts
  • src/app/examples/si-chat-messages/si-user-message.ts
  • src/app/examples/si-chat-messages/si-ai-message.ts
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.ts
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/markdown-renderer/markdown-renderer.ts
  • projects/element-ng/chat-messages/si-chat-input.component.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
📚 Learning: 2025-12-15T07:16:53.762Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:92-105
Timestamp: 2025-12-15T07:16:53.762Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits must be used instead of fixture.whenStable() to avoid injector destroyed errors during mount/unmount operations in zoneless mode. The GridStack timing-dependent operations require actual async delays.

Applied to files:

  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-15T07:16:32.082Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:69-80
Timestamp: 2025-12-15T07:16:32.082Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing grid item rendering and initialization. This is likely due to gridstack library's initialization timing or lifecycle behavior that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-11T10:09:01.564Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1151
File: projects/element-ng/auto-collapsable-list/si-auto-collapsable-list.directive.spec.ts:83-104
Timestamp: 2025-12-11T10:09:01.564Z
Learning: In the auto-collapsable-list directive tests (projects/element-ng/auto-collapsable-list/si-auto-collapsable-list.directive.spec.ts), jasmine.clock() successfully controls the directive's setTimeout-based layout logic in zoneless mode. Mock timers work fine here, unlike in select component overflow tests where real setTimeout waits are required.

Applied to files:

  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-08T11:25:51.584Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/si-select.component.spec.ts:511-516
Timestamp: 2025-12-08T11:25:51.584Z
Learning: In the select component overflow tests (projects/element-ng/select/si-select.component.spec.ts), jasmine.clock() cannot be used to control the timing for overflow item detection. Real setTimeout waits must be used instead, likely due to ResizeObserver or debounced layout calculations that jasmine.clock() cannot control in zoneless mode.

Applied to files:

  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-08T11:24:45.272Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/options/si-select-lazy-options.directive.spec.ts:67-85
Timestamp: 2025-12-08T11:24:45.272Z
Learning: In select lazy options tests (projects/element-ng/select/options/si-select-lazy-options.directive.spec.ts), jasmine.clock() cannot control RxJS debounceTime in zoneless mode. Real setTimeout waits must be used instead for tests involving search debouncing.

Applied to files:

  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-04T11:54:31.132Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1133
File: projects/element-ng/tour/si-tour.service.spec.ts:21-26
Timestamp: 2025-12-04T11:54:31.132Z
Learning: In the siemens/element repository, all components are standalone by default and do not require the explicit `standalone: true` flag. Components should be added to the `imports` array in TestBed configuration, not the `declarations` array.

Applied to files:

  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
📚 Learning: 2025-12-01T04:01:27.365Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1099
File: projects/element-ng/accordion/si-accordion.component.spec.ts:39-43
Timestamp: 2025-12-01T04:01:27.365Z
Learning: With Angular 20 and esbuild, synchronous `TestBed.configureTestingModule(...).compileComponents()` calls work correctly even when components use external templates (templateUrl), because esbuild pre-compiles templates at build time. The async/await pattern is not required in this scenario.

Applied to files:

  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
📚 Learning: 2025-12-09T14:32:26.166Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:21-47
Timestamp: 2025-12-09T14:32:26.166Z
Learning: In Angular templates, prefer using nested *ngIf blocks over *ngSwitch for branching on message types within the chat-messages components. Use *ngIf with else branches to handle distinct cases and avoid complex switch logic in HTML templates. This guideline applies to all HTML templates under projects/element-ng/chat-messages.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
📚 Learning: 2025-12-15T07:17:06.981Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts:37-49
Timestamp: 2025-12-15T07:17:06.981Z
Learning: In widget-instance-editor-dialog component tests (projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing component initialization. This is likely due to the component's lifecycle behavior or modal initialization timing that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-05T08:00:38.407Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1151
File: projects/element-ng/typeahead/si-typeahead.directive.spec.ts:114-121
Timestamp: 2025-12-05T08:00:38.407Z
Learning: In the typeahead test suite (projects/element-ng/typeahead/si-typeahead.directive.spec.ts), jasmine.clock() must be installed in beforeAll and uninstalled in afterAll (not beforeEach/afterEach) because using per-test clock installation causes schedulerFunction-related issues in these specific tests.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
📚 Learning: 2025-12-04T05:50:17.637Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1135
File: projects/element-ng/tree-view/si-tree-view.component.spec.ts:953-964
Timestamp: 2025-12-04T05:50:17.637Z
Learning: In the siemens/element repository, when making tree-view tests zoneless-ready, jasmine.clock() should be used to mimic setTimeouts even in zoneless mode, as the component implementation relies on setTimeout calls that need to be controlled in tests.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-16T16:19:17.950Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1207
File: playwright/snapshots/si-filtered-search.spec.ts-snapshots/si-filtered-search--si-filtered-search-playground--data-entered.yaml:38-38
Timestamp: 2025-12-16T16:19:17.950Z
Learning: Do not review files in the playwright/snapshots directory, as they contain auto-generated test artifacts. Exclude any YAML snapshot files under playwright/snapshots from code reviews in the siemens/element repository. If a YAML file is not an auto-generated snapshot, verify its origin before skipping.

Applied to files:

  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yaml
📚 Learning: 2025-11-18T12:37:30.510Z
Learnt from: Killusions
Repo: siemens/element PR: 1040
File: projects/element-ng/chat-messages/si-chat-input.component.ts:338-349
Timestamp: 2025-11-18T12:37:30.510Z
Learning: In projects/element-ng/chat-messages/si-chat-input.component.ts, the interrupt behavior is intentionally different for button clicks vs Enter key: the button can emit interrupt even without content, but pressing Enter requires content or attachments (canSend() must be true) to emit interrupt.

Applied to files:

  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • src/app/examples/si-chat-messages/si-chat-input.html
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/chat-message.model.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • src/app/examples/si-chat-messages/si-chat-container.html
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-chat-input.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
📚 Learning: 2025-12-09T14:19:34.846Z
Learnt from: Killusions
Repo: siemens/element PR: 967
File: package.json:153-153
Timestamp: 2025-12-09T14:19:34.846Z
Learning: In library projects like element-ng, optional features that are provided through callback/function parameters (e.g., syntaxHighlighter in markdown renderer) should not have their implementation dependencies (e.g., highlight.js) listed in the library's dependencies. These should remain in devDependencies for demo/example purposes, and consuming applications should install them directly if they choose to use those features.

Applied to files:

  • src/app/examples/si-markdown-renderer/si-markdown-renderer.ts
📚 Learning: 2025-12-09T14:33:54.441Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: src/app/examples/si-chat-messages/si-ai-message.ts:24-43
Timestamp: 2025-12-09T14:33:54.441Z
Learning: In src/app/examples/ (example/demo code) directories, allow and expect code duplication. Treat duplication as acceptable for demonstration code that aims to illustrate usage rather than enforce DRY. Do not enforce refactoring to remove duplication in example files; focus on readability and clarity of examples. This applies to all TypeScript files under src/app/examples (including nested subdirectories like si-chat-messages).

Applied to files:

  • src/app/examples/si-markdown-renderer/si-markdown-renderer.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • src/app/examples/si-chat-messages/si-tool-message.ts
  • src/app/examples/si-chat-messages/si-user-message.ts
  • src/app/examples/si-chat-messages/si-ai-message.ts
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-22T13:04:20.883Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: src/app/examples/ag-grid/ag-grid-empty-state.ts:20-24
Timestamp: 2025-12-22T13:04:20.883Z
Learning: The SiEmptyStateComponent in siemens/element-ng accepts icon names in kebab-case format (e.g., 'element-technical-operator') that may not be directly exported as constants in the element-icons.ts file. Do not flag these as errors if they render correctly at runtime.

Applied to files:

  • projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts
📚 Learning: 2025-12-22T13:21:01.053Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: projects/element-ng/ag-grid/provider.ts:74-81
Timestamp: 2025-12-22T13:21:01.053Z
Learning: In the siemens/element repository, configuration providers use custom string tokens with useValue for consistency (e.g., provideSiDatatableConfig uses { provide: 'configuration', useValue: {...} }). The AG Grid provider follows this same pattern with { provide: 'ag-grid-options', useValue: provideGlobalGridOptions({...}) }.

Applied to files:

  • projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
📚 Learning: 2025-12-09T14:32:34.036Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:21-47
Timestamp: 2025-12-09T14:32:34.036Z
Learning: In projects/element-ng/chat-messages, nested if blocks are preferred over switch statements for branching on message types in Angular templates.

Applied to files:

  • projects/element-ng/chat-messages/si-user-message.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/chat-messages/si-chat-message.component.scss
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • src/app/examples/si-chat-messages/si-chat-container.html
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • api-goldens/element-ng/chat-messages/index.api.md
📚 Learning: 2025-12-08T11:25:20.861Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/si-select.component.spec.ts:204-205
Timestamp: 2025-12-08T11:25:20.861Z
Learning: In zoneless Angular tests (using provideZonelessChangeDetection), calling fixture.changeDetectorRef.markForCheck() before fixture.detectChanges() is required even for components using the default change detection strategy (not OnPush). This differs from zone.js-based testing where markForCheck is primarily needed only for OnPush components.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-04T05:50:38.735Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1135
File: projects/element-ng/tree-view/si-tree-view.component.spec.ts:1244-1245
Timestamp: 2025-12-04T05:50:38.735Z
Learning: In zoneless Angular tests with OnPush components, calling `await runOnPushChangeDetection(fixture)` followed by `await fixture.whenStable()` is NOT redundant. The `runOnPushChangeDetection` helper forces change detection to run for OnPush components, while `whenStable()` waits for all async operations to complete. Both are necessary and serve different purposes.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-01T14:12:11.111Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1104
File: projects/element-ng/datepicker/components/si-day-selection.component.spec.ts:198-202
Timestamp: 2025-12-01T14:12:11.111Z
Learning: In zoneless Angular tests (using provideZonelessChangeDetection), prefer `await fixture.whenStable()` over `fixture.detectChanges()` after dispatching events or triggering async operations, as `whenStable()` waits for all asynchronous operations to complete and better mimics the production environment.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-22T13:29:31.048Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: projects/element-ng/ag-grid/parts/color-scheme.part.ts:35-35
Timestamp: 2025-12-22T13:29:31.048Z
Learning: In the Element design system (projects/element-ng/theme and projects/element-theme), only `--element-body-font-family` is exposed as a CSS custom property for typography. Font sizes are NOT exposed as CSS custom properties; they are defined using internal SCSS variables (e.g., `typography.$si-font-size-body`) that compile to fixed values. Using hardcoded pixel values for fontSize in AG Grid theme configuration (e.g., `fontSize: '14px'`) is the correct approach.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/dashboards-demo/src/styles.scss
📚 Learning: 2025-12-04T10:35:45.465Z
Learnt from: Killusions
Repo: siemens/element PR: 1147
File: docs/fundamentals/ux-text-style-guide/dialogs-and-buttons.md:81-84
Timestamp: 2025-12-04T10:35:45.465Z
Learning: In docs/fundamentals/ux-text-style-guide/dialogs-and-buttons.md, the Clear content section's Do's intentionally contains four identical "Delete Wittelsbacherplatz München?" entries to show that the same simple, direct question is the appropriate alternative for multiple different incorrect phrasings (overly wordy questions, generic terms, unnecessary disclaimers, and redundant words).

Applied to files:

  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yaml
📚 Learning: 2025-12-17T14:01:05.705Z
Learnt from: dauriamarco
Repo: siemens/element PR: 908
File: projects/element-ng/side-panel/si-side-panel.component.ts:70-74
Timestamp: 2025-12-17T14:01:05.705Z
Learning: In the Element side-panel component (projects/element-ng/side-panel/si-side-panel.component.ts), the `xxxlMinimum` breakpoint (1920px) is intentionally hardcoded as a private static constant rather than being part of the configurable `Breakpoints` interface. This design preserves full Bootstrap compatibility (which only defines breakpoints up to xxl/1400px) while allowing Element to handle ultra-wide screens explicitly without affecting the standard breakpoint configuration.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-chat-container.component.scss
📚 Learning: 2025-12-03T13:29:01.075Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1058
File: docs/components/pages/landing-page.md:34-36
Timestamp: 2025-12-03T13:29:01.075Z
Learning: In Markdown blockquotes with numbered sequences, escaping only the first number (e.g., `\1.`) is sufficient to prevent auto-numbering for the entire sequence. Subsequent numbers (2., 3., etc.) do not need individual escaping.

Applied to files:

  • src/assets/sample-markdown.md
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yaml
📚 Learning: 2025-12-09T14:19:26.605Z
Learnt from: Killusions
Repo: siemens/element PR: 967
File: package.json:153-153
Timestamp: 2025-12-09T14:19:26.605Z
Learning: In library projects (e.g., element-ng), do not list implementation dependencies for optional features in the main dependencies. Move those into devDependencies (used for demos/examples) and have consuming apps install them separately if they enable the feature. This avoids bloating library consumers with unnecessary packages and clarifies that optional features are not guaranteed to work without extra installs. If a feature is truly optional, consider documenting it and, if appropriate, using optionalDependencies to reflect optional runtime usage.

Applied to files:

  • package.json
🧬 Code graph analysis (8)
projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts (1)
projects/element-ng/chat-messages/chat-message.model.ts (2)
  • ChatMessage (157-157)
  • MessageAction (18-31)
src/app/examples/si-chat-messages/si-chat-container.ts (4)
projects/element-translate-ng/translate/si-translate.inject.ts (1)
  • injectSiTranslateService (11-20)
projects/element-ng/markdown-renderer/markdown-renderer.ts (1)
  • getMarkdownRenderer (69-402)
projects/element-ng/chat-messages/chat-message.model.ts (2)
  • ChatMessage (157-157)
  • MessageAction (18-31)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (2)
  • PromptCategory (11-13)
  • PromptSuggestion (15-17)
playwright/e2e/element-examples/static.spec.ts (1)
playwright/support/test-helpers.ts (1)
  • test (286-296)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (2)
src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (1)
  • Component (13-42)
src/app/examples/si-chat-messages/si-chat-container.ts (1)
  • Component (43-369)
src/app/examples/si-chat-messages/si-user-message.ts (2)
projects/element-translate-ng/translate/si-translate.inject.ts (1)
  • injectSiTranslateService (11-20)
projects/element-ng/markdown-renderer/markdown-renderer.ts (1)
  • getMarkdownRenderer (69-402)
src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (1)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (3)
  • Component (37-96)
  • PromptCategory (11-13)
  • PromptSuggestion (15-17)
projects/element-ng/chat-messages/si-tool-message.component.ts (1)
projects/element-translate-ng/translate/t.ts (1)
  • t (38-51)
src/app/examples/si-chat-messages/si-ai-chat-container.ts (5)
projects/element-ng/chat-messages/si-ai-chat-container.component.ts (1)
  • Component (74-581)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (2)
  • Component (37-96)
  • PromptSuggestion (15-17)
projects/element-ng/chat-messages/si-chat-input.component.ts (1)
  • ChatInputAttachment (47-54)
projects/element-ng/chat-messages/chat-message.model.ts (4)
  • ChatMessage (157-157)
  • UserChatMessage (77-86)
  • AiChatMessage (95-102)
  • MessageAction (18-31)
projects/element-ng/file-uploader/si-file-upload.directive.ts (1)
  • FileUploadError (18-21)
🪛 ast-grep (0.40.3)
projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts

[warning] 108-108: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: tempDiv.innerHTML = createHtml()
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)


[warning] 108-108: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: tempDiv.innerHTML = createHtml()
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)

projects/element-ng/markdown-renderer/markdown-renderer.ts

[warning] 116-116: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(newlinePlaceholder, 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 122-122: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(placeholder, 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 123-123: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(newlinePlaceholder, 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 284-284: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: div.innerHTML = html
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)


[warning] 284-284: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: div.innerHTML = html
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)


[warning] 734-734: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(placeholder, 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 738-738: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(escapedDollarPlaceholder, 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts

[warning] 106-106: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: containerEl.innerHTML = ''
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build

Comment on lines 13 to 18
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SiAiWelcomeScreenComponent]
}).compileComponents();
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider removing the async/await pattern.

With Angular 20 and esbuild, compileComponents() can be called synchronously because templates are pre-compiled at build time. The async/await pattern is not required here.

🔎 Simplified synchronous pattern
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
+  beforeEach(() => {
+    TestBed.configureTestingModule({
       imports: [SiAiWelcomeScreenComponent]
     }).compileComponents();

Based on learnings, Angular 20 + esbuild pre-compiles templates at build time.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SiAiWelcomeScreenComponent]
}).compileComponents();
beforeEach(() => {
TestBed.configureTestingModule({
imports: [SiAiWelcomeScreenComponent]
}).compileComponents();
🤖 Prompt for AI Agents
In projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
around lines 13-16, the beforeEach uses an unnecessary async/await with
compileComponents(); remove the async wrapper and the await, making the
beforeEach synchronous and call
TestBed.configureTestingModule(...).compileComponents(); directly so the test
relies on Angular 20 + esbuild precompiled templates.

Comment on lines 58 to 65
let calledCategoryId: string | undefined | null = null;
component.selectedCategory.subscribe((categoryId: string | undefined) => {
calledCategoryId = categoryId;
});
const categoryButton = fixture.nativeElement.querySelector('button');
categoryButton?.click();

expect(calledCategoryId as string | undefined | null).toBe('cat1');
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Simplify the type union and remove unnecessary cast.

The distinction between undefined and null adds complexity without value. Initialize with undefined and remove the explicit cast.

🔎 Simplified type union
-    let calledCategoryId: string | undefined | null = null;
+    let calledCategoryId: string | undefined;
     component.selectedCategory.subscribe((categoryId: string | undefined) => {
       calledCategoryId = categoryId;
     });
     const categoryButton = fixture.nativeElement.querySelector('button');
     categoryButton?.click();
 
-    expect(calledCategoryId as string | undefined | null).toBe('cat1');
+    expect(calledCategoryId).toBe('cat1');
🤖 Prompt for AI Agents
In projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
around lines 58–65, calledCategoryId is typed as string | undefined | null and
later cast in the expect; change the declaration to use only string | undefined
and initialize it to undefined, keep the subscribe callback as-is, then remove
the unnecessary cast in the expect assertion so it reads
expect(calledCategoryId).toBe('cat1').

Comment on lines +11 to +17
export interface PromptCategory {
label: string;
}

export interface PromptSuggestion {
text: string;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adding an id field to PromptCategory for better separation of concerns.

The PromptCategory interface only has a label field, which is used both for display and as the selection identifier. This creates confusion (as seen in example code where selectedCategory is initialized to 'all' but categories use 'All prompts'). Consider adding an optional id field to separate the identifier from the display label:

export interface PromptCategory {
  id?: string;
  label: string;
}

This would allow selectedCategory to track by ID while displaying the label, making the API more flexible and less error-prone.

🤖 Prompt for AI Agents
In projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts around
lines 11 to 17, the PromptCategory interface currently exposes only a label
which is being used both as display text and as the selection identifier; add an
optional id:string field to the interface (or make it required if you prefer) so
components can track selectedCategory by id while rendering label for display,
then update any initialization and selection logic to use category.id for
comparisons and keep label for UI.

Comment on lines +47 to +59
::ng-deep &:not(:has(si-ai-welcome-screen)) {
max-inline-size: 720px;
}

::ng-deep &:has(si-ai-welcome-screen) {
inline-size: 100%;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Remove unnecessary ::ng-deep from messages-container selectors.

Similar to the .chat-container issue above, these selectors use ::ng-deep unnecessarily. The :has() pseudo-class naturally checks for descendant elements, so ::ng-deep is not needed here. Remove it to keep the styles properly scoped to the component.

🔎 Proposed fix
-  ::ng-deep &:not(:has(si-ai-welcome-screen)) {
+  &:not(:has(si-ai-welcome-screen)) {
     max-inline-size: 720px;
   }

-  ::ng-deep &:has(si-ai-welcome-screen) {
+  &:has(si-ai-welcome-screen) {
     inline-size: 100%;
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
::ng-deep &:not(:has(si-ai-welcome-screen)) {
max-inline-size: 720px;
}
::ng-deep &:has(si-ai-welcome-screen) {
inline-size: 100%;
}
&:not(:has(si-ai-welcome-screen)) {
max-inline-size: 720px;
}
&:has(si-ai-welcome-screen) {
inline-size: 100%;
}
🤖 Prompt for AI Agents
In projects/element-ng/chat-messages/si-chat-container.component.scss around
lines 47 to 53, the selectors use unnecessary ::ng-deep before :has() which is
redundant and breaks component scoping; remove the ::ng-deep tokens so the rules
read "&:not(:has(si-ai-welcome-screen)) { max-inline-size: 720px; }" and
"&:has(si-ai-welcome-screen) { inline-size: 100%; }" keeping the rest of the
selector structure intact to ensure styles remain scoped to the component.

Comment on lines +100 to +105
const orderIndex = cacheOrder.indexOf(key);
if (orderIndex > -1) {
cacheOrder.splice(orderIndex, 1);
}
cacheOrder.push(key);
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

LRU order tracking could be more efficient.

The current implementation uses indexOf and splice (both O(n) operations) to maintain the LRU order. For frequently accessed caches with many entries, this could become a performance bottleneck.

Consider using a Set for O(1) order operations, or a doubly-linked list if you need to maintain strict ordering.

🤖 Prompt for AI Agents
In projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts around
lines 100 to 104, the LRU tracking uses cacheOrder.indexOf + splice + push
(O(n)) which can be slow; replace the array-based order with a Set (or a small
doubly-linked list) to get O(1) updates: change cacheOrder from Array to Set, on
access if the key exists do cacheOrder.delete(key) then cacheOrder.add(key) to
mark it most-recent, and when evicting remove the oldest entry by reading
cacheOrder.values().next().value and calling cacheOrder.delete(oldKey); update
any other code that assumes array methods (indexing/length semantics) to use Set
methods or convert to an array only when necessary.

Comment on lines +129 to +160
export const getCachedOrCreateString = (
cache: Map<string, string>,
cacheOrder: string[],
cacheSize: number,
key: string,
createString: () => string
): string => {
const cached = cache.get(key);
if (cached) {
const orderIndex = cacheOrder.indexOf(key);
if (orderIndex > -1) {
cacheOrder.splice(orderIndex, 1);
}
cacheOrder.push(key);
return cached;
}

const result = createString();

cache.set(key, result);
cacheOrder.push(key);

if (cacheOrder.length > cacheSize) {
const oldestKey = cacheOrder.shift();
if (oldestKey) {
cache.delete(oldestKey);
}
}

return result;
};
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider reducing duplication with a generic cache implementation.

The logic in getCachedOrCreateString is nearly identical to getCachedOrCreateElement (lines 91-123). This duplication increases maintenance burden.

Consider creating a generic getCachedOrCreate<T> function that both functions can use, or at least extracting the LRU management logic into a shared utility.

💡 Example generic implementation approach
function getCachedOrCreate<T>(
  cache: Map<string, T>,
  cacheOrder: string[],
  cacheSize: number,
  key: string,
  create: () => T
): T {
  const cached = cache.get(key);
  if (cached) {
    const orderIndex = cacheOrder.indexOf(key);
    if (orderIndex > -1) {
      cacheOrder.splice(orderIndex, 1);
    }
    cacheOrder.push(key);
    return cached;
  }

  const result = create();
  cache.set(key, result);
  cacheOrder.push(key);

  if (cacheOrder.length > cacheSize) {
    const oldestKey = cacheOrder.shift();
    if (oldestKey) {
      cache.delete(oldestKey);
    }
  }

  return result;
}

// Then wrap for specific types if needed
export const getCachedOrCreateElement = (
  cache: Map<string, HTMLElement>,
  cacheOrder: string[],
  cacheSize: number,
  key: string,
  createHtml: () => string
): HTMLElement => {
  return getCachedOrCreate(cache, cacheOrder, cacheSize, key, () => {
    const tempDiv = document.createElement('div');
    tempDiv.innerHTML = createHtml();
    const element = tempDiv.firstElementChild as HTMLElement;
    if (!element) {
      throw new Error('createHtml() must return valid HTML with at least one element');
    }
    return element;
  });
};
🤖 Prompt for AI Agents
In projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts around
lines 129 to 159, duplicate LRU cache logic is implemented in
getCachedOrCreateString (and similarly in getCachedOrCreateElement at lines
91-123); extract a single generic helper like getCachedOrCreate<T>(cache,
cacheOrder, cacheSize, key, create) that encapsulates lookup, order update,
insertion and eviction, then refactor getCachedOrCreateString and
getCachedOrCreateElement to call this generic function (for the element variant,
wrap the createHtml -> HTMLElement transformation inside the generic create
callback and validate the created element), ensuring behavior and eviction
semantics remain identical.

Comment on lines 326 to 347
// Add copy functionality to code blocks
div.querySelectorAll('.copy-code-btn').forEach(btn => {
btn.addEventListener('click', e => {
const button = e.target as HTMLButtonElement;
const codeId = button.getAttribute('data-code-id');
if (!codeId) {
return;
}

const codeElement = div.querySelector(`#${codeId}`);
if (!codeElement) {
return;
}

const code = codeElement.textContent ?? '';

navigator.clipboard.writeText(code).catch(() => {
// Clipboard API may fail if not in a secure context or permissions denied
console.warn('Failed to copy code to clipboard');
});
});
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Event listeners are attached but never removed - potential memory leak.

When the returned div element is removed from the DOM, the event listeners attached to .copy-code-btn and .download-table-btn elements will persist if those elements are cached and reused. Since cached elements (commentsToReplace) are cloned from the cache and inserted directly, their event listeners are re-attached on each render.

Consider using event delegation on the container div instead of attaching listeners to each button, which would automatically clean up when the container is removed.

🔎 Proposed fix using event delegation
-    // Add copy functionality to code blocks
-    div.querySelectorAll('.copy-code-btn').forEach(btn => {
-      btn.addEventListener('click', e => {
-        const button = e.target as HTMLButtonElement;
-        const codeId = button.getAttribute('data-code-id');
+    // Add copy functionality to code blocks using event delegation
+    div.addEventListener('click', e => {
+      const target = e.target as HTMLElement;
+      
+      // Handle copy code button clicks
+      if (target.classList.contains('copy-code-btn')) {
+        const codeId = target.getAttribute('data-code-id');
         if (!codeId) {
           return;
         }
-
         const codeElement = div.querySelector(`#${codeId}`);
         if (!codeElement) {
           return;
         }
-
         const code = codeElement.textContent ?? '';
-
         navigator.clipboard.writeText(code).catch(() => {
-          // Clipboard API may fail if not in a secure context or permissions denied
           console.warn('Failed to copy code to clipboard');
         });
-      });
+        return;
+      }
+      
+      // Handle download table button clicks
+      if (target.classList.contains('download-table-btn')) {
+        const tableId = target.getAttribute('data-table-id');
+        const tableIndexStr = target.getAttribute('data-table-index');
+        // ... rest of download logic
+      }
     });

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In projects/element-ng/markdown-renderer/markdown-renderer.ts around lines
326-347, per-button click listeners on .copy-code-btn (and related
.download-table-btn elsewhere) cause leaks because cloned/cached nodes get
reattached; replace those individual listeners with a single delegated click
handler on the parent div: add one click listener on the returned container that
inspects event.target (or closest('.copy-code-btn') /
closest('.download-table-btn')), reads data-code-id or data-download-id, and
performs copy/download logic accordingly; remove the loop that attaches
listeners to every button so tearing down the container automatically removes
the handlers.

@Killusions Killusions force-pushed the feat/add-ai-welcome-screen branch from 60b0a60 to 252d106 Compare December 23, 2025 13:07
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: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
docs/patterns/ai/ai-chat.md (1)

137-137: Clarify slot naming syntax.

The slot naming in line 137 uses slash notation (si-chat-input/siChatContainerInput) without clear explanation. Developers may not understand whether this represents two separate slots, an alternative name, or a hierarchical relationship.

🔎 Suggested improvement

Clarify the slot and directive relationship:

- `si-chat-input` with directive `siChatContainerInput` -> For the input (whether default or custom).

Or, if they are aliases, explicitly state that:

- `si-chat-input` (or `siChatContainerInput` helper directive) -> For the input (whether default or custom).
projects/element-ng/chat-messages/index.ts (1)

5-17: LGTM with minor ordering suggestion.

The new exports correctly expose the AI chat components and consolidated chat-message model. The alphabetical ordering of exports is broken by the new additions at lines 14-17 (si-tool-message, si-ai-chat-container, si-ai-welcome-screen appear after si-user-message).

Consider reordering for consistency:

🔎 Suggested reordering
 export * from './chat-message.model';
+export * from './si-ai-chat-container.component';
 export * from './si-ai-message.component';
+export * from './si-ai-welcome-screen.component';
 export * from './si-attachment-list.component';
 export * from './si-chat-container.component';
 export * from './si-chat-container-input.directive';
 export * from './si-chat-input.component';
 export * from './si-chat-input-disclaimer.directive';
 export * from './si-chat-message-action.directive';
 export * from './si-chat-message.component';
-export * from './si-tool-message.component';
+export * from './si-tool-message.component';
 export * from './si-user-message.component';
-export * from './si-ai-chat-container.component';
-export * from './si-ai-welcome-screen.component';
♻️ Duplicate comments (20)
projects/element-ng/chat-messages/si-tool-message.component.spec.ts (1)

165-171: Consider strengthening the signal output test.

As noted in a previous review, this test verifies that hasOutput() returns true when a signal is provided, but it doesn't verify that the component correctly unwraps and uses the signal value when formatting or displaying the output.

🔎 Suggested enhancement
  it('should handle signal output', () => {
    const outputSignal = signal('{"result": 20}');
    fixture.componentRef.setInput('output', outputSignal);
    fixture.detectChanges();

    expect((component as any).hasOutput()).toBe(true);
+   // Verify signal value is correctly unwrapped
+   const formatted = (component as any).formatData(outputSignal());
+   expect(formatted).toBe('{"result": 20}');
  });
projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts (1)

108-110: Null reference risk when createHtml() returns empty or text-only content.

tempDiv.firstElementChild can be null if createHtml() returns an empty string or text-only content without element nodes. The type assertion as HTMLElement masks this, causing runtime errors when downstream code accesses properties on a null value.

The XSS and null reference concerns raised in past reviews remain unaddressed. The JSDoc security warning and null check should be added.

projects/element-ng/markdown-renderer/markdown-renderer.ts (1)

326-347: Event listeners attached without cleanup - potential memory leak.

Per past review, event listeners are attached to each .copy-code-btn element but never removed. When the returned div is removed from the DOM, these listeners persist. Consider using event delegation on the container instead.

projects/element-ng/chat-messages/si-chat-container.component.scss (2)

23-29: Remove the unnecessary ::ng-deep pseudo-class.

The ::ng-deep is not needed with :has() since it naturally checks for descendant elements. This unnecessarily breaks component style encapsulation.

🔎 Proposed fix
-  ::ng-deep &:has(si-ai-welcome-screen) {
+  &:has(si-ai-welcome-screen) {
     inline-size: 100%;
     // stylelint-disable-next-line declaration-no-important
     padding-inline-start: 0 !important;
     // stylelint-disable-next-line declaration-no-important
     padding-inline-end: 0 !important;
   }

47-53: Remove unnecessary ::ng-deep from messages-container selectors.

The :has() pseudo-class already checks for descendant elements, so ::ng-deep is redundant and breaks component scoping.

🔎 Proposed fix
-  ::ng-deep &:not(:has(si-ai-welcome-screen)) {
+  &:not(:has(si-ai-welcome-screen)) {
     max-inline-size: 720px;
   }

-  ::ng-deep &:has(si-ai-welcome-screen) {
+  &:has(si-ai-welcome-screen) {
     inline-size: 100%;
   }
src/app/examples/si-chat-messages/si-ai-welcome-screen.html (1)

8-9: Consider using i18n for consistency.

The hardcoded English text could use translation keys to demonstrate best practices, as other parts of the example use the translate pipe.

projects/element-ng/chat-messages/si-ai-welcome-screen.component.html (1)

11-17: Consider tracking by a stable identifier.

This concern was raised in a previous review - using track $index can cause unnecessary re-renders if categories are reordered.

src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (1)

21-28: Potential mismatch between selectedCategory and category labels.

This concern was raised in a previous review - selectedCategory is initialized to 'all' but the categories array uses { label: 'All prompts' }, causing a mismatch since onCategoryClick uses the label property.

projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (1)

11-17: Consider adding an id field to PromptCategory.

The JSDoc at line 52-53 references "category ID" but the interface only has label. The component uses label as both the display text and identifier (line 90), which can cause confusion.

src/app/examples/si-chat-messages/si-chat-container.ts (1)

243-252: filteredPromptSuggestions does not update when selectedCategory changes.

The signal is initialized statically with allPromptSuggestions but never reacts to category selection. If filtering is intended, use a computed signal.

🔎 Suggested implementation if filtering is intended
-  readonly filteredPromptSuggestions = signal<PromptSuggestion[]>(this.allPromptSuggestions);
+  readonly filteredPromptSuggestions = computed(() => {
+    const category = this.selectedCategory();
+    if (!category || category === 'all') {
+      return this.allPromptSuggestions;
+    }
+    // Add category-based filtering logic here
+    return this.allPromptSuggestions;
+  });

If this is intentionally static for demonstration purposes, consider adding a clarifying comment.

projects/element-ng/chat-messages/si-tool-message.component.ts (4)

109-121: Signal detection is fragile; prefer isSignal from Angular core.

The check typeof data === 'function' && 'call' in data is unreliable since all functions have a call property. Use Angular's isSignal() utility instead.

🔎 Proposed fix
-import { Component, input, Signal, booleanAttribute } from '@angular/core';
+import { Component, input, Signal, booleanAttribute, isSignal } from '@angular/core';
 ...
 protected formatData(data: string | object | Signal<string | object> | undefined): string {
   if (data === undefined || data === null) return '';
-  const unwrappedData =
-    typeof data === 'function' && 'call' in data ? (data as Signal<string | object>)() : data;
+  const unwrappedData = isSignal(data) ? data() : data;
   ...
 }

123-130: Cache signal values to avoid redundant reads.

hasInputArguments() reads this.inputArguments() twice. While not critical, caching improves clarity.

🔎 Proposed fix
 protected hasInputArguments(): boolean {
-  return this.inputArguments() !== undefined && this.inputArguments() !== null;
+  const value = this.inputArguments();
+  return value !== undefined && value !== null;
 }

132-142: Remove dead code path or implement the documented behavior.

The comment on line 140 mentions showing loading for empty string output, but the method just returns false. Either implement this behavior or remove the misleading comment.

🔎 Suggested cleanup
 protected getLoadingState(): boolean {
-  const loadingValue = this.loading();
-
-  // If explicitly loading
-  if (loadingValue) {
-    return true;
-  }
-
-  // If output is empty string (not undefined), show loading
-  return false;
+  return this.loading();
 }

144-147: Remove redundant type assertion.

The cast as string | object | undefined matches the declared return type and serves no purpose.

🔎 Proposed simplification
 protected getOutputValue(): string | object | undefined {
-  const outputValue = this.output();
-  return outputValue as string | object | undefined;
+  return this.output();
 }
projects/element-ng/chat-messages/si-chat-input.component.ts (1)

147-155: Breaking change: sending and interruptible no longer coerce non-boolean values.

This was previously flagged. The change from input(false, { transform: booleanAttribute }) to model(false) removes automatic coercion of string values like "true" to boolean. Since the component is marked @experimental, this is acceptable.

projects/element-ng/chat-messages/chat-message.model.ts (1)

18-31: Consider typing the action parameter more specifically.

The action callback uses any for its first parameter. This was previously flagged—consider using unknown for better type safety.

src/app/examples/si-chat-messages/si-ai-chat-container.ts (2)

255-259: Loose typing on messagesSignal parameter.

This was previously flagged. Using any loses type safety. Consider WritableSignal<ChatMessage[]> for better documentation in example code.


262-279: Nested setTimeout calls lack cleanup on component destroy.

This was previously flagged. If the component is destroyed mid-simulation, these timeouts will still fire. Consider adding ngOnDestroy for lifecycle cleanup, or add a comment noting this simplification.

projects/element-ng/chat-messages/si-ai-chat-container.component.ts (2)

110-116: messageVersions WeakMap is never updated, breaking cache invalidation.

This was previously flagged. The messageVersions.get() on line 408 always returns undefined (defaulting to 0) since messageVersions.set() is never called. This means the cache on line 412 will always match on version, preventing invalidation when message actions change.


464-480: Type assertion in getContentValue returns empty string for falsy content.

The function returns '' as T when content is falsy, but T could be object. This type assertion is technically unsafe for object types. However, in practice, the callers use this for string content, so the runtime behavior is correct.

🔎 Consider a more type-safe approach
-  protected getContentValue<T extends string | object>(content: T | Signal<T> | undefined): T {
-    if (!content) return '' as T;
-    return isSignal(content) ? (content as Signal<T>)() : content;
+  protected getContentValue<T extends string | object>(content: T | Signal<T> | undefined): T | '' {
+    if (!content) return '';
+    return isSignal(content) ? (content as Signal<T>)() : content;
   }

Or use function overloads for string vs object content.

Comment on lines +24 to +28
<button si-action-card type="button" class="w-100" (click)="onPromptClick(suggestion)">
<div body class="card-body card-text text-white">
{{ suggestion.text }}
</div>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's find the si-action-card component definition
find . -type f \( -name "*action*card*" -o -name "*si-action*" \) | grep -E "\.(ts|component|scss|css|html)$"

Repository: siemens/element

Length of output: 621


🏁 Script executed:

# Search for si-action-card styling in SCSS files
rg "si-action-card" -t scss -A 10 -B 2

Repository: siemens/element

Length of output: 87


🏁 Script executed:

# Check for theme-aware text color utilities
rg "text-white|text-.*light|theme.*text" -t scss | head -30

Repository: siemens/element

Length of output: 87


🏁 Script executed:

# Look at the component file to understand context better
cat projects/element-ng/chat-messages/si-ai-welcome-screen.component.html | head -40

Repository: siemens/element

Length of output: 1219


🏁 Script executed:

# Search for any theme-related configurations or utilities
find . -type f -name "*theme*" | grep -E "\.(ts|scss|css|html)$" | head -20

Repository: siemens/element

Length of output: 713


🏁 Script executed:

# Read the si-action-card component implementation
cat ./projects/element-ng/card/si-action-card.component.ts

Repository: siemens/element

Length of output: 2079


🏁 Script executed:

# Read the si-action-card component template
cat ./projects/element-ng/card/si-action-card.component.html

Repository: siemens/element

Length of output: 1026


🏁 Script executed:

# Look for SCSS/CSS styling files for the card component
find ./projects/element-ng/card -type f \( -name "*.scss" -o -name "*.css" \)

Repository: siemens/element

Length of output: 108


🏁 Script executed:

# Check the theme styling to understand how light/dark themes work
head -100 ./projects/element-theme/src/theme.scss

Repository: siemens/element

Length of output: 1469


🏁 Script executed:

# Search for text color utilities in the codebase
rg "text-white|text-.*color|color.*utility" -A 3 -B 3 | head -50

Repository: siemens/element

Length of output: 4751


🏁 Script executed:

# Read the si-card.component.scss file
cat ./projects/element-ng/card/si-card.component.scss

Repository: siemens/element

Length of output: 1190


🏁 Script executed:

# Check the theme styling files to understand action-card background colors
cat ./projects/element-theme/src/theme/_theme-element.scss | head -200

Repository: siemens/element

Length of output: 12366


🏁 Script executed:

# Search for action-card specific styling in the codebase
rg "action-card" -t ts -t html -A 5 -B 2 | head -100

Repository: siemens/element

Length of output: 7240


🏁 Script executed:

# Check if Bootstrap's text-white is being used and what it does
rg "text-white" -A 2 -B 2 | head -50

Repository: siemens/element

Length of output: 2719


🏁 Script executed:

# Look for si-ai-welcome-screen component styling
find . -path "*/chat-messages/*welcome*" -type f \( -name "*.scss" -o -name "*.css" -o -name "*.ts" \)

Repository: siemens/element

Length of output: 275


🏁 Script executed:

# Read the welcome screen component TypeScript file
cat ./projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts

Repository: siemens/element

Length of output: 3255


🏁 Script executed:

# Check if there's a stylesheet for si-ai-welcome-screen
find ./projects/element-ng/chat-messages -name "*welcome*" -type f | head -20

Repository: siemens/element

Length of output: 347


🏁 Script executed:

# Look for default button styling or action-card background definition
rg "action-card|\.selected" -A 5 -B 2 | grep -E "(background|color|style)" | head -30

Repository: siemens/element

Length of output: 2755


🏁 Script executed:

# Check for any global Bootstrap button/card styling
rg "btn|button|card.*background" -t ts -t html | grep -i "light\|dark\|theme" | head -20

Repository: siemens/element

Length of output: 1013


🏁 Script executed:

# Read si-ai-welcome-screen component stylesheet
cat ./projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss

Repository: siemens/element

Length of output: 866


🏁 Script executed:

# Check the full card styling including default background
cat ./projects/element-theme/src/styles/bootstrap/_card.scss

Repository: siemens/element

Length of output: 6346


🏁 Script executed:

# Look for theme-aware text color utilities
rg "text-primary|text-secondary|text-inverse" -A 2 | head -40

Repository: siemens/element

Length of output: 3183


🏁 Script executed:

# Check what element-base-1 colors are in dark theme
cat ./projects/element-theme/src/theme/_theme-element.scss | grep -A 300 "theme-element-dark"

Repository: siemens/element

Length of output: 13471


🏁 Script executed:

# Verify the element-base-input-experimental color definition for light theme
rg "element-base-input-experimental" -A 1 -B 1 | head -20

Repository: siemens/element

Length of output: 1643


🏁 Script executed:

# Check what $card-color defaults to (the text color variable for cards)
rg "\$card-color|card-color:" -B 3 -A 3 | head -30

Repository: siemens/element

Length of output: 777


Replace hardcoded text-white with a theme-aware text color.

The text-white class creates poor contrast in light themes, where the action card background is set to a very light experimental blue color. Use text-primary instead, which automatically adjusts to dark text in light themes and white text in dark themes, or remove the class entirely to inherit the card's default text color handling.

🤖 Prompt for AI Agents
In projects/element-ng/chat-messages/si-ai-welcome-screen.component.html around
lines 24 to 27, the element uses the hardcoded class "text-white" which causes
poor contrast in light themes; replace "text-white" with "text-primary" (or
remove the text color class to inherit the card's default) so the text color
becomes theme-aware and retains proper contrast across light/dark themes; update
the class attribute on the <div body ...> accordingly and verify visual contrast
in both themes.

Comment on lines 427 to 429
// Add temporary closing backticks at the end to handle incomplete code blocks during streaming
const tempClosingMarker = `\n\`\`\`--TEMP-CLOSE--\n`;
html = html + tempClosingMarker;
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Temporary closing marker for streaming support is clever but fragile.

The temp closing marker approach handles incomplete code blocks during streaming, but the marker string --TEMP-CLOSE-- could theoretically appear in user content and be incorrectly stripped at line 529.

Consider using a more unique marker (e.g., include a random component like the other placeholders) to avoid false positives in edge cases.

🔎 Suggested improvement
-  const tempClosingMarker = `\n\`\`\`--TEMP-CLOSE--\n`;
+  const tempCloseId = Math.random().toString(36).substring(2, 15);
+  const tempClosingMarker = `\n\`\`\`--TEMP-CLOSE-${tempCloseId}--\n`;
   html = html + tempClosingMarker;
   
   // ... later ...
   
-  html = html.replace(tempClosingMarker, '').replace(/--TEMP-CLOSE--/g, '');
+  html = html.replace(tempClosingMarker, '').replace(new RegExp(`--TEMP-CLOSE-${tempCloseId}--`, 'g'), '');

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In projects/element-ng/markdown-renderer/markdown-renderer.ts around lines
427-429, the temporary closing marker `--TEMP-CLOSE--` is too generic and may
collide with user content; replace it with a unique marker that includes a
securely generated random component (e.g., append a UUID or crypto-random
string) when you create it and store that exact marker in a local variable, then
use that same variable when appending to html and when later stripping it out so
only the exact injected marker is removed; ensure the random generator produces
URL-safe characters and that any existing placeholder-removal code matches the
marker exactly.

Comment on lines 1 to 13
<div class="si-layout-fixed-height w-100 h-100">
<si-ai-chat-container
statusSeverity="info"
statusMessage="AI responses are for demonstration purposes."
colorVariant="base-0"
[messages]="messages()"
[sending]="sending()"
[loading]="loading()"
[disableInterrupt]="disableInterrupt()"
[interrupting]="interrupting()"
[syntaxHighlighter]="syntaxHighlighter"
[promptSuggestions]="promptSuggestionsByCategory"
>
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider internationalizing hardcoded user-facing strings.

While hardcoded strings are acceptable in example files, using i18n keys for user-facing text (lines 4, 16-17, 45) demonstrates best practices and makes examples more educational.

🤖 Prompt for AI Agents
In src/app/examples/si-chat-messages/si-ai-chat-container.html around lines 1 to
13, replace hardcoded user-facing strings with i18n keys: extract messages like
"AI responses are for demonstration purposes." (and any other hardcoded labels
referenced in the review) into translation keys and bind them using the app's
i18n mechanism (e.g., translate pipe or i18n attribute), update the template to
use those keys instead of literal text, and ensure corresponding entries are
added to the translations files for each supported locale.

Comment on lines +84 to +89
## Images

Images can be included as follows:

![Building Image](./assets/images/building-1.webp)

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for the image file
echo "=== Searching for building-1.webp ==="
find . -name "building-1.webp" -type f

echo ""
echo "=== Checking directory structure in src/assets/ ==="
ls -la src/assets/ 2>/dev/null || echo "src/assets/ does not exist or is not accessible"

echo ""
echo "=== Looking for any image files in src/assets/ ==="
find src/assets/ -type f -name "*.webp" -o -type f -name "*.png" -o -type f -name "*.jpg" -o -type f -name "*.jpeg" 2>/dev/null

echo ""
echo "=== Repository structure overview ==="
git ls-files | head -30

Repository: siemens/element

Length of output: 1816


Fix image path in markdown.

Line 88 references ./assets/images/building-1.webp, but the file is located at src/assets/sample-markdown.md. If the markdown renderer resolves relative paths from the file location, this path would incorrectly resolve to src/assets/assets/images/building-1.webp. The correct relative path should be ./images/building-1.webp.

The image file exists at src/assets/images/building-1.webp, so update the markdown reference accordingly.

🤖 Prompt for AI Agents
In src/assets/sample-markdown.md around lines 84 to 89, the image path
references ./assets/images/building-1.webp which will resolve to
src/assets/assets/images/building-1.webp; update the markdown image reference to
use the correct relative path ./images/building-1.webp so it points to the
existing file at src/assets/images/building-1.webp.

@github-actions
Copy link

@Killusions Killusions force-pushed the feat/add-ai-welcome-screen branch from 252d106 to 33d9fb0 Compare December 23, 2025 13:24
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: 3

♻️ Duplicate comments (4)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.html (1)

1-33: Template structure is well-organized.

The component template correctly implements:

  • Content projection via <ng-content /> for the welcome header
  • Conditional rendering for categories and suggestions using Angular's new control flow syntax
  • Proper event binding for category and prompt selection

Note: Previous review comments already addressed the track $index optimization (consider track category.label) and the text-white contrast issue. Please address those recommendations.

docs/patterns/ai/ai-chat.md (1)

89-101: Documentation improvements needed.

The documentation is helpful but has clarity issues already noted in previous reviews:

  1. Line 89: The fixed height requirement phrasing could be clearer
  2. Lines 95-97: The relationship between "built-in" and "slotted" is ambiguous

Please address the previous review suggestions to clarify whether si-ai-welcome-screen is automatically included or optionally slotted.

src/app/examples/si-chat-messages/si-ai-chat-container.html (1)

36-42: Empty button content—add visible close icon.

The close button is empty between its tags. While the element-cancel class may provide styling, the button should contain an explicit icon element for proper rendering and accessibility.

🔎 Proposed fix
     <button
       type="button"
       class="btn btn-circle btn-sm btn-ghost element-cancel"
       aria-label="Close modal"
       (click)="modalRef.hide('cancel')"
     >
+      <si-icon icon="element-cancel" />
     </button>
projects/element-ng/chat-messages/si-ai-chat-container.component.ts (1)

110-116: messageVersions WeakMap is never updated, preventing cache invalidation.

The caching mechanism retrieves a version from messageVersions (line 421) but never calls messageVersions.set() to update it. This means:

  • The version always defaults to 0
  • Once cached with version: 0, the check on line 425 always passes
  • Message actions cannot be invalidated when they change
🔎 Proposed fix

When creating or updating the cache entry, increment and store the version:

   private getMessageActions(message: ChatMessage): {
     primary: MessageAction[];
     secondary: MenuItem[];
     version: number;
   } {
     if (this.isTemplateMessage(message) || message.type === 'tool') {
       return { primary: [], secondary: [], version: 0 };
     }

     const actions = message.actions ?? [];

-    // Get or create version number for this message
-    const version = this.messageVersions.get(message) ?? 0;
+    // Get current version and increment for new cache entry
+    const currentVersion = this.messageVersions.get(message) ?? 0;
+    const version = currentVersion + 1;

     // Check if we have a cached version that matches
     const cached = this.messageActionsCache.get(message);
-    if (cached?.version === version) {
+    if (cached?.version === currentVersion) {
       return cached;
     }

     // Build primary and secondary actions
     const primary = actions.slice(0, 3);
     const secondary = actions.slice(3).map(
       action =>
         ({
           ...action,
           action: action.action as unknown as (actionParam: any, source: MenuItem) => void,
           type: 'action'
         }) as MenuItem
     );

     const result = { primary, secondary, version };
     this.messageActionsCache.set(message, result);
+    this.messageVersions.set(message, version);

     // Return the cached object to maintain reference equality
     return result;
   }

Also applies to: 409-445

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 252d106 and 33d9fb0.

⛔ Files ignored due to path filters (2)
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-light-linux.png is excluded by !**/*.png
📒 Files selected for processing (12)
  • api-goldens/element-ng/chat-messages/index.api.md
  • api-goldens/element-ng/translate/index.api.md
  • docs/patterns/ai/ai-chat.md
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yaml
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
🧰 Additional context used
🧠 Learnings (23)
📚 Learning: 2025-12-09T14:31:33.543Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:14-50
Timestamp: 2025-12-09T14:31:33.543Z
Learning: In projects/element-ng/chat-messages/si-ai-chat-container.component.html, message IDs can change, so tracking by message.id is not appropriate. The component uses `track message` (object identity) which is the correct approach for this use case.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
📚 Learning: 2025-12-09T14:32:26.166Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:21-47
Timestamp: 2025-12-09T14:32:26.166Z
Learning: In Angular templates, prefer using nested *ngIf blocks over *ngSwitch for branching on message types within the chat-messages components. Use *ngIf with else branches to handle distinct cases and avoid complex switch logic in HTML templates. This guideline applies to all HTML templates under projects/element-ng/chat-messages.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
📚 Learning: 2025-11-18T12:37:30.510Z
Learnt from: Killusions
Repo: siemens/element PR: 1040
File: projects/element-ng/chat-messages/si-chat-input.component.ts:338-349
Timestamp: 2025-11-18T12:37:30.510Z
Learning: In projects/element-ng/chat-messages/si-chat-input.component.ts, the interrupt behavior is intentionally different for button clicks vs Enter key: the button can emit interrupt even without content, but pressing Enter requires content or attachments (canSend() must be true) to emit interrupt.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
📚 Learning: 2025-12-11T10:09:01.564Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1151
File: projects/element-ng/auto-collapsable-list/si-auto-collapsable-list.directive.spec.ts:83-104
Timestamp: 2025-12-11T10:09:01.564Z
Learning: In the auto-collapsable-list directive tests (projects/element-ng/auto-collapsable-list/si-auto-collapsable-list.directive.spec.ts), jasmine.clock() successfully controls the directive's setTimeout-based layout logic in zoneless mode. Mock timers work fine here, unlike in select component overflow tests where real setTimeout waits are required.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-15T07:16:53.762Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:92-105
Timestamp: 2025-12-15T07:16:53.762Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits must be used instead of fixture.whenStable() to avoid injector destroyed errors during mount/unmount operations in zoneless mode. The GridStack timing-dependent operations require actual async delays.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-15T07:16:32.082Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:69-80
Timestamp: 2025-12-15T07:16:32.082Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing grid item rendering and initialization. This is likely due to gridstack library's initialization timing or lifecycle behavior that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-08T11:25:51.584Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/si-select.component.spec.ts:511-516
Timestamp: 2025-12-08T11:25:51.584Z
Learning: In the select component overflow tests (projects/element-ng/select/si-select.component.spec.ts), jasmine.clock() cannot be used to control the timing for overflow item detection. Real setTimeout waits must be used instead, likely due to ResizeObserver or debounced layout calculations that jasmine.clock() cannot control in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-15T07:17:06.981Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts:37-49
Timestamp: 2025-12-15T07:17:06.981Z
Learning: In widget-instance-editor-dialog component tests (projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing component initialization. This is likely due to the component's lifecycle behavior or modal initialization timing that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-08T11:25:20.861Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/si-select.component.spec.ts:204-205
Timestamp: 2025-12-08T11:25:20.861Z
Learning: In zoneless Angular tests (using provideZonelessChangeDetection), calling fixture.changeDetectorRef.markForCheck() before fixture.detectChanges() is required even for components using the default change detection strategy (not OnPush). This differs from zone.js-based testing where markForCheck is primarily needed only for OnPush components.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-01T14:12:11.111Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1104
File: projects/element-ng/datepicker/components/si-day-selection.component.spec.ts:198-202
Timestamp: 2025-12-01T14:12:11.111Z
Learning: In zoneless Angular tests (using provideZonelessChangeDetection), prefer `await fixture.whenStable()` over `fixture.detectChanges()` after dispatching events or triggering async operations, as `whenStable()` waits for all asynchronous operations to complete and better mimics the production environment.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-04T05:50:38.735Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1135
File: projects/element-ng/tree-view/si-tree-view.component.spec.ts:1244-1245
Timestamp: 2025-12-04T05:50:38.735Z
Learning: In zoneless Angular tests with OnPush components, calling `await runOnPushChangeDetection(fixture)` followed by `await fixture.whenStable()` is NOT redundant. The `runOnPushChangeDetection` helper forces change detection to run for OnPush components, while `whenStable()` waits for all async operations to complete. Both are necessary and serve different purposes.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-15T10:05:59.100Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1193
File: projects/element-ng/search-bar/si-search-bar.component.spec.ts:21-28
Timestamp: 2025-12-15T10:05:59.100Z
Learning: In tests that rely on Jasmine's fake clock to control time-based RxJS operators (e.g., debounceTime), use jasmine.clock().install() together with jasmine.clock().mockDate() to enable precise timing control. Without mockDate, scheduler-based operators may not respond to the fake clock. Apply this guidance to spec files (e.g., any file named *.spec.ts or *.spec.js) that test time-sensitive behavior, ensuring you install and mockDate before advancing time in tests.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-17T04:34:55.597Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1173
File: src/app/examples/si-charts/interactive/interactive.ts:5-5
Timestamp: 2025-12-17T04:34:55.597Z
Learning: Guideline: In Angular projects using OnPush change detection (zoneless mode), you only need to call ChangeDetectorRef.markForCheck() for asynchronous operations (e.g., setTimeout, setInterval, Promises, Observables) where a change is not automatically detected. Event handlers triggered by Angular template bindings (click, input, etc.) will trigger change detection automatically and do not require explicit markForCheck() calls. Apply this broadly to TS files within Angular components/services that use OnPush; use markForCheck() selectively for async work where change detection wouldn’t run otherwise.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
📚 Learning: 2025-12-16T16:19:17.950Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1207
File: playwright/snapshots/si-filtered-search.spec.ts-snapshots/si-filtered-search--si-filtered-search-playground--data-entered.yaml:38-38
Timestamp: 2025-12-16T16:19:17.950Z
Learning: Do not review files in the playwright/snapshots directory, as they contain auto-generated test artifacts. Exclude any YAML snapshot files under playwright/snapshots from code reviews in the siemens/element repository. If a YAML file is not an auto-generated snapshot, verify its origin before skipping.

Applied to files:

  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yaml
📚 Learning: 2025-12-23T09:24:35.163Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/translate/index.api.md:12-84
Timestamp: 2025-12-23T09:24:35.163Z
Learning: In the siemens/element repository, do not review files under the api-goldens/ directory (e.g., api-goldens/**/index.api.md) since they are auto-generated by API Extractor. Exclude these from review checks and focus on source files that are not auto-generated.

Applied to files:

  • api-goldens/element-ng/translate/index.api.md
  • api-goldens/element-ng/chat-messages/index.api.md
📚 Learning: 2025-12-23T09:24:57.843Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/index.api.md:324-325
Timestamp: 2025-12-23T09:24:57.843Z
Learning: Do not review files in the api-goldens directory, as they are auto-generated API reports produced by API Extractor.

Applied to files:

  • api-goldens/element-ng/translate/index.api.md
  • api-goldens/element-ng/chat-messages/index.api.md
📚 Learning: 2025-12-23T09:24:40.395Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/module-federation/index.api.md:7-11
Timestamp: 2025-12-23T09:24:40.395Z
Learning: In the siemens/element repository, do not review any files under the api-goldens directory, as they are auto-generated API reports produced by API Extractor. These MD files should be excluded from review unless explicitly overridden.

Applied to files:

  • api-goldens/element-ng/translate/index.api.md
  • api-goldens/element-ng/chat-messages/index.api.md
📚 Learning: 2025-12-09T14:32:34.036Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:21-47
Timestamp: 2025-12-09T14:32:34.036Z
Learning: In projects/element-ng/chat-messages, nested if blocks are preferred over switch statements for branching on message types in Angular templates.

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • api-goldens/element-ng/chat-messages/index.api.md
📚 Learning: 2025-12-11T14:44:11.278Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1185
File: projects/element-ng/navbar/si-navbar-item/si-navbar-item.component.html:11-11
Timestamp: 2025-12-11T14:44:11.278Z
Learning: The si-icon component in siemens/element-ng/icon automatically applies aria-hidden="true" to its content. Do not suggest adding aria-hidden="true" to si-icon elements, as accessibility is already handled internally by the component.

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-chat-container.html
📚 Learning: 2025-12-22T13:04:20.883Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: src/app/examples/ag-grid/ag-grid-empty-state.ts:20-24
Timestamp: 2025-12-22T13:04:20.883Z
Learning: The SiEmptyStateComponent in siemens/element-ng accepts icon names in kebab-case format (e.g., 'element-technical-operator') that may not be directly exported as constants in the element-icons.ts file. Do not flag these as errors if they render correctly at runtime.

Applied to files:

  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • api-goldens/element-ng/chat-messages/index.api.md
📚 Learning: 2025-12-08T11:24:45.272Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/options/si-select-lazy-options.directive.spec.ts:67-85
Timestamp: 2025-12-08T11:24:45.272Z
Learning: In select lazy options tests (projects/element-ng/select/options/si-select-lazy-options.directive.spec.ts), jasmine.clock() cannot control RxJS debounceTime in zoneless mode. Real setTimeout waits must be used instead for tests involving search debouncing.

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-04T05:50:17.637Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1135
File: projects/element-ng/tree-view/si-tree-view.component.spec.ts:953-964
Timestamp: 2025-12-04T05:50:17.637Z
Learning: In the siemens/element repository, when making tree-view tests zoneless-ready, jasmine.clock() should be used to mimic setTimeouts even in zoneless mode, as the component implementation relies on setTimeout calls that need to be controlled in tests.

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-09T14:33:54.441Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: src/app/examples/si-chat-messages/si-ai-message.ts:24-43
Timestamp: 2025-12-09T14:33:54.441Z
Learning: In src/app/examples/ (example/demo code) directories, allow and expect code duplication. Treat duplication as acceptable for demonstration code that aims to illustrate usage rather than enforce DRY. Do not enforce refactoring to remove duplication in example files; focus on readability and clarity of examples. This applies to all TypeScript files under src/app/examples (including nested subdirectories like si-chat-messages).

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
🧬 Code graph analysis (1)
projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts (1)
projects/element-ng/chat-messages/chat-message.model.ts (2)
  • ChatMessage (157-157)
  • MessageAction (18-31)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (12)
projects/element-ng/translate/si-translatable-keys.interface.ts (1)

6-8: New translatable keys follow established conventions.

The new keys for AI chat container, markdown renderer, and tool message components are correctly added:

  • Alphabetically ordered within their component groups
  • Follow the SI_COMPONENT.ACTION naming convention
  • Properly defined as optional strings

Also applies to: 171-172, 222-223

projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (1)

66-82: Well-implemented filtering logic with appropriate type handling.

The filteredPromptSuggestions computed property correctly handles both input types:

  • Returns array as-is when promptSuggestions is an array
  • Returns category-specific suggestions when a category is selected
  • Falls back to flattened suggestions when no category is selected

The logic is clean and handles edge cases properly.

docs/patterns/ai/ai-chat.md (1)

112-124: Code examples are well-structured.

The TypeScript examples clearly demonstrate both usage patterns:

  • Simple array for flat suggestions
  • Record with categories for grouped suggestions

This provides good developer guidance.

projects/element-ng/chat-messages/si-ai-chat-container.component.html (2)

19-67: Message rendering follows established patterns.

The implementation correctly:

  • Uses track message for object identity tracking (per project guidelines)
  • Uses nested @if blocks instead of @switch for message type branching (per project guidelines)
  • Properly handles template messages via ngTemplateOutlet
  • Separates user, AI, and tool message rendering with appropriate bindings

Based on learnings, this approach is correct for the chat-messages components.


70-78: Status notification rendering is correct.

The conditional check @if (statusSeverity() && statusMessage()) ensures both values are present before rendering, and the non-null assertions are safe within this guard.

src/app/examples/si-chat-messages/si-ai-chat-container.html (1)

1-30: Example demonstrates comprehensive feature usage.

The example showcases:

  • Status notifications
  • Multiple input bindings (placeholder, disclaimer, attachments)
  • Event handling (send, interrupt, fileError)
  • Prompt suggestions integration

This provides good reference for consumers of the component.

playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yaml (1)

1-30: Auto-generated snapshot file - skipping review.

Per project guidelines, Playwright snapshot files in playwright/snapshots/ are auto-generated test artifacts and should not be manually reviewed.

projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts (4)

20-30: Test setup follows zoneless Angular patterns correctly.

The test configuration properly uses:

  • provideZonelessChangeDetection() for zoneless testing
  • provideNoopAnimations() for animation handling
  • Standard TestBed.configureTestingModule pattern

This aligns with the project's testing conventions.


460-500: Action caching tests validate important optimization.

The tests for action handling (lines 460-500) properly verify:

  • Primary/secondary action splitting when more than 3 actions exist
  • Caching behavior for memoization

This ensures consistent behavior and performance for message actions.


1-501: Comprehensive test coverage for the new component.

The test suite provides excellent coverage including:

  • Default state verification
  • Message type rendering (user, AI, tool)
  • Welcome screen behavior
  • Loading and interrupting states
  • Signal content handling and updates
  • Action caching and splitting
  • Input propagation to child components

Well-structured tests that follow project patterns.


121-136: Remove unnecessary content property from tool message test.

The content property is optional in the ToolChatMessage interface (inherited from BaseChatMessage), so the content: '' assignment on line 127 is redundant and can be removed.

src/app/examples/si-chat-messages/si-ai-chat-container.ts (1)

1-299: Example code demonstrates AI chat container usage effectively.

The component provides a clear demonstration of:

  • Syntax highlighting and LaTeX rendering integration
  • Message state management with signals
  • Prompt suggestions and categorization
  • Action handlers and UI state toggles
  • Simulated AI response flow

The messagesSignal typing issue from previous reviews has been resolved (line 256). The nested setTimeout calls in simulateAiResponse (lines 280-297) lack lifecycle cleanup, but this simplification is acceptable for demonstration purposes.

Comment on lines 10 to 13
<p class="h1 mb-0 text-white">
<strong>{{ greeting() | translate }}</strong>
</p>
<p class="h1 mb-0 text-white">{{ welcomeMessage() | translate }}</p>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Consider theme-aware text color for welcome messages.

Similar to the issue in si-ai-welcome-screen.component.html, the hardcoded text-white class on the greeting and welcome message may create poor contrast in light themes. Consider using a theme-aware alternative or ensuring the parent container always provides sufficient contrast.

🔎 Proposed fix
-      <p class="h1 mb-0 text-white">
+      <p class="h1 mb-0">
         <strong>{{ greeting() | translate }}</strong>
       </p>
-      <p class="h1 mb-0 text-white">{{ welcomeMessage() | translate }}</p>
+      <p class="h1 mb-0">{{ welcomeMessage() | translate }}</p>

If white text is required, ensure the welcome screen container has a guaranteed dark background in all themes.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<p class="h1 mb-0 text-white">
<strong>{{ greeting() | translate }}</strong>
</p>
<p class="h1 mb-0 text-white">{{ welcomeMessage() | translate }}</p>
<p class="h1 mb-0">
<strong>{{ greeting() | translate }}</strong>
</p>
<p class="h1 mb-0">{{ welcomeMessage() | translate }}</p>
🤖 Prompt for AI Agents
In projects/element-ng/chat-messages/si-ai-chat-container.component.html around
lines 10 to 13, the greeting and welcome message use the hardcoded "text-white"
class which can cause poor contrast in light themes; replace this with a
theme-aware class or conditional binding (e.g., a CSS utility or component class
that switches text color based on current theme) or remove "text-white" and
ensure the parent container enforces a dark background in all themes so contrast
is always sufficient.

@Killusions Killusions force-pushed the feat/add-ai-welcome-screen branch 2 times, most recently from ff44574 to 6ec8dde Compare December 30, 2025 09:23
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: 3

♻️ Duplicate comments (31)
projects/element-ng/chat-messages/si-chat-container.component.scss (2)

23-29: Remove unnecessary ::ng-deep from this selector.

The ::ng-deep &:has(si-ai-welcome-screen) pattern is unnecessary and potentially problematic. The :has() pseudo-class naturally checks for descendant elements, and prepending ::ng-deep to the parent reference & can leak styles globally.

🔎 Proposed fix
-  ::ng-deep &:has(si-ai-welcome-screen) {
+  &:has(si-ai-welcome-screen) {
     inline-size: 100%;
     // stylelint-disable-next-line declaration-no-important
     padding-inline-start: 0 !important;
     // stylelint-disable-next-line declaration-no-important
     padding-inline-end: 0 !important;
   }

47-53: Remove unnecessary ::ng-deep from messages-container selectors.

Same issue as above: ::ng-deep before &:has() and &:not(:has()) is unnecessary and can cause style leakage.

🔎 Proposed fix
-  ::ng-deep &:not(:has(si-ai-welcome-screen)) {
+  &:not(:has(si-ai-welcome-screen)) {
     max-inline-size: 720px;
   }

-  ::ng-deep &:has(si-ai-welcome-screen) {
+  &:has(si-ai-welcome-screen) {
     inline-size: 100%;
   }
src/app/examples/si-chat-messages/si-ai-welcome-screen.html (1)

8-9: Consider using i18n for consistency.

The welcome text is hardcoded in English. For consistency with the library component templates that use the translate pipe and to demonstrate best practices in examples, consider making these strings translatable.

🔎 Suggested approach
-    <p class="h1 mb-0 text-white"> <strong>Hello</strong>, </p>
-    <p class="h1 mb-0 text-white">how can I help you today?</p>
+    <p class="h1 mb-0 text-white"> <strong>{{ 'EXAMPLE.HELLO' | translate }}</strong>, </p>
+    <p class="h1 mb-0 text-white">{{ 'EXAMPLE.HOW_CAN_I_HELP' | translate }}</p>
docs/patterns/ai/ai-chat.md (2)

95-101: Clarify welcome screen architecture.

The text describes the welcome screen as both "built-in" and "can be slotted," which creates ambiguity about whether it's required or optional.

🔎 Suggested clarification

If the welcome screen is optional:

-The AI chat container includes a built-in initial welcome screen component that displays when there are no messages. It can be slotted into the **si-chat-container** component. It accepts prompt suggestions as an input.
+The AI chat container includes a default initial welcome screen that displays when there are no messages. You can customize or replace it by providing your own si-ai-welcome-screen component via the default slot. It accepts prompt suggestions as an input.

If the welcome screen is always present:

-The AI chat container includes a built-in initial welcome screen component that displays when there are no messages. It can be slotted into the **si-chat-container** component. It accepts prompt suggestions as an input.
+The si-ai-chat-container automatically includes the si-ai-welcome-screen component as its initial state, displaying when there are no messages. It accepts prompt suggestions as an input.

89-93: Clarify fixed height requirement.

The phrasing "it should be inserted into a layout with fixed height, if no fixed height is provided, please set a height in pixels" is somewhat unclear. Consider rewording for clarity.

🔎 Suggested improvement
-The **si-ai-chat-container** component provides a complete AI chat interface, it should be inserted into a layout with fixed height, if no fixed height is provided, please set a height in pixels.
+The **si-ai-chat-container** component provides a complete AI chat interface with an integrated welcome screen. It requires a fixed height constraint; if the parent layout does not provide one, explicitly set the component height in pixels.
projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss (1)

37-39: ::ng-deep is deprecated.

This was flagged in a previous review. Consider the alternatives mentioned there (CSS custom properties, ViewEncapsulation.None, or exposing component inputs).

src/app/examples/si-chat-messages/si-ai-chat-container.html (1)

36-42: Empty close button still lacks visible content.

This was flagged in a previous review. The button between lines 36-42 has no visible icon or text content—only the element-cancel class. Add an icon element or visible content for proper rendering.

projects/element-ng/chat-messages/si-ai-welcome-screen.component.html (3)

11-11: Consider tracking by a stable identifier.

The loop uses track $index, which can cause unnecessary re-renders if categories are reordered. Consider track category.label for more stable tracking, assuming labels are unique.


25-25: Replace hardcoded text-white with theme-aware text color.

The text-white class creates poor contrast in light themes where the action card background is light. Remove the text-white class to inherit the card's default text color handling, which automatically adjusts for theme.

🔎 Proposed fix
-            <div body class="card-body card-text text-white">
+            <div body class="card-body card-text">

23-23: Consider tracking suggestions by a stable identifier.

Similar to the categories loop, using track $index for suggestions can cause unnecessary re-renders if the array is reordered. If suggestions have a unique identifier (e.g., id or text), consider tracking by that property instead.

projects/element-ng/chat-messages/si-ai-chat-container.component.html (1)

10-13: Replace hardcoded text-white with theme-aware text color.

The hardcoded text-white class may create poor contrast in light themes. Remove the class to ensure proper contrast across all themes, or ensure the parent container guarantees a dark background in all themes.

🔎 Proposed fix
-      <p class="h1 mb-0 text-white">
+      <p class="h1 mb-0">
         <strong>{{ greeting() | translate }}</strong>
       </p>
-      <p class="h1 mb-0 text-white">{{ welcomeMessage() | translate }}</p>
+      <p class="h1 mb-0">{{ welcomeMessage() | translate }}</p>
projects/element-ng/chat-messages/si-tool-message.component.scss (2)

15-17: Usage of ::ng-deep for child component styling.

While ::ng-deep is deprecated, it remains necessary for styling encapsulated child components until Angular provides stable alternatives. The usage here for adjusting spinner size is appropriate.


77-97: Usage of ::ng-deep for collapsible panel styling.

Similar to the spinner styling, ::ng-deep is used here to adjust internal collapsible panel structure. This is an acceptable pattern until Angular provides alternatives for styling encapsulated children.

projects/element-ng/chat-messages/si-tool-message.component.spec.ts (1)

165-171: Strengthen the signal output test.

The test verifies hasOutput() returns true when a signal is provided, but doesn't verify that the component correctly unwraps the signal value when formatting/displaying output.

🔎 Suggested enhancement
  it('should handle signal output', () => {
    const outputSignal = signal('{"result": 20}');
    fixture.componentRef.setInput('output', outputSignal);
    fixture.detectChanges();

    expect((component as any).hasOutput()).toBe(true);
+   // Verify signal value is correctly unwrapped
+   const formatted = (component as any).formatData(outputSignal());
+   expect(formatted).toBe('{"result": 20}');
  });
src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (2)

21-28: Potential mismatch between selectedCategory and category labels.

The selectedCategory signal is initialized to 'all', but promptCategories contains { label: 'All prompts' }. Since onCategoryClick (in the component being demonstrated) sets selectedCategory using the category's label property, the initial value 'all' won't match any category label.

🔎 Suggested alignment

Option 1: Initialize to match the label:

- readonly selectedCategory = signal<string>('all');
+ readonly selectedCategory = signal<string>('All prompts');

Option 2: Use undefined for no initial selection:

- readonly selectedCategory = signal<string>('all');
+ readonly selectedCategory = signal<string | undefined>(undefined);

30-37: Consider demonstrating category-based filtering in the example.

The promptSuggestions uses a flat array format, which doesn't showcase the SiAiWelcomeScreenComponent's category filtering feature. Consider using the Record<string, PromptSuggestion[]> format to better demonstrate this capability.

This is optional as the example may intentionally show the simple array format.

projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts (1)

186-228: Consider testing internal computed signals through observable behavior.

Multiple tests access internal computed signals via (component as any) type casting (e.g., inputInterruptible(), inputSending()). While functional, this bypasses TypeScript safety and couples tests to private implementation details.

Consider:

  1. Testing the observable effects these signals drive (e.g., input component state, UI elements)
  2. Exposing these as public test-only getters if they represent important component behavior

This is a minor suggestion; the current approach is functional.

projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (1)

11-17: Past feedback still applies: Consider adding an id field to PromptCategory.

The PromptCategory interface uses label for both display and identification. As noted in the past review, the example code shows selectedCategory initialized to 'all' while categories use labels like 'All prompts', which creates potential confusion.

projects/element-ng/markdown-renderer/markdown-renderer.ts (3)

326-347: Event delegation would be cleaner, but current approach is not a true memory leak.

The past review suggested event delegation to avoid memory leaks. While the current per-button listener approach is not ideal, it's not a true memory leak: when the containing div is removed from the DOM, the buttons and their listeners become unreachable and will be garbage collected. Event delegation on the container div would still be a cleaner pattern, as suggested previously.


265-269: Document the purpose of duplicate table tag removal.

As noted in the past review, this complex regex that removes duplicate table tags would benefit from a brief comment explaining when this situation occurs (e.g., adjacent table rows can cause nested table wrappers).


427-429: Temp closing marker could theoretically collide with user content.

As noted previously, the static --TEMP-CLOSE-- marker could appear in user content. Consider using a unique marker with a random component like other placeholders.

src/app/examples/si-chat-messages/si-chat-container.ts (1)

243-252: filteredPromptSuggestions remains static despite selectedCategory changes.

As noted in the past review, filteredPromptSuggestions is initialized with all suggestions but never updates when selectedCategory changes. If category-based filtering is intended for this demo, consider using a computed signal. If this is intentionally simplified for demonstration purposes, a comment would clarify the intent.

projects/element-ng/chat-messages/si-tool-message.component.ts (4)

109-121: Signal detection is fragile; prefer isSignal from Angular core.

As noted in the past review, the check typeof data === 'function' && 'call' in data is unreliable since all functions have a call property. Angular provides isSignal() for this purpose.

🔎 Proposed fix
-import { Component, input, Signal, booleanAttribute } from '@angular/core';
+import { Component, input, Signal, booleanAttribute, isSignal } from '@angular/core';

 protected formatData(data: string | object | Signal<string | object> | undefined): string {
   if (data === undefined || data === null) return '';
-  const unwrappedData =
-    typeof data === 'function' && 'call' in data ? (data as Signal<string | object>)() : data;
+  const unwrappedData = isSignal(data) ? data() : data;
   // ...
 }

123-130: Multiple signal reads; consider caching the value.

As noted previously, hasInputArguments() invokes this.inputArguments() twice. Cache the value in a local variable.

🔎 Proposed fix
 protected hasInputArguments(): boolean {
-  return this.inputArguments() !== undefined && this.inputArguments() !== null;
+  const value = this.inputArguments();
+  return value !== undefined && value !== null;
 }

132-142: getLoadingState contains dead code path.

As noted in the past review, the comment on line 140 mentions showing loading for empty string output, but the method just returns false. Either implement the behavior or remove the misleading comment.

🔎 Suggested cleanup
 protected getLoadingState(): boolean {
-  const loadingValue = this.loading();
-
-  // If explicitly loading
-  if (loadingValue) {
-    return true;
-  }
-
-  // If output is empty string (not undefined), show loading
-  return false;
+  return this.loading();
 }

144-147: Redundant type assertion in getOutputValue.

As noted previously, the cast matches the declared return type and serves no purpose. Simplify to return this.output();.

src/app/examples/si-chat-messages/si-ai-chat-container.ts (2)

273-276: Loose typing on messagesSignal parameter; consider WritableSignal<ChatMessage[]>.

As noted in the past review, using any loses type safety. Since this is example code demonstrating proper usage patterns, stronger typing would serve as better documentation.


280-297: Nested setTimeout calls lack cleanup on component destroy.

As noted previously, if the component is destroyed mid-simulation, these timeouts will still fire. Other examples in this codebase implement ngOnDestroy for lifecycle cleanup. Consider adding it here or adding a comment noting this simplification is intentional for the demo.

projects/element-ng/chat-messages/si-chat-input.component.ts (1)

147-155: Breaking change: sending and interruptible no longer coerce non-boolean values.

As noted in the past review, changing from input(false, { transform: booleanAttribute }) to model(false) removes automatic coercion of string values like "true" to boolean. Parents must now pass actual boolean values. Since the component is marked @experimental, this is acceptable but worth noting in migration documentation.

projects/element-ng/chat-messages/si-ai-chat-container.component.ts (2)

108-114: [Previously flagged] messageVersions WeakMap is never updated, breaking cache invalidation.

This issue was identified in a previous review and remains unresolved. The cache will always return stale data once populated since the version tracking is non-functional.


541-559: [Previously flagged] Off-by-one boundary check could benefit from clarifying comment.

The suggested comment from the previous review has not been applied. The logic is correct, but a comment would improve maintainability.

Comment on lines 27 to 53
// Numbers, literals
.hljs-number,
.hljs-literal,
.hljs-variable,
.hljs-template-variable {
color: variables.$element-text-primary;
}

// Strings
.hljs-string,
.hljs-doctag {
color: variables.$element-text-secondary;
}

// Function names, class names
.hljs-title,
.hljs-section,
.hljs-selector-id {
color: variables.$element-text-primary;
font-weight: variables.$si-font-weight-semibold;
}

// Types, classes
.hljs-type,
.hljs-class .hljs-title {
color: variables.$element-text-primary;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adding more color differentiation for syntax groups.

Many syntax elements share $element-text-primary (numbers, variables, types, attributes, built-ins, template tags, symbols, selectors, markup, formulas, params). While this ensures a clean look, it may reduce code readability for developers who rely on color differentiation to quickly identify syntax elements.

This is a design choice, so verify with UX whether the current minimal color palette meets accessibility and usability requirements.

🤖 Prompt for AI Agents
In projects/element-theme/src/styles/components/_markdown-hljs-theme.scss around
lines 27 to 53, multiple syntax groups are all using
variables.$element-text-primary which reduces visual differentiation; update the
stylesheet so distinct token groups use different color variables (e.g., assign
numbers/variables/types to $element-text-primary, strings/doctags to
$element-text-secondary, and pick an additional semantic variable like
$element-accent or create new token color variables for built-ins/template
tags/symbols/selectors) to increase contrast and readability, update font-weight
only where emphasis is needed, and coordinate the exact variable choices with
UX/accessibility to ensure contrast and consistency.

Comment on lines 34 to 44
syntaxHighlighter: (code: string, language?: string): string | undefined => {
if (language && hljs.getLanguage(language)) {
try {
return hljs.highlight(code, { language }).value;
} catch {
// If highlighting fails, fall back to no highlighting
}
}
return undefined;
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

highlight.js import all languages bundle size default

💡 Result:

Short answer: importing the main highlight.js package (import hljs from 'highlight.js') loads all languages by default (the project lists ~190–200 languages), which substantially increases bundle size. The exact size depends on version and build, but examples show multi-hundred‑KB impacts (hundreds KB minified / ~200–800 KB parsed and ~50–300 KB gzipped in real projects). To avoid that cost, use the core build and register only the languages you need. [1][2][3]

Sources:

  • highlight.js docs: importing main package loads all languages (and recommends using core + per-language imports). [1]
  • highlight.js npm/GitHub/CDN notes about CDN/common builds and language packaging. [2]
  • Real-world reports showing the languages bundle can add hundreds of KB (examples: GitLab issue and blog measurements). [3][4]

🌐 Web query:

highlight.js reduce bundle size import specific languages CDN vs npm

💡 Result:

Short answer: import the core (not the full package) and register only the languages you need when bundling with npm; if using a CDN, either load the prebuilt core + per-language assets from @highlightjs/cdn-assets (or the site’s custom download) or fetch only the individual language .js files so you don't pull all languages. [1][2][3]

How-to (minimal examples)

  • NPM / bundlers (smallest bundle, tree-shakable)

    • Install: npm install highlight.js
    • Import core + specific languages and register:
      import hljs from 'highlight.js/lib/core';
      import javascript from 'highlight.js/lib/languages/javascript';
      import python from 'highlight.js/lib/languages/python';
      hljs.registerLanguage('javascript', javascript);
      hljs.registerLanguage('python', python);
    • Or import 'highlight.js/lib/common' to get the smaller common set instead of everything. [1][2][3]
  • CDN (no build step)

    • Use @highlightjs/cdn-assets (or site CDN) and load core + only the languages you need: <script src=".../es/core.min.js"></script> <script src=".../es/languages/javascript.min.js"></script> <script>hljs.registerLanguage('javascript', window.hljsDefineJavascript);</script>
    • Or use the site’s “custom download” to get a single file with only selected languages. This avoids the full highlight.min.js bundle. [2][3]

Trade-offs

  • NPM + core imports: smallest bundles and best for modern build pipelines (tree-shaking, code-splitting). Recommended for apps.
  • CDN: fastest to get started and good for static sites; must ensure you load only the language files you need (or use a custom-built bundle) to avoid large payloads. [1][2][3]

Sources

  1. highlightjs.org — Usage / import core & languages.
  2. highlight.js GitHub README — CDN assets, ES module examples, importmap.
  3. npm / CDN docs — notes on custom builds and @highlightjs/cdn-assets.

🏁 Script executed:

cat -n src/app/examples/si-chat-messages/si-ai-message.ts | head -50

Repository: siemens/element

Length of output: 2608


Replace full highlight.js import with core + specific languages.

Line 12 imports hljs from 'highlight.js', which includes all ~190–200 languages by default and adds 200–800 KB (parsed) / ~50–300 KB (gzipped) to the bundle. Replace with:

import hljs from 'highlight.js/lib/core';
import javascript from 'highlight.js/lib/languages/javascript';
// Register only the languages this component uses
hljs.registerLanguage('javascript', javascript);
// Add other languages as needed...

Alternatively, use 'highlight.js/lib/common' for a smaller predefined set of common languages if registering individual languages is not feasible.

🤖 Prompt for AI Agents
In src/app/examples/si-chat-messages/si-ai-message.ts around lines 34 to 43, the
file currently imports the full highlight.js bundle which bloats the client;
replace the default full import with the lightweight core import and explicitly
register only the languages used by this component (e.g., javascript) via
hljs.registerLanguage calls, or alternatively import 'highlight.js/lib/common'
if you prefer a small preset of common languages; update imports accordingly and
keep the existing syntaxHighlighter function unchanged except it will now use
the core+registered languages.

@panch1739
Copy link
Member

@Killusions Love iiiiit! I have only two points:

  1. Is there a version somewhere with the key visual?
  2. In the responsive behavior, the summary chips are not stacking, but wrapping individually:
image

When there is no space, the summary chips should stack:

image

Can you check these things? Thank youuu

@Killusions
Copy link
Member Author

@Killusions Love iiiiit! I have only two points:

  1. Is there a version somewhere with the key visual?
  2. In the responsive behavior, the summary chips are not stacking, but wrapping individually:
image When there is no space, the summary chips should stack: image Can you check these things? Thank youuu

The wrapping I'll fix but don't the specs only have the key visual if bigger than a certain screen size?

@panch1739
Copy link
Member

@Killusions Love iiiiit! I have only two points:

  1. Is there a version somewhere with the key visual?
  2. In the responsive behavior, the summary chips are not stacking, but wrapping individually:
image When there is no space, the summary chips should stack: image Can you check these things? Thank youuu

The wrapping I'll fix but don't the specs only have the key visual if bigger than a certain screen size?

@Killusions yes, the key visual should only be visible when there is space, in the responsive version is not visible. I was asking if there was a version with the key visual at all...even in big breakpoints (xl, xxl) i dont see it 🤔

Or am i missing something?

I also see that the tooling is added with this sort of loader...didn't we agreed on wait for this? The design will change quite soon, as the AI team is working on some visualization for this:

image

@Killusions
Copy link
Member Author

@Killusions Love iiiiit! I have only two points:

  1. Is there a version somewhere with the key visual?
  2. In the responsive behavior, the summary chips are not stacking, but wrapping individually:
image When there is no space, the summary chips should stack: image Can you check these things? Thank youuu

The wrapping I'll fix but don't the specs only have the key visual if bigger than a certain screen size?

@Killusions yes, the key visual should only be visible when there is space, in the responsive version is not visible. I was asking if there was a version with the key visual at all...even in big breakpoints (xl, xxl) i dont see it 🤔

Or am i missing something?

I also see that the tooling is added with this sort of loader...didn't we agreed on wait for this? The design will change quite soon, as the AI team is working on some visualization for this:

image

Don't worry it's just rebased on top, I won't merge it before this one.
But the missing key visual is weird because locally it works for me.

@Killusions Killusions force-pushed the feat/add-ai-welcome-screen branch from 6ec8dde to 177e1e8 Compare January 7, 2026 16:17
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: 6

🤖 Fix all issues with AI agents
In @.npmrc:
- Line 3: The .npmrc entry for the @linus scoped registry
("@linus:registry=https://code.siemens.com/api/v4/packages/npm/") points to a
URL that returns 404; update this entry to a valid, reachable registry URL (or
remove it if the scope should use the default registry), and if the registry
requires authentication add the proper auth config (e.g., auth token or
credentials) to .npmrc so npm can resolve @linus packages; verify the corrected
URL by running an npm install for a known @linus package to confirm resolution.

In @docs/patterns/ai/ai-chat.md:
- Line 89: Rewrite the sentence describing the si-ai-chat-container to remove
the comma splice and clarify the fixed-height requirement: state that the
si-ai-chat-container provides a complete AI chat interface with an integrated
welcome screen, requires a fixed height constraint, and if the parent layout
does not provide one the developer must set an explicit pixel height (give a
brief example such as style="height: 600px"); update the sentence in the docs to
this clearer wording and ensure no ambiguous phrasing remains.

In @projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts:
- Around line 186-228: Tests access internal computed signals via (component as
any).inputInterruptible() and inputSending(); make these approachable without
casting by exposing test helpers or public getters. Add public methods or
readonly properties on the component (e.g., getInputInterruptible(),
getInputSending() or public readonly
inputInterruptibleSignal/inputSendingSignal) that return the computed values or
signals, update tests to call those instead of casting, or alternatively
refactor tests to assert observable UI/behavior changes driven by those computed
signals rather than calling internals directly.

In @projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss:
- Around line 42-44: The summary chips are wrapping individually because the
rule on div:first-child uses flex-wrap: wrap; instead of switching the row to a
column at smaller viewports; update the styling for the selector div:first-child
(or its parent container/class used for the chip row) to change flex-direction
from row to column at the responsive breakpoint (via a media query or container
query) so the whole chip row stacks vertically, or alternatively add a
responsive utility class (e.g., flex-column on small screens) to that container
to force column layout rather than horizontal wrapping.

In @src/app/examples/si-chat-messages/si-ai-welcome-screen.ts:
- Around line 21-28: The initial value of the signal selectedCategory does not
match any promptCategories.label (selectedCategory is 'all' while
promptCategories contains 'All prompts'), causing the initial selection to fail;
fix by aligning them — either change the selectedCategory initial value to 'All
prompts' (matching the label) or update the promptCategories entry to use 'all'
(or both) and ensure casing/spacing is consistent with the component logic that
compares the signal to PromptCategory.label.

In @src/app/examples/si-chat-messages/si-chat-container.html:
- Around line 41-50: The category chips container (.prompt-suggestions >
div:first-child) uses flex-wrap and needs a responsive override: add a media
query or container query for small breakpoints (e.g., .si-container-xs,
.si-container-sm) to set flex-direction: column, adjust gap/align-items (e.g.,
align-items: stretch or flex-start) and remove horizontal wrapping so chips
stack vertically; update the stylesheet used by the si-ai-welcome-screen
template (or the parent container CSS) to include this rule so the chip layout
switches to column on small viewports.
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6ec8dde and 177e1e8.

⛔ Files ignored due to path filters (7)
  • package-lock.json is excluded by !**/package-lock.json
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-light-linux.png is excluded by !**/*.png
📒 Files selected for processing (31)
  • .npmrc
  • api-goldens/element-ng/chat-messages/index.api.md
  • api-goldens/element-ng/translate/index.api.md
  • docs/patterns/ai/ai-chat.md
  • package.json
  • playwright/e2e/element-examples/static.spec.ts
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
  • projects/dashboards-demo/src/styles.scss
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • projects/element-theme/src/styles/variables/_semantic-tokens.scss
  • projects/element-theme/src/theme/_theme-element.scss
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.html
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.ts
  • src/app/examples/si-chat-messages/si-chat-container.html
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • src/styles.scss
🧰 Additional context used
🧠 Learnings (41)
📚 Learning: 2025-12-16T16:19:17.950Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1207
File: playwright/snapshots/si-filtered-search.spec.ts-snapshots/si-filtered-search--si-filtered-search-playground--data-entered.yaml:38-38
Timestamp: 2025-12-16T16:19:17.950Z
Learning: Do not review files in the playwright/snapshots directory, as they contain auto-generated test artifacts. Exclude any YAML snapshot files under playwright/snapshots from code reviews in the siemens/element repository. If a YAML file is not an auto-generated snapshot, verify its origin before skipping.

Applied to files:

  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
📚 Learning: 2025-12-22T13:04:35.578Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: src/app/examples/ag-grid/ag-grid-empty-state.ts:20-24
Timestamp: 2025-12-22T13:04:35.578Z
Learning: The SiEmptyStateComponent in siemens/element-ng accepts icon names in kebab-case format (e.g., 'element-technical-operator') that may not be directly exported as constants in the element-icons.ts file. Do not flag these as errors if they render correctly at runtime.

Applied to files:

  • projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • api-goldens/element-ng/chat-messages/index.api.md
📚 Learning: 2025-12-22T13:29:36.922Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: projects/element-ng/ag-grid/parts/color-scheme.part.ts:35-35
Timestamp: 2025-12-22T13:29:36.922Z
Learning: In the Element design system (projects/element-ng/theme and projects/element-theme), only `--element-body-font-family` is exposed as a CSS custom property for typography. Font sizes are NOT exposed as CSS custom properties; they are defined using internal SCSS variables (e.g., `typography.$si-font-size-body`) that compile to fixed values. Using hardcoded pixel values for fontSize in AG Grid theme configuration (e.g., `fontSize: '14px'`) is the correct approach.

Applied to files:

  • projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/dashboards-demo/src/styles.scss
📚 Learning: 2025-12-17T04:34:55.597Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1173
File: src/app/examples/si-charts/interactive/interactive.ts:5-5
Timestamp: 2025-12-17T04:34:55.597Z
Learning: Guideline: In Angular projects using OnPush change detection (zoneless mode), you only need to call ChangeDetectorRef.markForCheck() for asynchronous operations (e.g., setTimeout, setInterval, Promises, Observables) where a change is not automatically detected. Event handlers triggered by Angular template bindings (click, input, etc.) will trigger change detection automatically and do not require explicit markForCheck() calls. Apply this broadly to TS files within Angular components/services that use OnPush; use markForCheck() selectively for async work where change detection wouldn’t run otherwise.

Applied to files:

  • projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts
  • playwright/e2e/element-examples/static.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
📚 Learning: 2025-12-30T13:52:33.581Z
Learnt from: dauriamarco
Repo: siemens/element PR: 1221
File: projects/element-ng/side-panel/si-side-panel.component.ts:136-142
Timestamp: 2025-12-30T13:52:33.581Z
Learning: Maintain the existing negative naming convention (e.g., disableBackdrop) across the siemens/element repository for consistency. Do not refactor to positive names (e.g., showBackdrop, hasBackdrop) unless the project explicitly changes the convention. In reviews, flag changes that alter established naming patterns in related files under projects/element-ng.

Applied to files:

  • projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
📚 Learning: 2025-12-09T14:32:34.036Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:21-47
Timestamp: 2025-12-09T14:32:34.036Z
Learning: In projects/element-ng/chat-messages, nested if blocks are preferred over switch statements for branching on message types in Angular templates.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • src/app/examples/si-chat-messages/si-chat-container.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • api-goldens/element-ng/chat-messages/index.api.md
📚 Learning: 2025-12-09T14:31:33.543Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:14-50
Timestamp: 2025-12-09T14:31:33.543Z
Learning: In projects/element-ng/chat-messages/si-ai-chat-container.component.html, message IDs can change, so tracking by message.id is not appropriate. The component uses `track message` (object identity) which is the correct approach for this use case.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • src/app/examples/si-chat-messages/si-chat-container.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-welcome-screen.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
📚 Learning: 2026-01-02T16:41:57.274Z
Learnt from: kfenner
Repo: siemens/element PR: 1005
File: docs/fundamentals/styles/sizing.md:18-26
Timestamp: 2026-01-02T16:41:57.274Z
Learning: In Element documentation (siemens/element), sizing utility examples in docs may intentionally differ from implementation examples to demonstrate multiple valid approaches - for example, documentation might use traditional CSS properties like `height` and `width` while the implementation example uses logical properties like `block-size` and `inline-size`. These are considered different examples rather than inconsistencies.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
📚 Learning: 2025-12-17T14:01:05.705Z
Learnt from: dauriamarco
Repo: siemens/element PR: 908
File: projects/element-ng/side-panel/si-side-panel.component.ts:70-74
Timestamp: 2025-12-17T14:01:05.705Z
Learning: In the Element side-panel component (projects/element-ng/side-panel/si-side-panel.component.ts), the `xxxlMinimum` breakpoint (1920px) is intentionally hardcoded as a private static constant rather than being part of the configurable `Breakpoints` interface. This design preserves full Bootstrap compatibility (which only defines breakpoints up to xxl/1400px) while allowing Element to handle ultra-wide screens explicitly without affecting the standard breakpoint configuration.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-chat-container.component.scss
📚 Learning: 2025-12-31T07:16:13.451Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: projects/element-ng/ag-grid/parts/radio-style.part.ts:15-61
Timestamp: 2025-12-31T07:16:13.451Z
Learning: In the AG Grid theme package (projects/element-ng/ag-grid), styling should maintain consistency with the base Element design system components rather than adding enhancements or extra CSS. If accessibility improvements like focus-visible indicators are needed, they should be implemented at the Element design system level first.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-theme/src/theme/_theme-element.scss
📚 Learning: 2025-12-15T10:05:59.100Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1193
File: projects/element-ng/search-bar/si-search-bar.component.spec.ts:21-28
Timestamp: 2025-12-15T10:05:59.100Z
Learning: In tests that rely on Jasmine's fake clock to control time-based RxJS operators (e.g., debounceTime), use jasmine.clock().install() together with jasmine.clock().mockDate() to enable precise timing control. Without mockDate, scheduler-based operators may not respond to the fake clock. Apply this guidance to spec files (e.g., any file named *.spec.ts or *.spec.js) that test time-sensitive behavior, ensuring you install and mockDate before advancing time in tests.

Applied to files:

  • playwright/e2e/element-examples/static.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2026-01-07T12:19:38.754Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1240
File: projects/dashboards-ng/package.json:21-22
Timestamp: 2026-01-07T12:19:38.754Z
Learning: In the siemens/element repository, Angular peer dependencies are intentionally pinned to exact major versions (e.g., "angular/core": "21") rather than ranges in package.json files for published packages like siemens/dashboards-ng, siemens/element-ng, and siemens/element-translate-ng. This is a deliberate strategy to ensure strict version alignment.

Applied to files:

  • .npmrc
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
📚 Learning: 2025-12-09T14:19:26.605Z
Learnt from: Killusions
Repo: siemens/element PR: 967
File: package.json:153-153
Timestamp: 2025-12-09T14:19:26.605Z
Learning: In library projects (e.g., element-ng), do not list implementation dependencies for optional features in the main dependencies. Move those into devDependencies (used for demos/examples) and have consuming apps install them separately if they enable the feature. This avoids bloating library consumers with unnecessary packages and clarifies that optional features are not guaranteed to work without extra installs. If a feature is truly optional, consider documenting it and, if appropriate, using optionalDependencies to reflect optional runtime usage.

Applied to files:

  • package.json
📚 Learning: 2025-12-11T10:09:01.564Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1151
File: projects/element-ng/auto-collapsable-list/si-auto-collapsable-list.directive.spec.ts:83-104
Timestamp: 2025-12-11T10:09:01.564Z
Learning: In the auto-collapsable-list directive tests (projects/element-ng/auto-collapsable-list/si-auto-collapsable-list.directive.spec.ts), jasmine.clock() successfully controls the directive's setTimeout-based layout logic in zoneless mode. Mock timers work fine here, unlike in select component overflow tests where real setTimeout waits are required.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-15T07:17:06.981Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts:37-49
Timestamp: 2025-12-15T07:17:06.981Z
Learning: In widget-instance-editor-dialog component tests (projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing component initialization. This is likely due to the component's lifecycle behavior or modal initialization timing that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-15T07:16:53.762Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:92-105
Timestamp: 2025-12-15T07:16:53.762Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits must be used instead of fixture.whenStable() to avoid injector destroyed errors during mount/unmount operations in zoneless mode. The GridStack timing-dependent operations require actual async delays.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-08T11:24:45.272Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/options/si-select-lazy-options.directive.spec.ts:67-85
Timestamp: 2025-12-08T11:24:45.272Z
Learning: In select lazy options tests (projects/element-ng/select/options/si-select-lazy-options.directive.spec.ts), jasmine.clock() cannot control RxJS debounceTime in zoneless mode. Real setTimeout waits must be used instead for tests involving search debouncing.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-01T04:01:27.365Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1099
File: projects/element-ng/accordion/si-accordion.component.spec.ts:39-43
Timestamp: 2025-12-01T04:01:27.365Z
Learning: With Angular 20 and esbuild, synchronous `TestBed.configureTestingModule(...).compileComponents()` calls work correctly even when components use external templates (templateUrl), because esbuild pre-compiles templates at build time. The async/await pattern is not required in this scenario.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
📚 Learning: 2025-12-15T07:16:32.082Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:69-80
Timestamp: 2025-12-15T07:16:32.082Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing grid item rendering and initialization. This is likely due to gridstack library's initialization timing or lifecycle behavior that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-05T08:00:38.407Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1151
File: projects/element-ng/typeahead/si-typeahead.directive.spec.ts:114-121
Timestamp: 2025-12-05T08:00:38.407Z
Learning: In the typeahead test suite (projects/element-ng/typeahead/si-typeahead.directive.spec.ts), jasmine.clock() must be installed in beforeAll and uninstalled in afterAll (not beforeEach/afterEach) because using per-test clock installation causes schedulerFunction-related issues in these specific tests.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
📚 Learning: 2025-12-01T14:12:11.111Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1104
File: projects/element-ng/datepicker/components/si-day-selection.component.spec.ts:198-202
Timestamp: 2025-12-01T14:12:11.111Z
Learning: In zoneless Angular tests (using provideZonelessChangeDetection), prefer `await fixture.whenStable()` over `fixture.detectChanges()` after dispatching events or triggering async operations, as `whenStable()` waits for all asynchronous operations to complete and better mimics the production environment.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-04T05:50:38.735Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1135
File: projects/element-ng/tree-view/si-tree-view.component.spec.ts:1244-1245
Timestamp: 2025-12-04T05:50:38.735Z
Learning: In zoneless Angular tests with OnPush components, calling `await runOnPushChangeDetection(fixture)` followed by `await fixture.whenStable()` is NOT redundant. The `runOnPushChangeDetection` helper forces change detection to run for OnPush components, while `whenStable()` waits for all async operations to complete. Both are necessary and serve different purposes.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-04T05:50:17.637Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1135
File: projects/element-ng/tree-view/si-tree-view.component.spec.ts:953-964
Timestamp: 2025-12-04T05:50:17.637Z
Learning: In the siemens/element repository, when making tree-view tests zoneless-ready, jasmine.clock() should be used to mimic setTimeouts even in zoneless mode, as the component implementation relies on setTimeout calls that need to be controlled in tests.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-12-08T11:25:20.861Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/si-select.component.spec.ts:204-205
Timestamp: 2025-12-08T11:25:20.861Z
Learning: In zoneless Angular tests (using provideZonelessChangeDetection), calling fixture.changeDetectorRef.markForCheck() before fixture.detectChanges() is required even for components using the default change detection strategy (not OnPush). This differs from zone.js-based testing where markForCheck is primarily needed only for OnPush components.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-08T11:25:51.584Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/si-select.component.spec.ts:511-516
Timestamp: 2025-12-08T11:25:51.584Z
Learning: In the select component overflow tests (projects/element-ng/select/si-select.component.spec.ts), jasmine.clock() cannot be used to control the timing for overflow item detection. Real setTimeout waits must be used instead, likely due to ResizeObserver or debounced layout calculations that jasmine.clock() cannot control in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
📚 Learning: 2025-11-18T12:37:30.510Z
Learnt from: Killusions
Repo: siemens/element PR: 1040
File: projects/element-ng/chat-messages/si-chat-input.component.ts:338-349
Timestamp: 2025-11-18T12:37:30.510Z
Learning: In projects/element-ng/chat-messages/si-chat-input.component.ts, the interrupt behavior is intentionally different for button clicks vs Enter key: the button can emit interrupt even without content, but pressing Enter requires content or attachments (canSend() must be true) to emit interrupt.

Applied to files:

  • src/app/examples/si-chat-messages/si-chat-container.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
📚 Learning: 2025-12-11T14:44:11.278Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1185
File: projects/element-ng/navbar/si-navbar-item/si-navbar-item.component.html:11-11
Timestamp: 2025-12-11T14:44:11.278Z
Learning: The si-icon component in siemens/element-ng/icon automatically applies aria-hidden="true" to its content. Do not suggest adding aria-hidden="true" to si-icon elements, as accessibility is already handled internally by the component.

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-chat-container.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
📚 Learning: 2026-01-02T06:41:22.404Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: playwright/e2e/element-examples/static.spec.ts:119-121
Timestamp: 2026-01-02T06:41:22.404Z
Learning: In the Element design system (siemens/element repository), disabling the `aria-required-children` accessibility rule for `SiEmptyStateComponent` is an accepted pattern. This component is used in AG Grid overlays (AgNoRowsOverlayComponent) and other places in Element, and the rule is consistently disabled in tests where this component appears (e.g., si-pills-input, datatable-row-group, ag-grid-empty-state).

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-chat-container.html
📚 Learning: 2025-12-04T11:54:31.132Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1133
File: projects/element-ng/tour/si-tour.service.spec.ts:21-26
Timestamp: 2025-12-04T11:54:31.132Z
Learning: In the siemens/element repository, all components are standalone by default and do not require the explicit `standalone: true` flag. Components should be added to the `imports` array in TestBed configuration, not the `declarations` array.

Applied to files:

  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
📚 Learning: 2025-12-22T13:26:40.908Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1237
File: tools/api-goldens/test_api_report.ts:19-23
Timestamp: 2025-12-22T13:26:40.908Z
Learning: In the siemens/element repository, the team intentionally uses internal APIs from `microsoft/api-extractor` (such as `AstDeclaration`, `AstModule`, `ExportAnalyzer`, `ApiItemMetadata`, and `Collector` from `/lib/analyzer` and `/lib/collector` paths) in `tools/api-goldens/test_api_report.ts` to customize API extraction behavior (e.g., marking protected members as internal). This is an accepted practice because the required functionality is not available through the public API, and the version is pinned to mitigate risks.

Applied to files:

  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
📚 Learning: 2025-12-22T13:21:07.745Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: projects/element-ng/ag-grid/provider.ts:74-81
Timestamp: 2025-12-22T13:21:07.745Z
Learning: In the siemens/element repository, configuration providers use custom string tokens with useValue for consistency (e.g., provideSiDatatableConfig uses { provide: 'configuration', useValue: {...} }). The AG Grid provider follows this same pattern with { provide: 'ag-grid-options', useValue: provideGlobalGridOptions({...}) }.

Applied to files:

  • projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts
📚 Learning: 2025-12-09T14:32:26.166Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:21-47
Timestamp: 2025-12-09T14:32:26.166Z
Learning: In Angular templates, prefer using nested *ngIf blocks over *ngSwitch for branching on message types within the chat-messages components. Use *ngIf with else branches to handle distinct cases and avoid complex switch logic in HTML templates. This guideline applies to all HTML templates under projects/element-ng/chat-messages.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
📚 Learning: 2025-12-01T09:34:50.028Z
Learnt from: Killusions
Repo: siemens/element PR: 1047
File: docs/fundamentals/ux-text-style-guide/basics.md:45-50
Timestamp: 2025-12-01T09:34:50.028Z
Learning: In docs/fundamentals/ux-text-style-guide/basics.md, the Don'ts section intentionally contains duplicate "Hey there!" entries to show that the same informal greeting is an inappropriate alternative for multiple formal welcome messages (both "Welcome to Building X" and "Welcome Werner von Siemens").

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-welcome-screen.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
📚 Learning: 2025-12-09T14:33:54.441Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: src/app/examples/si-chat-messages/si-ai-message.ts:24-43
Timestamp: 2025-12-09T14:33:54.441Z
Learning: In src/app/examples/ (example/demo code) directories, allow and expect code duplication. Treat duplication as acceptable for demonstration code that aims to illustrate usage rather than enforce DRY. Do not enforce refactoring to remove duplication in example files; focus on readability and clarity of examples. This applies to all TypeScript files under src/app/examples (including nested subdirectories like si-chat-messages).

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-welcome-screen.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
📚 Learning: 2026-01-07T08:57:45.608Z
Learnt from: dauriamarco
Repo: siemens/element PR: 1226
File: src/app/examples/si-navbar-vertical/si-navbar-vertical.ts:112-115
Timestamp: 2026-01-07T08:57:45.608Z
Learning: Do not strictly enforce badge color consistency in example files under src/app/examples. Treat badge color checks as non-blocking for TypeScript files in this directory; reviewers may still note inconsistencies, but they should not require changes for these example files. Apply this guidance broadly to all files within src/app/examples.

Applied to files:

  • src/app/examples/si-chat-messages/si-ai-welcome-screen.ts
  • src/app/examples/si-chat-messages/si-ai-chat-container.ts
  • src/app/examples/si-chat-messages/si-chat-container.ts
📚 Learning: 2025-12-04T10:35:45.465Z
Learnt from: Killusions
Repo: siemens/element PR: 1147
File: docs/fundamentals/ux-text-style-guide/dialogs-and-buttons.md:81-84
Timestamp: 2025-12-04T10:35:45.465Z
Learning: In docs/fundamentals/ux-text-style-guide/dialogs-and-buttons.md, the Clear content section's Do's intentionally contains four identical "Delete Wittelsbacherplatz München?" entries to show that the same simple, direct question is the appropriate alternative for multiple different incorrect phrasings (overly wordy questions, generic terms, unnecessary disclaimers, and redundant words).

Applied to files:

  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
📚 Learning: 2026-01-02T16:41:48.359Z
Learnt from: kfenner
Repo: siemens/element PR: 1005
File: docs/fundamentals/styles/sizing.md:18-26
Timestamp: 2026-01-02T16:41:48.359Z
Learning: In Element docs, sizing examples may differ between documentation and implementation to illustrate multiple valid approaches. Do not flag such differences as inconsistencies; treat them as separate illustrative examples (e.g., using height/width in docs vs block-size/inline-size in implementation). Apply this understanding across Markdown documentation files to avoid false-positive review flags.

Applied to files:

  • docs/patterns/ai/ai-chat.md
📚 Learning: 2025-12-23T09:24:35.163Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/translate/index.api.md:12-84
Timestamp: 2025-12-23T09:24:35.163Z
Learning: In the siemens/element repository, do not review files under the api-goldens/ directory (e.g., api-goldens/**/index.api.md) since they are auto-generated by API Extractor. Exclude these from review checks and focus on source files that are not auto-generated.

Applied to files:

  • api-goldens/element-ng/translate/index.api.md
  • api-goldens/element-ng/chat-messages/index.api.md
📚 Learning: 2025-12-23T09:24:57.843Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/index.api.md:324-325
Timestamp: 2025-12-23T09:24:57.843Z
Learning: Do not review files in the api-goldens directory, as they are auto-generated API reports produced by API Extractor.

Applied to files:

  • api-goldens/element-ng/translate/index.api.md
  • api-goldens/element-ng/chat-messages/index.api.md
📚 Learning: 2025-12-23T09:24:40.395Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/module-federation/index.api.md:7-11
Timestamp: 2025-12-23T09:24:40.395Z
Learning: In the siemens/element repository, do not review any files under the api-goldens directory, as they are auto-generated API reports produced by API Extractor. These MD files should be excluded from review unless explicitly overridden.

Applied to files:

  • api-goldens/element-ng/translate/index.api.md
  • api-goldens/element-ng/chat-messages/index.api.md
📚 Learning: 2025-12-09T14:19:34.846Z
Learnt from: Killusions
Repo: siemens/element PR: 967
File: package.json:153-153
Timestamp: 2025-12-09T14:19:34.846Z
Learning: In library projects like element-ng, optional features that are provided through callback/function parameters (e.g., syntaxHighlighter in markdown renderer) should not have their implementation dependencies (e.g., highlight.js) listed in the library's dependencies. These should remain in devDependencies for demo/example purposes, and consuming applications should install them directly if they choose to use those features.

Applied to files:

  • src/app/examples/si-chat-messages/si-chat-container.ts
🧬 Code graph analysis (5)
playwright/e2e/element-examples/static.spec.ts (1)
playwright/support/test-helpers.ts (1)
  • test (286-296)
src/app/examples/si-chat-messages/si-ai-chat-container.ts (4)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (1)
  • PromptSuggestion (15-17)
projects/element-ng/chat-messages/si-chat-input.component.ts (1)
  • ChatInputAttachment (47-54)
projects/element-ng/chat-messages/chat-message.model.ts (4)
  • ChatMessage (157-157)
  • UserChatMessage (77-86)
  • AiChatMessage (95-102)
  • MessageAction (18-31)
projects/element-ng/file-uploader/si-file-upload.directive.ts (1)
  • FileUploadError (18-21)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (1)
src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (1)
  • Component (13-42)
src/app/examples/si-chat-messages/si-chat-container.ts (4)
projects/element-translate-ng/translate/si-translate.inject.ts (1)
  • injectSiTranslateService (11-20)
projects/element-ng/markdown-renderer/markdown-renderer.ts (1)
  • getMarkdownRenderer (69-402)
projects/element-ng/chat-messages/chat-message.model.ts (2)
  • ChatMessage (157-157)
  • MessageAction (18-31)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (2)
  • PromptCategory (11-13)
  • PromptSuggestion (15-17)
projects/element-ng/chat-messages/si-ai-chat-container.component.ts (4)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (1)
  • PromptSuggestion (15-17)
projects/element-ng/chat-messages/si-chat-input.component.ts (1)
  • ChatInputAttachment (47-54)
projects/element-ng/chat-messages/chat-message.model.ts (4)
  • ChatMessage (157-157)
  • MessageAction (18-31)
  • AiChatMessage (95-102)
  • TemplateChatMessage (135-143)
projects/element-ng/markdown-renderer/markdown-renderer.ts (1)
  • MarkdownRendererOptions (20-54)
🔇 Additional comments (33)
projects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.ts (1)

28-28: LGTM! Brand namespace migration is consistent.

The font and theme import paths have been correctly updated from @simpl/brand to @linus/brand. This aligns with the broader namespace migration across the repository, and the corresponding test expectations in index.spec.ts have been updated to match.

Also applies to: 46-47

package.json (3)

56-56: LGTM! Script updated for brand namespace migration.

The prepare-brand script has been correctly updated to use @linus/brand for favicon asset copying, consistent with the namespace migration.


184-184: LGTM! Brand dependency migration is consistent.

The optionalDependencies entry has been correctly updated from @simpl/brand to @linus/brand@2.3.0, consistent with the namespace migration across the repository.


142-142: Dependencies are correctly placed and versions are secure.

The new devDependencies (@types/katex@0.16.7, highlight.js@^11.11.1, katex@0.16.27) are appropriately located in devDependencies for optional markdown rendering features. All versions are free of known security vulnerabilities:

  • katex@0.16.27: All prior CVEs (CVE-2024-28244, CVE-2024-28245, CVE-2024-28246, CVE-2025-23207) are patched in this version.
  • highlight.js@^11.11.1: Latest stable release in the actively maintained 11.x series; older vulnerabilities affecting pre-10.4.x have been resolved.
  • @types/katex@0.16.7: No vulnerabilities in the type definitions.
src/styles.scss (1)

17-17: LGTM! SCSS imports updated for brand namespace migration.

The font and theme import paths have been correctly updated from @simpl/brand to @linus/brand, consistent with the repository-wide namespace migration.

Also applies to: 19-20

projects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.ts (1)

97-98: LGTM! Test expectations updated for brand namespace migration.

The test expectations have been correctly updated to reflect the new @linus/brand namespace in both test scenarios. This ensures the SCSS migration schematic produces the correct output with the updated brand imports.

Also applies to: 102-102, 113-113, 128-129

projects/dashboards-demo/src/styles.scss (1)

3-3: The @linus/brand package migration is properly configured.

The @linus/brand package is already declared in the root package.json with version 2.3.0, and the .npmrc is correctly configured with the @linus registry pointing to the Siemens NPM registry. The migration from @simpl/brand to @linus/brand is complete with no remaining unmigrated references. The internal paths in the imports (assets/fonts, dist/element-theme-siemens-brand-light, dist/element-theme-siemens-brand-dark) appear consistent with the package structure.

projects/element-ng/translate/si-translatable-keys.interface.ts (1)

6-8: LGTM!

The new translatable keys follow the existing pattern and align with the new AI chat components (SI_AI_CHAT_CONTAINER, SI_MARKDOWN_RENDERER, SI_TOOL_MESSAGE). All keys are optional strings, maintaining backward compatibility.

Also applies to: 171-172, 222-223

playwright/e2e/element-examples/static.spec.ts (2)

119-121: LGTM!

The new test cases for si-ai-chat-container, si-tool-message, and si-ai-welcome-screen follow the existing test pattern and provide coverage for the new components.


112-112: No action required. The color-contrast and link-in-text-block rule suppressions are appropriate for this component. SiMarkdownRendererComponent is a content renderer that transforms user-provided markdown input into HTML. The link-in-text-block suppression reflects the intended behavior of rendered markdown links, and the color-contrast suppression acknowledges that arbitrary user content cannot guarantee WCAG AA contrast requirements. These suppressions are consistent with Element's established pattern for content and presentation components.

Likely an incorrect or invalid review comment.

src/app/examples/si-chat-messages/si-chat-container.html (2)

2-2: LGTM!

The template reference variable #chatContainer enables programmatic access to the chat container, which is useful for controlling scroll behavior or other container-level operations.


68-68: LGTM!

The placeholder text update to "Enter a command, question or topic…" is more descriptive and uses a proper ellipsis character.

docs/patterns/ai/ai-chat.md (2)

112-124: LGTM!

The prompt suggestions documentation clearly explains the two approaches (simple array vs. categorized record) with concrete TypeScript examples. This effectively guides developers on how to structure their prompt data.


126-143: LGTM!

The base chat container documentation provides a clear explanation of the slot architecture and available slots, helping developers understand how to build custom chat interfaces.

projects/element-theme/src/styles/variables/_semantic-tokens.scss (1)

189-190: The semantic token is correctly defined and properly used; verify responsive behavior claim.

The token $element-ai-key-visual is correctly defined in _semantic-tokens.scss:190 with appropriate theme-specific values in _theme-element.scss (black SVG in light theme, white SVG in dark theme). The component si-ai-welcome-screen.component.scss properly consumes the token via background-image: variables.$element-ai-key-visual;.

However, the responsive behavior contradicts your observation: the key visual is hidden only at small breakpoints (xs, sm), not at large breakpoints (xl, xxl). The component explicitly hides the visual at container-xs and container-sm via the :host selector (lines 31-32). If the visual is not appearing at xl/xxl, the issue may be elsewhere (e.g., parent layout constraints, z-index, or visibility). Verify the actual rendering context at large breakpoints.

Likely an incorrect or invalid review comment.

src/app/examples/si-chat-messages/si-ai-welcome-screen.html (1)

1-11: LGTM! Template bindings are correct.

The component bindings and template structure are well-formed. The two-way binding for selectedCategory, input bindings for categories and promptSuggestions, and event binding for promptSelected align with the component's API.

The projected content (greeting text) follows the expected pattern for content projection in the welcome screen component.

Note: The hardcoded English text in lines 8-9 has already been flagged in a previous review comment for i18n consideration.

projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts (1)

1-90: LGTM! Test coverage is comprehensive.

The test suite provides good coverage of the component's functionality:

  • Component creation
  • Category display and selection
  • Prompt suggestion display and selection
  • Edge cases (empty categories/suggestions)

The tests correctly use fixture.componentRef.setInput() for setting inputs and spy on event emitters to verify outputs. The zoneless change detection setup is appropriate.

Note: Two previous review comments have already identified optional refactoring opportunities:

  1. Removing the async/await pattern in the beforeEach (lines 14-18)
  2. Simplifying the type union in one of the tests
src/app/examples/si-chat-messages/si-ai-chat-container.html (2)

1-31: LGTM! Container and input setup is well-structured.

The component composition is correct:

  • si-ai-chat-container with appropriate bindings for status, messages, loading states, and configurations
  • si-chat-input properly configured with placeholder, disclaimer, file handling, and event bindings
  • Event handlers for send, interrupt, and fileError are properly wired

The fixed-height layout wrapper and full-width classes ensure proper sizing.

Note: Hardcoded user-facing strings in lines 4, 16-17 have already been flagged for i18n consideration in a previous review comment.


33-47: Critical: Empty close button requires content.

The modal template header contains a close button (lines 36-42) with no content between its tags. While the element-cancel class may apply styling, the button should contain an explicit icon element for proper rendering and visibility.

This issue has been flagged in a previous review comment.

Likely an incorrect or invalid review comment.

projects/element-theme/src/theme/_theme-element.scss (1)

220-222: LGTM! Theme-aware key visual properly implemented.

The element-ai-key-visual token is correctly added to both light and dark theme maps with appropriate fills (black for light theme, white for dark theme). The inline SVG approach is standard for theme files and ensures the visual is always available without external dependencies.

Also applies to: 371-373

projects/element-ng/chat-messages/index.ts (1)

5-17: LGTM! Public API exports correctly updated.

The barrel file exports are properly updated to include the new AI chat components and consolidated model exports. The changes align with the PR objectives of adding the ai-welcome-screen component and related functionality.

projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss (2)

50-52: Refactor away from the deprecated ::ng-deep selector.

The deprecated ::ng-deep selector should be replaced with a more maintainable approach such as using CSS custom properties, exposing an input for style customization, or applying a class directly to the button elements in the template.

Likely an incorrect or invalid review comment.


15-27: Verify the key visual visibility with proper container context.

The component correctly uses SiResponsiveContainerDirective via hostDirectives, which automatically applies the si-container-* classes. The variables.$element-ai-key-visual is properly defined as an SVG in the theme files. The ::before pseudo-element should only be hidden on xs and sm breakpoints and should display at larger sizes (md, lg, xl, xxl).

However, the absolutely-positioned ::before extends 104px to the left (inset-inline-start: -104px). Verify that:

  • The component's parent container doesn't have overflow: hidden or other overflow constraints that would clip the element
  • The component has sufficient space to the left at the target breakpoints (the viewport or parent needs to accommodate the 104px offset)
  • The ResizeObserver is detecting container size changes correctly and applying the classes as expected
projects/element-ng/chat-messages/si-ai-welcome-screen.component.html (2)

25-25: Replace hardcoded text-white with a theme-aware text color.

The hardcoded text-white class creates poor contrast in light themes where the action card background uses a light experimental blue color. Replace with text-primary or remove the class to inherit the card's default text color for proper theme-aware rendering.

Likely an incorrect or invalid review comment.


11-17: Consider tracking by a stable identifier.

Using track $index can cause unnecessary re-renders when the categories array is reordered. Consider tracking by a stable property such as category.label (assuming labels are unique) for better performance.

⛔ Skipped due to learnings
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:14-50
Timestamp: 2025-12-09T14:31:33.543Z
Learning: In projects/element-ng/chat-messages/si-ai-chat-container.component.html, message IDs can change, so tracking by message.id is not appropriate. The component uses `track message` (object identity) which is the correct approach for this use case.
src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (1)

30-37: promptSuggestions signal doesn't leverage category filtering.

The component has promptCategories defined but promptSuggestions is a flat array. To demonstrate the category filtering feature of SiAiWelcomeScreenComponent, consider using the Record<string, PromptSuggestion[]> format.

This is optional since the example may intentionally demonstrate the simple array format.

Likely an incorrect or invalid review comment.

projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (1)

11-13: Consider adding an id field to PromptCategory for better separation of concerns.

The PromptCategory interface only has a label field, which is used both for display and as the selection identifier. This creates confusion (as seen in example code where selectedCategory is initialized to 'all' but categories use 'All prompts'). Consider adding an optional id field to separate the identifier from the display label.

⛔ Skipped due to learnings
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: src/app/examples/ag-grid/ag-grid-empty-state.ts:20-24
Timestamp: 2025-12-22T13:04:35.578Z
Learning: The SiEmptyStateComponent in siemens/element-ng accepts icon names in kebab-case format (e.g., 'element-technical-operator') that may not be directly exported as constants in the element-icons.ts file. Do not flag these as errors if they render correctly at runtime.
projects/element-ng/chat-messages/si-ai-chat-container.component.html (1)

10-13: Consider theme-aware text color for welcome messages.

The hardcoded text-white class on the greeting and welcome message may create poor contrast in light themes. Consider using a theme-aware alternative or ensuring the parent container always provides sufficient contrast.

⛔ Skipped due to learnings
Learnt from: Killusions
Repo: siemens/element PR: 1047
File: docs/fundamentals/ux-text-style-guide/basics.md:45-50
Timestamp: 2025-12-01T09:34:50.028Z
Learning: In docs/fundamentals/ux-text-style-guide/basics.md, the Don'ts section intentionally contains duplicate "Hey there!" entries to show that the same informal greeting is an inappropriate alternative for multiple formal welcome messages (both "Welcome to Building X" and "Welcome Werner von Siemens").
Learnt from: dauriamarco
Repo: siemens/element PR: 1226
File: src/app/examples/si-navbar-vertical/si-navbar-vertical.ts:112-115
Timestamp: 2026-01-07T08:57:45.608Z
Learning: Badge color consistency in example files (src/app/examples/) is not a priority and should not be strictly enforced during reviews.
src/app/examples/si-chat-messages/si-ai-chat-container.ts (1)

1-298: LGTM! Example component demonstrates proper usage patterns.

The example component effectively demonstrates the AI chat container API with syntax highlighting, LaTeX rendering, message handling, and UI state management. The code is clear and instructive for users learning the component.

Note: Previous review comments have already addressed typing and lifecycle cleanup considerations for the simulation logic.

src/app/examples/si-chat-messages/si-chat-container.ts (2)

68-103: LGTM! Markdown renderer properly configured with optional features.

The markdown renderer setup demonstrates good practices:

  • Syntax highlighting with hljs includes proper error handling and fallback
  • LaTeX rendering with KaTeX has error handling
  • Translation service correctly bound for button labels
  • Clear comments guide users on dependency requirements

287-289: Appropriate use of setTimeout for post-render scrolling.

The setTimeout(..., 0) pattern correctly defers the scroll operation until after Angular's change detection and DOM updates complete, ensuring the chat container has rendered the new message before scrolling.

projects/element-ng/chat-messages/si-ai-chat-container.component.ts (2)

1-592: LGTM! Well-architected component with comprehensive API surface.

This component demonstrates excellent Angular practices:

  • Proper use of signals and computed for reactive state management
  • Clean separation of concerns with helper methods
  • Comprehensive JSDoc documentation for public API
  • Appropriate use of WeakMap for message-based caching
  • Correct effect usage for child component coordination
  • Well-designed loading state injection logic

Note: A previous review comment has already addressed the cache invalidation mechanism for messageVersions.


579-591: Clean prompt selection integration.

The onPromptSelected handler properly:

  • Accesses the chat input component via signal
  • Sets the input value from the suggestion
  • Programmatically triggers the send event
  • Clears the input after sending

This provides a seamless UX for selecting prompt suggestions from the welcome screen.

.npmrc Outdated
@@ -1,2 +1,3 @@
@simpl:registry=https://code.siemens.com/api/v4/packages/npm/
@simpl-labs:registry=https://code.siemens.com/api/v4/packages/npm/
@linus:registry=https://code.siemens.com/api/v4/packages/npm/
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the .npmrc file to understand the full context
cat -n .npmrc 2>/dev/null || echo "File not found or error reading"

Repository: siemens/element

Length of output: 174


🏁 Script executed:

# Check if the registry is accessible
echo "Checking registry accessibility..."
curl -s -I https://code.siemens.com/api/v4/packages/npm/ 2>&1 | head -n 5

Repository: siemens/element

Length of output: 229


🏁 Script executed:

# Check package availability (with timeout to avoid hanging)
echo "Checking @linus/brand availability..."
timeout 5 npm view @linus/brand --registry=https://code.siemens.com/api/v4/packages/npm/ 2>&1 | head -n 15 || echo "Request timed out or package not found"

Repository: siemens/element

Length of output: 142


Registry URL returns 404 – fix before merging.

The configured registry at https://code.siemens.com/api/v4/packages/npm/ is not accessible and returns an HTTP 404 error. This will prevent npm from resolving @linus scoped packages.

Verify the registry URL is correct and that the registry exists. If authentication is required, ensure it's configured properly in .npmrc.

🤖 Prompt for AI Agents
In @.npmrc at line 3, The .npmrc entry for the @linus scoped registry
("@linus:registry=https://code.siemens.com/api/v4/packages/npm/") points to a
URL that returns 404; update this entry to a valid, reachable registry URL (or
remove it if the scope should use the default registry), and if the registry
requires authentication add the proper auth config (e.g., auth token or
credentials) to .npmrc so npm can resolve @linus packages; verify the corrected
URL by running an npm install for a known @linus package to confirm resolution.

Comment on lines 186 to 228
it('should compute inputInterruptible correctly', () => {
fixture.componentRef.setInput('loading', true);
fixture.componentRef.setInput('disableInterrupt', false);
fixture.componentRef.setInput('sending', false);
fixture.componentRef.setInput('interrupting', false);
fixture.detectChanges();

expect((component as any).inputInterruptible()).toBe(true);

fixture.componentRef.setInput('interrupting', true);
fixture.componentRef.setInput('loading', false);
fixture.componentRef.setInput('disableInterrupt', true);
fixture.componentRef.setInput('sending', true);
fixture.detectChanges();

expect((component as any).inputInterruptible()).toBe(true);

fixture.componentRef.setInput('loading', false);
fixture.componentRef.setInput('interrupting', false);
fixture.detectChanges();

expect((component as any).inputInterruptible()).toBe(false);
});

it('should compute inputSending correctly', () => {
fixture.componentRef.setInput('sending', true);
fixture.componentRef.setInput('interrupting', false);
fixture.detectChanges();

expect((component as any).inputSending()).toBe(true);

fixture.componentRef.setInput('sending', false);
fixture.componentRef.setInput('interrupting', true);
fixture.detectChanges();

expect((component as any).inputSending()).toBe(true);

fixture.componentRef.setInput('sending', false);
fixture.componentRef.setInput('interrupting', false);
fixture.detectChanges();

expect((component as any).inputSending()).toBe(false);
});
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider exposing test helpers for computed signal testing.

Multiple tests access internal computed signals via (component as any) casts. While this works, consider:

  1. Exposing these as public for testing if they represent important component behavior
  2. Or testing the observable effects rather than internal state

This is a minor suggestion and the current approach is functional.

🤖 Prompt for AI Agents
In @projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
around lines 186 - 228, Tests access internal computed signals via (component as
any).inputInterruptible() and inputSending(); make these approachable without
casting by exposing test helpers or public getters. Add public methods or
readonly properties on the component (e.g., getInputInterruptible(),
getInputSending() or public readonly
inputInterruptibleSignal/inputSendingSignal) that return the computed values or
signals, update tests to call those instead of casting, or alternatively
refactor tests to assert observable UI/behavior changes driven by those computed
signals rather than calling internals directly.

Comment on lines +42 to +44
> div:first-child {
flex-wrap: wrap;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix the chip wrapping behavior to match design expectations.

PR comments report that summary chips are wrapping individually instead of stacking vertically when space is constrained. The current flex-wrap: wrap allows horizontal wrapping, but the expected behavior appears to be that the entire chip row should switch to a vertical stack layout at smaller sizes.

🎨 Proposed fix for responsive chip layout

Consider using a media query or container query to switch the flex-direction from row to column at the appropriate breakpoint:

 .prompt-suggestions {
   max-inline-size: 720px;
 
   > div:first-child {
-    flex-wrap: wrap;
+    @media (max-width: 768px) {
+      flex-direction: column;
+    }
   }
 }

Alternatively, if you want to maintain the wrapping behavior but control it better, consider adjusting the flex layout of the parent container in the HTML template to use flex-column on smaller breakpoints.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In @projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss around
lines 42 - 44, The summary chips are wrapping individually because the rule on
div:first-child uses flex-wrap: wrap; instead of switching the row to a column
at smaller viewports; update the styling for the selector div:first-child (or
its parent container/class used for the chip row) to change flex-direction from
row to column at the responsive breakpoint (via a media query or container
query) so the whole chip row stacks vertically, or alternatively add a
responsive utility class (e.g., flex-column on small screens) to that container
to force column layout rather than horizontal wrapping.

Comment on lines +41 to +50
} @empty {
<si-ai-welcome-screen
[categories]="promptCategories"
[promptSuggestions]="filteredPromptSuggestions()"
[(selectedCategory)]="selectedCategory"
(promptSelected)="onPromptSelected($event)"
>
<p class="h1 mb-0 text-white"> <strong>Hello</strong>, </p>
<p class="h1 mb-0 text-white">how can I help you today?</p>
</si-ai-welcome-screen>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the responsive styling for chips in ai-welcome-screen
echo "=== Checking ai-welcome-screen component styles ==="
rg -n -C 10 'si-summary-chip|flex-wrap|flex-direction' projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss

echo ""
echo "=== Checking if there are media queries for responsive behavior ==="
rg -n '@media|@container' projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss

echo ""
echo "=== List the si-ai-welcome-screen component files ==="
fd 'si-ai-welcome-screen' projects/

Repository: siemens/element

Length of output: 880


🏁 Script executed:

#!/bin/bash
# Check the component template
echo "=== Checking si-ai-welcome-screen component template ==="
cat projects/element-ng/chat-messages/si-ai-welcome-screen.component.html

echo ""
echo "=== Check the full scss file ==="
cat projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss

Repository: siemens/element

Length of output: 2257


Fix responsive chip stacking for small viewports.

The current implementation uses flex-wrap: wrap on the category chips container without responsive rules. At small viewport sizes, chips need to stack vertically using flex-direction: column rather than wrapping horizontally within a single row. Add a media query or container query to the .prompt-suggestions > div:first-child selector to apply flex-direction: column and adjust related properties at small breakpoints (e.g., .si-container-xs, .si-container-sm).

🤖 Prompt for AI Agents
In @src/app/examples/si-chat-messages/si-chat-container.html around lines 41 -
50, The category chips container (.prompt-suggestions > div:first-child) uses
flex-wrap and needs a responsive override: add a media query or container query
for small breakpoints (e.g., .si-container-xs, .si-container-sm) to set
flex-direction: column, adjust gap/align-items (e.g., align-items: stretch or
flex-start) and remove horizontal wrapping so chips stack vertically; update the
stylesheet used by the si-ai-welcome-screen template (or the parent container
CSS) to include this rule so the chip layout switches to column on small
viewports.

@Killusions Killusions force-pushed the feat/add-ai-welcome-screen branch from 177e1e8 to 2d1237b Compare January 8, 2026 16:52
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: 18

🤖 Fix all issues with AI agents
In @docs/components/chat-messages/chat-message.md:
- Line 119: Change the "Tool Message Component" heading from level 2 to level 3
to match the rest of the document; locate the heading titled "Tool Message
Component" and replace the "##" prefix with "###" so it aligns with "Base chat
message", "Attachment list", "Markdown renderer", "User message", and "AI
message" section headings.

In @docs/patterns/ai/ai-chat.md:
- Line 89: Reword the confusing sentence about height for the
si-ai-chat-container: replace the circular phrasing with a clear statement such
as "The si-ai-chat-container requires a fixed height (either provided by its
parent layout or set directly in pixels)." Ensure the updated text references
the component name si-ai-chat-container and explains that height can come from
the parent or be set on the component itself.

In @package.json:
- Line 156: The package.json devDependency "highlight.js" uses a caret range
("^11.11.1") which is inconsistent with other exact-version devDependencies;
change the dependency entry for "highlight.js" to use the exact version
"11.11.1" (remove the leading caret) so it matches the format used by other
devDependencies like "katex" and "@types/katex".

In @projects/element-ng/chat-messages/chat-message.model.ts:
- Around line 135-143: TemplateChatMessage lacks the discriminant used by other
message types, making runtime/type-narrowing harder; update the
TemplateChatMessage interface to include a readonly type property (matching the
pattern used by BaseChatMessage and other message variants) with a literal value
like 'template' so checks such as message.type === 'template' will narrow the
union of ChatMessage[] to TemplateChatMessage.

In @projects/element-ng/chat-messages/si-ai-chat-container.component.ts:
- Around line 486-491: The null/undefined check in getOutputValue is verbose;
replace the condition `outputValue === undefined || outputValue === null` with
the concise loose-equality check `outputValue == null` so the method still
returns undefined for both null and undefined inputs, and keep the existing
isSignal branch and return behavior unchanged (refer to getOutputValue and
isSignal).

In @projects/element-ng/chat-messages/si-ai-welcome-screen.component.html:
- Around line 11-17: The ngFor loops currently use track $index which can cause
unnecessary DOM churn; update the ngFor directives that iterate categories() and
suggestions to use a stable unique key instead (e.g., track category.label for
the categories loop and track suggestion.id or suggestion.text for the
suggestions loop) so Angular can identify items across reorders/filters; locate
the loops rendering <si-summary-chip> (uses categories(), selectedCategory(),
onCategoryClick) and the suggestions loop and replace the track $index with the
appropriate unique property that is guaranteed stable and unique.
- Line 25: The markup uses the body projection attribute on si-action-card with
a hardcoded text-white class which fails contrast against the card’s background
(variables.$element-base-input-experimental / color-experimental-deep-blue-25)
in light theme; replace the static text-white with a theme-aware text color
(e.g., the project’s theme utility class) or apply conditional styling/class
toggling based on the active theme inside si-ai-welcome-screen.component (or in
si-action-card where <ng-content select="[body]"/> is projected) so the text
color meets contrast requirements in both light and dark themes.

In @projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss:
- Around line 50-52: Replace the ::ng-deep rule targeting button[si-action-card]
with a maintainable approach: remove ::ng-deep from the selector and instead (1)
expose a CSS custom property on the parent/host (e.g., --si-action-card-bg) and
set that in si-ai-welcome-screen.component.scss so the child action-card can
consume it, or (2) use a :host-context(...) selector on the welcome component to
style the child if the child honors host-context, or (3) add an @Input on the
child action-card component to accept a background value and set that input from
the welcome component template; update the action-card implementation to read
the custom property/input so the background-color applied to
button[si-action-card] no longer requires ::ng-deep.
- Around line 15-27: Add a temporary visual debug indicator and instrument the
responsive container to confirm which si-container-* class and measured width
are actually applied at xl/xxl: in the template for the welcome header (::before
key visual) add a non-invasive debug overlay (visible only in dev) that prints
the active si-container-* class, and in the SiResponsiveContainerDirective log
the measured clientWidth from the ResizeObserver callback and the class chosen;
ensure the ResizeObserver measurement runs after layout stabilizes (wrap initial
measurement in requestAnimationFrame or setTimeout 0 and re-run on window
resize) and calculate width using element.clientWidth minus any parent
horizontal padding (account for si-chat-container px-6 / px-md-9) so thresholds
for xl/xxl are evaluated correctly; if timing or padding is the cause, either
adjust the measurement timing or the breakpoint thresholds, and remove the debug
overlay after verification.

In @projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts:
- Around line 49-59: The test name is misleading — it says "should emit
categorySelected" but the assertion checks the `selectedCategory()` signal;
update the spec title to reflect the actual behavior (e.g., "should update
selectedCategory when category is clicked") and keep the existing test body that
sets inputs via `fixture.componentRef.setInput('categories', ...)`, clicks the
`si-summary-chip .chip`, and asserts `component.selectedCategory()`; do not
change the assertion to check an output/event since `selectedCategory` is a
model input/signal, not an emitted output.

In @projects/element-ng/chat-messages/si-chat-message.component.scss:
- Around line 52-55: There are two separate `.message-wrapper` rule blocks;
merge them into a single `.message-wrapper` selector that includes
`min-inline-size: 0`, `max-inline-size: 100%` and the additional properties
currently in the later block so the cascade is preserved; remove the duplicate
rule block and ensure the combined rule appears in the logical location in the
stylesheet to maintain specificity and intended layout.

In @projects/element-ng/chat-messages/si-tool-message.component.scss:
- Around line 15-17: The stylesheet uses deprecated ::ng-deep to style child
component internals (e.g., the rule targeting si-loading-spinner and other
blocks at lines 15-17, 77-93, 95-97); replace this by either (A) moving the deep
styles into the component TypeScript by setting ViewEncapsulation.None on the
SiToolMessageComponent and keeping the selectors without ::ng-deep, or (B)
better, update the child components (si-loading-spinner, si-collapsible-panel)
to expose CSS custom properties (e.g., --loading-spinner-size) and then set
those properties on :host or the component stylesheet without ::ng-deep; if
neither is feasible for now, leave a clear TODO comment and mark the ::ng-deep
usage as temporary.

In @projects/element-ng/chat-messages/si-tool-message.component.spec.ts:
- Line 119: Tests are accessing private/protected methods (formatData,
hasInputArguments, hasOutput, getLoadingState) by casting the component to any;
instead either (a) make these methods public on SiToolMessageComponent if they
are part of the component contract and should be tested directly, or (b) change
the tests to assert rendered output/behavior via the component's public API
(inputs, outputs, DOM queries) rather than calling internal methods; pick one
approach and update the spec cases that reference formatData, hasInputArguments,
hasOutput, and getLoadingState to use the chosen public surface so tests no
longer rely on casting to any.

In @projects/element-ng/chat-messages/si-tool-message.component.ts:
- Around line 132-142: The getLoadingState method contains an outdated comment
about empty-string output but returns false and is unnecessarily verbose;
simplify it to directly return the boolean value of this.loading() (e.g., use
Boolean(this.loading()) or !!this.loading()) and remove the incorrect comment
about empty-string handling; update references in the component to rely on the
simplified getLoadingState implementation.
- Around line 109-121: The runtime check in formatData incorrectly treats any
function as a Signal; replace the fragile typeof+call check with Angular's
isSignal utility to reliably detect Signal values: import and use isSignal(data)
when unwrapping the Signal in formatData (which accepts string | object |
Signal<string|object> | undefined) and then call the Signal only after isSignal
returns true; keep the remaining null/undefined, string and JSON.stringify
handling intact.

In @projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts:
- Around line 108-110: The code assumes tempDiv.firstElementChild is always
non-null; change the logic surrounding tempDiv, createHtml(), and the element
variable to guard against a null firstElementChild: after creating tempDiv and
setting innerHTML, check if tempDiv.firstElementChild exists before casting to
HTMLElement and caching/returning it, and if it's null handle explicitly (e.g.,
return null or wrap text nodes into a container) instead of casting null to
HTMLElement.

In @projects/element-ng/markdown-renderer/markdown-renderer.ts:
- Around line 820-835: The copy button handler that adds listeners to
'.copy-code-btn' should provide visual feedback: update the existing event
listener (the callback registered in
div.querySelectorAll('.copy-code-btn').forEach(...)) to call
navigator.clipboard.writeText(code).then(() => { change the clicked button’s
label/icon/state to indicate success (e.g., set innerText or add a 'copied' CSS
class) and restore the original state after a short timeout }) and in the
.catch() update the button to indicate failure (e.g., show an error state or
tooltip) and also restore after timeout; ensure you reference the clicked
element (const button = e.target as HTMLButtonElement) so the UI updates only
that button and avoid swallowing errors beyond logging.
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 177e1e8 and 2d1237b.

⛔ Files ignored due to path filters (13)
  • package-lock.json is excluded by !**/package-lock.json
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-user-message-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-user-message-element-examples-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-light-linux.png is excluded by !**/*.png
📒 Files selected for processing (47)
  • angular.json
  • api-goldens/element-ng/chat-messages/index.api.md
  • api-goldens/element-ng/markdown-renderer/index.api.md
  • api-goldens/element-ng/translate/index.api.md
  • docs/components/chat-messages/chat-message.md
  • docs/patterns/ai/ai-chat.md
  • package.json
  • playwright/e2e/element-examples/static.spec.ts
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-user-message.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yaml
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/message-action.model.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-chat-input.component.ts
  • projects/element-ng/chat-messages/si-chat-message.component.scss
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • projects/element-ng/link/si-link.directive.ts
  • projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts
  • projects/element-ng/markdown-renderer/markdown-renderer.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
💤 Files with no reviewable changes (2)
  • projects/element-ng/link/si-link.directive.ts
  • projects/element-ng/chat-messages/message-action.model.ts
🧰 Additional context used
🧠 Learnings (40)
📓 Common learnings
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:14-50
Timestamp: 2025-12-09T14:31:33.543Z
Learning: In projects/element-ng/chat-messages/si-ai-chat-container.component.html, message IDs can change, so tracking by message.id is not appropriate. The component uses `track message` (object identity) which is the correct approach for this use case.
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:21-47
Timestamp: 2025-12-09T14:32:34.036Z
Learning: In projects/element-ng/chat-messages, nested if blocks are preferred over switch statements for branching on message types in Angular templates.
Learnt from: Killusions
Repo: siemens/element PR: 1040
File: projects/element-ng/chat-messages/si-chat-input.component.ts:338-349
Timestamp: 2025-11-18T12:37:30.510Z
Learning: In projects/element-ng/chat-messages/si-chat-input.component.ts, the interrupt behavior is intentionally different for button clicks vs Enter key: the button can emit interrupt even without content, but pressing Enter requires content or attachments (canSend() must be true) to emit interrupt.
📚 Learning: 2025-12-11T10:09:01.564Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1151
File: projects/element-ng/auto-collapsable-list/si-auto-collapsable-list.directive.spec.ts:83-104
Timestamp: 2025-12-11T10:09:01.564Z
Learning: In the auto-collapsable-list directive tests (projects/element-ng/auto-collapsable-list/si-auto-collapsable-list.directive.spec.ts), jasmine.clock() successfully controls the directive's setTimeout-based layout logic in zoneless mode. Mock timers work fine here, unlike in select component overflow tests where real setTimeout waits are required.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
📚 Learning: 2025-12-09T14:31:33.543Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:14-50
Timestamp: 2025-12-09T14:31:33.543Z
Learning: In projects/element-ng/chat-messages/si-ai-chat-container.component.html, message IDs can change, so tracking by message.id is not appropriate. The component uses `track message` (object identity) which is the correct approach for this use case.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • projects/element-ng/chat-messages/si-chat-message.component.scss
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-user-message.yaml
  • projects/element-ng/chat-messages/index.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/si-chat-input.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
📚 Learning: 2025-12-15T07:17:06.981Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts:37-49
Timestamp: 2025-12-15T07:17:06.981Z
Learning: In widget-instance-editor-dialog component tests (projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing component initialization. This is likely due to the component's lifecycle behavior or modal initialization timing that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-15T07:16:53.762Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:92-105
Timestamp: 2025-12-15T07:16:53.762Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits must be used instead of fixture.whenStable() to avoid injector destroyed errors during mount/unmount operations in zoneless mode. The GridStack timing-dependent operations require actual async delays.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
📚 Learning: 2025-12-15T07:16:32.082Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:69-80
Timestamp: 2025-12-15T07:16:32.082Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing grid item rendering and initialization. This is likely due to gridstack library's initialization timing or lifecycle behavior that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • playwright/e2e/element-examples/static.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-08T11:25:51.584Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/si-select.component.spec.ts:511-516
Timestamp: 2025-12-08T11:25:51.584Z
Learning: In the select component overflow tests (projects/element-ng/select/si-select.component.spec.ts), jasmine.clock() cannot be used to control the timing for overflow item detection. Real setTimeout waits must be used instead, likely due to ResizeObserver or debounced layout calculations that jasmine.clock() cannot control in zoneless mode.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-08T11:25:20.861Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/si-select.component.spec.ts:204-205
Timestamp: 2025-12-08T11:25:20.861Z
Learning: In zoneless Angular tests (using provideZonelessChangeDetection), calling fixture.changeDetectorRef.markForCheck() before fixture.detectChanges() is required even for components using the default change detection strategy (not OnPush). This differs from zone.js-based testing where markForCheck is primarily needed only for OnPush components.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-04T05:50:17.637Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1135
File: projects/element-ng/tree-view/si-tree-view.component.spec.ts:953-964
Timestamp: 2025-12-04T05:50:17.637Z
Learning: In the siemens/element repository, when making tree-view tests zoneless-ready, jasmine.clock() should be used to mimic setTimeouts even in zoneless mode, as the component implementation relies on setTimeout calls that need to be controlled in tests.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
📚 Learning: 2025-12-01T04:01:27.365Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1099
File: projects/element-ng/accordion/si-accordion.component.spec.ts:39-43
Timestamp: 2025-12-01T04:01:27.365Z
Learning: With Angular 20 and esbuild, synchronous `TestBed.configureTestingModule(...).compileComponents()` calls work correctly even when components use external templates (templateUrl), because esbuild pre-compiles templates at build time. The async/await pattern is not required in this scenario.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
📚 Learning: 2025-12-08T11:24:45.272Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1163
File: projects/element-ng/select/options/si-select-lazy-options.directive.spec.ts:67-85
Timestamp: 2025-12-08T11:24:45.272Z
Learning: In select lazy options tests (projects/element-ng/select/options/si-select-lazy-options.directive.spec.ts), jasmine.clock() cannot control RxJS debounceTime in zoneless mode. Real setTimeout waits must be used instead for tests involving search debouncing.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-04T05:50:38.735Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1135
File: projects/element-ng/tree-view/si-tree-view.component.spec.ts:1244-1245
Timestamp: 2025-12-04T05:50:38.735Z
Learning: In zoneless Angular tests with OnPush components, calling `await runOnPushChangeDetection(fixture)` followed by `await fixture.whenStable()` is NOT redundant. The `runOnPushChangeDetection` helper forces change detection to run for OnPush components, while `whenStable()` waits for all async operations to complete. Both are necessary and serve different purposes.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-15T10:05:59.100Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1193
File: projects/element-ng/search-bar/si-search-bar.component.spec.ts:21-28
Timestamp: 2025-12-15T10:05:59.100Z
Learning: In tests that rely on Jasmine's fake clock to control time-based RxJS operators (e.g., debounceTime), use jasmine.clock().install() together with jasmine.clock().mockDate() to enable precise timing control. Without mockDate, scheduler-based operators may not respond to the fake clock. Apply this guidance to spec files (e.g., any file named *.spec.ts or *.spec.js) that test time-sensitive behavior, ensuring you install and mockDate before advancing time in tests.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • playwright/e2e/element-examples/static.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
📚 Learning: 2025-12-17T04:34:55.597Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1173
File: src/app/examples/si-charts/interactive/interactive.ts:5-5
Timestamp: 2025-12-17T04:34:55.597Z
Learning: Guideline: In Angular projects using OnPush change detection (zoneless mode), you only need to call ChangeDetectorRef.markForCheck() for asynchronous operations (e.g., setTimeout, setInterval, Promises, Observables) where a change is not automatically detected. Event handlers triggered by Angular template bindings (click, input, etc.) will trigger change detection automatically and do not require explicit markForCheck() calls. Apply this broadly to TS files within Angular components/services that use OnPush; use markForCheck() selectively for async work where change detection wouldn’t run otherwise.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • playwright/e2e/element-examples/static.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • projects/element-ng/markdown-renderer/markdown-renderer.ts
  • projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/si-chat-input.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
📚 Learning: 2025-12-30T13:52:33.581Z
Learnt from: dauriamarco
Repo: siemens/element PR: 1221
File: projects/element-ng/side-panel/si-side-panel.component.ts:136-142
Timestamp: 2025-12-30T13:52:33.581Z
Learning: Maintain the existing negative naming convention (e.g., disableBackdrop) across the siemens/element repository for consistency. Do not refactor to positive names (e.g., showBackdrop, hasBackdrop) unless the project explicitly changes the convention. In reviews, flag changes that alter established naming patterns in related files under projects/element-ng.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • projects/element-ng/markdown-renderer/markdown-renderer.ts
  • projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts
  • projects/element-ng/chat-messages/index.ts
  • projects/element-ng/chat-messages/si-chat-input.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/chat-message.model.ts
  • projects/element-ng/translate/si-translatable-keys.interface.ts
  • projects/element-ng/chat-messages/si-user-message.component.spec.ts
📚 Learning: 2026-01-02T16:41:48.359Z
Learnt from: kfenner
Repo: siemens/element PR: 1005
File: docs/fundamentals/styles/sizing.md:18-26
Timestamp: 2026-01-02T16:41:48.359Z
Learning: In Element docs, sizing examples may differ between documentation and implementation to illustrate multiple valid approaches. Do not flag such differences as inconsistencies; treat them as separate illustrative examples (e.g., using height/width in docs vs block-size/inline-size in implementation). Apply this understanding across Markdown documentation files to avoid false-positive review flags.

Applied to files:

  • docs/components/chat-messages/chat-message.md
  • docs/patterns/ai/ai-chat.md
📚 Learning: 2025-12-05T08:00:38.407Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1151
File: projects/element-ng/typeahead/si-typeahead.directive.spec.ts:114-121
Timestamp: 2025-12-05T08:00:38.407Z
Learning: In the typeahead test suite (projects/element-ng/typeahead/si-typeahead.directive.spec.ts), jasmine.clock() must be installed in beforeAll and uninstalled in afterAll (not beforeEach/afterEach) because using per-test clock installation causes schedulerFunction-related issues in these specific tests.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
📚 Learning: 2025-12-01T14:12:11.111Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1104
File: projects/element-ng/datepicker/components/si-day-selection.component.spec.ts:198-202
Timestamp: 2025-12-01T14:12:11.111Z
Learning: In zoneless Angular tests (using provideZonelessChangeDetection), prefer `await fixture.whenStable()` over `fixture.detectChanges()` after dispatching events or triggering async operations, as `whenStable()` waits for all asynchronous operations to complete and better mimics the production environment.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
📚 Learning: 2025-12-09T14:32:34.036Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:21-47
Timestamp: 2025-12-09T14:32:34.036Z
Learning: In projects/element-ng/chat-messages, nested if blocks are preferred over switch statements for branching on message types in Angular templates.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • projects/element-ng/chat-messages/si-chat-message.component.scss
  • projects/element-ng/chat-messages/index.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/chat-message.model.ts
📚 Learning: 2025-12-22T13:04:35.578Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: src/app/examples/ag-grid/ag-grid-empty-state.ts:20-24
Timestamp: 2025-12-22T13:04:35.578Z
Learning: The SiEmptyStateComponent in siemens/element-ng accepts icon names in kebab-case format (e.g., 'element-technical-operator') that may not be directly exported as constants in the element-icons.ts file. Do not flag these as errors if they render correctly at runtime.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/translate/si-translatable-keys.interface.ts
📚 Learning: 2025-12-22T13:29:36.922Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: projects/element-ng/ag-grid/parts/color-scheme.part.ts:35-35
Timestamp: 2025-12-22T13:29:36.922Z
Learning: In the Element design system (projects/element-ng/theme and projects/element-theme), only `--element-body-font-family` is exposed as a CSS custom property for typography. Font sizes are NOT exposed as CSS custom properties; they are defined using internal SCSS variables (e.g., `typography.$si-font-size-body`) that compile to fixed values. Using hardcoded pixel values for fontSize in AG Grid theme configuration (e.g., `fontSize: '14px'`) is the correct approach.

Applied to files:

  • projects/element-ng/chat-messages/si-tool-message.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
📚 Learning: 2026-01-02T16:41:57.274Z
Learnt from: kfenner
Repo: siemens/element PR: 1005
File: docs/fundamentals/styles/sizing.md:18-26
Timestamp: 2026-01-02T16:41:57.274Z
Learning: In Element documentation (siemens/element), sizing utility examples in docs may intentionally differ from implementation examples to demonstrate multiple valid approaches - for example, documentation might use traditional CSS properties like `height` and `width` while the implementation example uses logical properties like `block-size` and `inline-size`. These are considered different examples rather than inconsistencies.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
📚 Learning: 2025-12-17T14:01:05.705Z
Learnt from: dauriamarco
Repo: siemens/element PR: 908
File: projects/element-ng/side-panel/si-side-panel.component.ts:70-74
Timestamp: 2025-12-17T14:01:05.705Z
Learning: In the Element side-panel component (projects/element-ng/side-panel/si-side-panel.component.ts), the `xxxlMinimum` breakpoint (1920px) is intentionally hardcoded as a private static constant rather than being part of the configurable `Breakpoints` interface. This design preserves full Bootstrap compatibility (which only defines breakpoints up to xxl/1400px) while allowing Element to handle ultra-wide screens explicitly without affecting the standard breakpoint configuration.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
📚 Learning: 2025-12-31T07:16:13.451Z
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: projects/element-ng/ag-grid/parts/radio-style.part.ts:15-61
Timestamp: 2025-12-31T07:16:13.451Z
Learning: In the AG Grid theme package (projects/element-ng/ag-grid), styling should maintain consistency with the base Element design system components rather than adding enhancements or extra CSS. If accessibility improvements like focus-visible indicators are needed, they should be implemented at the Element design system level first.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
📚 Learning: 2025-11-18T12:37:30.510Z
Learnt from: Killusions
Repo: siemens/element PR: 1040
File: projects/element-ng/chat-messages/si-chat-input.component.ts:338-349
Timestamp: 2025-11-18T12:37:30.510Z
Learning: In projects/element-ng/chat-messages/si-chat-input.component.ts, the interrupt behavior is intentionally different for button clicks vs Enter key: the button can emit interrupt even without content, but pressing Enter requires content or attachments (canSend() must be true) to emit interrupt.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-chat-container.component.ts
  • projects/element-ng/chat-messages/si-chat-message.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-attachment-list.component.ts
  • projects/element-ng/chat-messages/si-chat-container.component.scss
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.ts
  • projects/element-ng/chat-messages/si-chat-input.component.spec.ts
  • projects/element-ng/chat-messages/si-ai-message.component.ts
  • projects/element-ng/chat-messages/si-tool-message.component.html
  • projects/element-ng/chat-messages/si-user-message.component.ts
  • projects/element-ng/chat-messages/index.ts
  • api-goldens/element-ng/chat-messages/index.api.md
  • projects/element-ng/chat-messages/si-chat-input.component.ts
  • projects/element-ng/chat-messages/si-ai-chat-container.component.ts
  • projects/element-ng/chat-messages/chat-message.model.ts
📚 Learning: 2025-12-09T14:32:26.166Z
Learnt from: Killusions
Repo: siemens/element PR: 998
File: projects/element-ng/chat-messages/si-ai-chat-container.component.html:21-47
Timestamp: 2025-12-09T14:32:26.166Z
Learning: In Angular templates, prefer using nested *ngIf blocks over *ngSwitch for branching on message types within the chat-messages components. Use *ngIf with else branches to handle distinct cases and avoid complex switch logic in HTML templates. This guideline applies to all HTML templates under projects/element-ng/chat-messages.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.html
  • projects/element-ng/chat-messages/si-tool-message.component.html
📚 Learning: 2025-12-01T09:34:50.028Z
Learnt from: Killusions
Repo: siemens/element PR: 1047
File: docs/fundamentals/ux-text-style-guide/basics.md:45-50
Timestamp: 2025-12-01T09:34:50.028Z
Learning: In docs/fundamentals/ux-text-style-guide/basics.md, the Don'ts section intentionally contains duplicate "Hey there!" entries to show that the same informal greeting is an inappropriate alternative for multiple formal welcome messages (both "Welcome to Building X" and "Welcome Werner von Siemens").

Applied to files:

  • projects/element-ng/chat-messages/si-ai-chat-container.component.html
📚 Learning: 2025-12-11T14:44:11.278Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1185
File: projects/element-ng/navbar/si-navbar-item/si-navbar-item.component.html:11-11
Timestamp: 2025-12-11T14:44:11.278Z
Learning: The si-icon component in siemens/element-ng/icon automatically applies aria-hidden="true" to its content. Do not suggest adding aria-hidden="true" to si-icon elements, as accessibility is already handled internally by the component.

Applied to files:

  • projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts
📚 Learning: 2025-12-04T11:54:31.132Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1133
File: projects/element-ng/tour/si-tour.service.spec.ts:21-26
Timestamp: 2025-12-04T11:54:31.132Z
Learning: In the siemens/element repository, all components are standalone by default and do not require the explicit `standalone: true` flag. Components should be added to the `imports` array in TestBed configuration, not the `declarations` array.

Applied to files:

  • projects/element-ng/chat-messages/si-attachment-list.component.spec.ts
📚 Learning: 2025-12-16T16:19:17.950Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1207
File: playwright/snapshots/si-filtered-search.spec.ts-snapshots/si-filtered-search--si-filtered-search-playground--data-entered.yaml:38-38
Timestamp: 2025-12-16T16:19:17.950Z
Learning: Do not review files in the playwright/snapshots directory, as they contain auto-generated test artifacts. Exclude any YAML snapshot files under playwright/snapshots from code reviews in the siemens/element repository. If a YAML file is not an auto-generated snapshot, verify its origin before skipping.

Applied to files:

  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-user-message.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yaml
📚 Learning: 2026-01-05T16:46:16.913Z
Learnt from: spliffone
Repo: siemens/element PR: 453
File: projects/element-translate-ng/ngx-translate/si-translate-ngxt.service.ts:42-44
Timestamp: 2026-01-05T16:46:16.913Z
Learning: In projects/element-translate-ng, the peer dependency range for ngx-translate/core includes both v16 and v17, requiring use of APIs compatible with both versions. The deprecated properties `currentLang`, `getDefaultLang()`, and `setDefaultLang()` must be used instead of their v17 replacements (`getCurrentLang()`, `getFallbackLang()`, `setFallbackLang()`) until v16 support is dropped in v49.

Applied to files:

  • projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts
  • api-goldens/element-ng/markdown-renderer/index.api.md
📚 Learning: 2025-12-09T14:19:26.605Z
Learnt from: Killusions
Repo: siemens/element PR: 967
File: package.json:153-153
Timestamp: 2025-12-09T14:19:26.605Z
Learning: In library projects (e.g., element-ng), do not list implementation dependencies for optional features in the main dependencies. Move those into devDependencies (used for demos/examples) and have consuming apps install them separately if they enable the feature. This avoids bloating library consumers with unnecessary packages and clarifies that optional features are not guaranteed to work without extra installs. If a feature is truly optional, consider documenting it and, if appropriate, using optionalDependencies to reflect optional runtime usage.

Applied to files:

  • package.json
📚 Learning: 2026-01-07T19:44:24.336Z
Learnt from: spliffone
Repo: siemens/element PR: 453
File: projects/element-translate-ng/package.json:26-26
Timestamp: 2026-01-07T19:44:24.336Z
Learning: In this repository, peerDependencies in package.json should use hyphen-major-version ranges (e.g., '16 - 17', '22 - 25') instead of standard semver ranges like '>=16.0.0 <18.0.0' or '^16.0.0 || ^17.0.0'. This convention is applied across all packages for consistency. During reviews, verify that each package.json lists peerDependencies using a hyphen-range format, and update any that use conventional semver expressions. If needed, adjust to the correct major-version bounds (e.g., '16 - 17' for 16.x/17.x).

Applied to files:

  • package.json
📚 Learning: 2025-12-22T13:26:40.908Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1237
File: tools/api-goldens/test_api_report.ts:19-23
Timestamp: 2025-12-22T13:26:40.908Z
Learning: In the siemens/element repository, the team intentionally uses internal APIs from `microsoft/api-extractor` (such as `AstDeclaration`, `AstModule`, `ExportAnalyzer`, `ApiItemMetadata`, and `Collector` from `/lib/analyzer` and `/lib/collector` paths) in `tools/api-goldens/test_api_report.ts` to customize API extraction behavior (e.g., marking protected members as internal). This is an accepted practice because the required functionality is not available through the public API, and the version is pinned to mitigate risks.

Applied to files:

  • api-goldens/element-ng/markdown-renderer/index.api.md
📚 Learning: 2025-12-23T09:24:35.163Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/translate/index.api.md:12-84
Timestamp: 2025-12-23T09:24:35.163Z
Learning: In the siemens/element repository, do not review files under the api-goldens/ directory (e.g., api-goldens/**/index.api.md) since they are auto-generated by API Extractor. Exclude these from review checks and focus on source files that are not auto-generated.

Applied to files:

  • api-goldens/element-ng/markdown-renderer/index.api.md
  • api-goldens/element-ng/chat-messages/index.api.md
  • api-goldens/element-ng/translate/index.api.md
📚 Learning: 2025-12-23T09:24:57.843Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/index.api.md:324-325
Timestamp: 2025-12-23T09:24:57.843Z
Learning: Do not review files in the api-goldens directory, as they are auto-generated API reports produced by API Extractor.

Applied to files:

  • api-goldens/element-ng/markdown-renderer/index.api.md
  • api-goldens/element-ng/chat-messages/index.api.md
  • api-goldens/element-ng/translate/index.api.md
📚 Learning: 2025-12-23T09:24:40.395Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/module-federation/index.api.md:7-11
Timestamp: 2025-12-23T09:24:40.395Z
Learning: In the siemens/element repository, do not review any files under the api-goldens directory, as they are auto-generated API reports produced by API Extractor. These MD files should be excluded from review unless explicitly overridden.

Applied to files:

  • api-goldens/element-ng/markdown-renderer/index.api.md
  • api-goldens/element-ng/chat-messages/index.api.md
  • api-goldens/element-ng/translate/index.api.md
📚 Learning: 2025-12-04T10:35:45.465Z
Learnt from: Killusions
Repo: siemens/element PR: 1147
File: docs/fundamentals/ux-text-style-guide/dialogs-and-buttons.md:81-84
Timestamp: 2025-12-04T10:35:45.465Z
Learning: In docs/fundamentals/ux-text-style-guide/dialogs-and-buttons.md, the Clear content section's Do's intentionally contains four identical "Delete Wittelsbacherplatz München?" entries to show that the same simple, direct question is the appropriate alternative for multiple different incorrect phrasings (overly wordy questions, generic terms, unnecessary disclaimers, and redundant words).

Applied to files:

  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yaml
  • playwright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yaml
📚 Learning: 2025-12-17T08:58:19.300Z
Learnt from: akashsonune
Repo: siemens/element PR: 567
File: projects/charts-ng/src/components/si-chart/si-chart.component.ts:604-609
Timestamp: 2025-12-17T08:58:19.300Z
Learning: In projects/charts-ng/src/components/si-chart/si-chart.component.ts, when implementing theme changes with chart.setTheme() that reuses the ECharts instance without disposing it, do not call afterChartInit() again as it will duplicate event listener registrations, leading to memory leaks and multiple event firings.

Applied to files:

  • projects/element-ng/markdown-renderer/markdown-renderer.ts
📚 Learning: 2025-12-03T13:29:01.075Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1058
File: docs/components/pages/landing-page.md:34-36
Timestamp: 2025-12-03T13:29:01.075Z
Learning: In Markdown blockquotes with numbered sequences, escaping only the first number (e.g., `\1.`) is sufficient to prevent auto-numbering for the entire sequence. Subsequent numbers (2., 3., etc.) do not need individual escaping.

Applied to files:

  • playwright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yaml
🧬 Code graph analysis (7)
playwright/e2e/element-examples/static.spec.ts (1)
playwright/support/test-helpers.ts (1)
  • test (286-296)
projects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.ts (1)
projects/element-ng/filtered-search/testing/si-filtered-search-criterion.harness.ts (1)
  • text (126-128)
projects/element-ng/chat-messages/si-ai-chat-container.component.spec.ts (1)
projects/element-ng/chat-messages/chat-message.model.ts (2)
  • ChatMessage (157-157)
  • MessageAction (18-31)
projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (3)
src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (1)
  • Component (13-42)
src/app/examples/si-chat-messages/si-ai-chat-container.ts (1)
  • Component (22-299)
src/app/examples/si-chat-messages/si-chat-container.ts (1)
  • Component (43-383)
projects/element-ng/chat-messages/si-tool-message.component.ts (2)
projects/element-ng/chat-messages/si-chat-container.component.ts (1)
  • Component (40-223)
projects/element-translate-ng/translate/t.ts (1)
  • t (38-51)
projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts (3)
projects/element-translate-ng/translate/si-translate.inject.ts (1)
  • injectSiTranslateService (11-20)
projects/element-translate-ng/translate/t.ts (1)
  • t (38-51)
projects/element-ng/markdown-renderer/markdown-renderer.ts (2)
  • MarkdownRendererOptions (18-47)
  • getMarkdownRenderer (66-889)
projects/element-ng/markdown-renderer/markdown-renderer.ts (1)
projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts (3)
  • getCachedOrCreateElement (91-123)
  • getCachedOrCreateString (129-159)
  • sanitizeHtmlWithStyles (13-85)
🪛 ast-grep (0.40.4)
projects/element-ng/markdown-renderer/si-markdown-renderer.component.ts

[warning] 106-106: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: containerEl.innerHTML = ''
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)

projects/element-ng/markdown-renderer/markdown-renderer.ts

[warning] 536-536: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: tempTable.innerHTML = <tbody>${row}</tbody>
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)


[warning] 757-757: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: div.innerHTML = processedHtml
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)


[warning] 536-536: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: tempTable.innerHTML = <tbody>${row}</tbody>
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)


[warning] 757-757: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: div.innerHTML = processedHtml
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)


[warning] 488-488: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(escapedPipePlaceholder, 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 734-734: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(paragraphPlaceholder, 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts

[warning] 108-108: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: tempDiv.innerHTML = createHtml()
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)


[warning] 108-108: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: tempDiv.innerHTML = createHtml()
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build


<si-docs-api component="SiMarkdownRendererComponent"></si-docs-api>

## Tool Message Component
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adjusting heading level for consistency.

The "## Tool Message Component" heading uses level 2 (##), while other component sections in this file use level 3 (###) headings:

  • Line 89: "### Base chat message"
  • Line 105: "### Attachment list"
  • Line 111: "### Markdown renderer"

For consistency within this document structure, consider changing to:

-## Tool Message Component
+### Tool message

This would align with the existing heading hierarchy and match the style used for "User message" and "AI message" sections.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## Tool Message Component
### Tool message
🤖 Prompt for AI Agents
In @docs/components/chat-messages/chat-message.md at line 119, Change the "Tool
Message Component" heading from level 2 to level 3 to match the rest of the
document; locate the heading titled "Tool Message Component" and replace the
"##" prefix with "###" so it aligns with "Base chat message", "Attachment list",
"Markdown renderer", "User message", and "AI message" section headings.

Comment on lines 135 to 143
export interface TemplateChatMessage {
/**
* Template to render the message
*/
template: TemplateRef<any>;

/** Context data to pass to the template */
templateContext?: any;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adding a type discriminator to TemplateChatMessage.

Unlike other message types that extend BaseChatMessage with a type discriminator, TemplateChatMessage lacks one. This could make runtime type narrowing more difficult when iterating over ChatMessage[].

♻️ Optional: Add type discriminator
 export interface TemplateChatMessage {
+  /** Type of message */
+  type: 'template';
+
   /**
    * Template to render the message
    */
   template: TemplateRef<any>;

   /** Context data to pass to the template */
   templateContext?: any;
 }

This would enable consistent type narrowing:

if (message.type === 'template') {
  // TypeScript knows message is TemplateChatMessage
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface TemplateChatMessage {
/**
* Template to render the message
*/
template: TemplateRef<any>;
/** Context data to pass to the template */
templateContext?: any;
}
export interface TemplateChatMessage {
/** Type of message */
type: 'template';
/**
* Template to render the message
*/
template: TemplateRef<any>;
/** Context data to pass to the template */
templateContext?: any;
}
🤖 Prompt for AI Agents
In @projects/element-ng/chat-messages/chat-message.model.ts around lines 135 -
143, TemplateChatMessage lacks the discriminant used by other message types,
making runtime/type-narrowing harder; update the TemplateChatMessage interface
to include a readonly type property (matching the pattern used by
BaseChatMessage and other message variants) with a literal value like 'template'
so checks such as message.type === 'template' will narrow the union of
ChatMessage[] to TemplateChatMessage.

Comment on lines 481 to 486
protected getContentValue<T extends string | object>(content: T | Signal<T> | undefined): T {
if (!content) return '' as T;
return isSignal(content) ? (content as Signal<T>)() : content;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix type safety issue in getContentValue.

Line 482 returns '' as T when content is undefined, but T can be string | object. Returning an empty string when T is object will cause runtime errors.

🐛 Proposed fix
 protected getContentValue<T extends string | object>(content: T | Signal<T> | undefined): T {
-  if (!content) return '' as T;
+  if (!content) return (typeof content === 'object' ? {} : '') as T;
   return isSignal(content) ? (content as Signal<T>)() : content;
 }

Alternatively, if empty object is not the desired default, consider splitting this into two separate methods for string and object types, or throw an error for invalid cases.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 486 to 493
protected getOutputValue(
outputValue: string | object | Signal<string | object> | undefined
): string | object | undefined {
if (outputValue === undefined || outputValue === null) return undefined;
return isSignal(outputValue) ? (outputValue as Signal<string | object>)() : outputValue;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider simplifying the null check.

The condition outputValue === undefined || outputValue === null can be simplified using loose equality: outputValue == null, which checks for both null and undefined.

♻️ Proposed refactor
 protected getOutputValue(
   outputValue: string | object | Signal<string | object> | undefined
 ): string | object | undefined {
-  if (outputValue === undefined || outputValue === null) return undefined;
+  if (outputValue == null) return undefined;
   return isSignal(outputValue) ? (outputValue as Signal<string | object>)() : outputValue;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
protected getOutputValue(
outputValue: string | object | Signal<string | object> | undefined
): string | object | undefined {
if (outputValue === undefined || outputValue === null) return undefined;
return isSignal(outputValue) ? (outputValue as Signal<string | object>)() : outputValue;
}
protected getOutputValue(
outputValue: string | object | Signal<string | object> | undefined
): string | object | undefined {
if (outputValue == null) return undefined;
return isSignal(outputValue) ? (outputValue as Signal<string | object>)() : outputValue;
}
🤖 Prompt for AI Agents
In @projects/element-ng/chat-messages/si-ai-chat-container.component.ts around
lines 486 - 491, The null/undefined check in getOutputValue is verbose; replace
the condition `outputValue === undefined || outputValue === null` with the
concise loose-equality check `outputValue == null` so the method still returns
undefined for both null and undefined inputs, and keep the existing isSignal
branch and return behavior unchanged (refer to getOutputValue and isSignal).

Comment on lines 52 to 55
.message-wrapper {
min-inline-size: 0;
max-inline-size: 100%;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

LGTM! Consider consolidating duplicate selectors.

The max-inline-size: 100% addition is appropriate for responsive layout. Note that .message-wrapper is defined again at lines 93-104 with additional properties. While CSS cascade handles this correctly, consolidating these into a single rule block would improve maintainability.

♻️ Optional: Consolidate duplicate .message-wrapper selectors

The .message-wrapper selector appears twice (lines 52-55 and 93-104). Consider merging them:

-.message-wrapper {
-  min-inline-size: 0;
-  max-inline-size: 100%;
-}
-
 // ... other rules ...

 .message-wrapper {
   min-inline-size: 0;
+  max-inline-size: 100%;
   inline-size: auto;

   &.start {
     margin-inline-end: auto;
   }

   &.end {
     margin-inline-start: auto;
   }
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In @projects/element-ng/chat-messages/si-chat-message.component.scss around
lines 52 - 55, There are two separate `.message-wrapper` rule blocks; merge them
into a single `.message-wrapper` selector that includes `min-inline-size: 0`,
`max-inline-size: 100%` and the additional properties currently in the later
block so the cascade is preserved; remove the duplicate rule block and ensure
the combined rule appears in the logical location in the stylesheet to maintain
specificity and intended layout.

Comment on lines 109 to 121
protected formatData(data: string | object | Signal<string | object> | undefined): string {
if (data === undefined || data === null) return '';
// Unwrap signal if provided
const unwrappedData =
typeof data === 'function' && 'call' in data ? (data as Signal<string | object>)() : data;
if (unwrappedData === undefined || unwrappedData === null) return '';
if (typeof unwrappedData === 'string') return unwrappedData;
try {
return JSON.stringify(unwrappedData, null, 2);
} catch {
return String(unwrappedData);
}
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🌐 Web query:

Angular isSignal utility function @angular/core

💡 Result:

isSignal checks whether a value is an Angular Signal (runtime type guard).

Usage

  • Import: import { isSignal } from '@angular/core'. [1]
  • Signature: isSignal(value: unknown): value is Signal. [1]
  • Example:
    const count = signal(0);
    isSignal(count); // true
    isSignal(42); // false. [2]

References
[1] Angular API — isSignal.
[2] Angular Guide — Signals (shows example usage of isSignal).


🏁 Script executed:

fd -t f "si-tool-message.component.ts" --exec head -20 {} \;

Repository: siemens/element

Length of output: 953


🏁 Script executed:

fd -t f "package.json" --exec grep -l "angular" {} \;

Repository: siemens/element

Length of output: 335


🏁 Script executed:

cat -n "projects/element-ng/chat-messages/si-tool-message.component.ts" | sed -n '100,130p'

Repository: siemens/element

Length of output: 1332


🏁 Script executed:

cat "projects/element-ng/package.json" | jq '.dependencies."@angular/core"' 2>/dev/null || grep -A 5 "@angular/core" projects/element-ng/package.json

Repository: siemens/element

Length of output: 63


🏁 Script executed:

cat "package.json" | jq '.dependencies."@angular/core"' 2>/dev/null || grep -A 5 "@angular/core" package.json | head -5

Repository: siemens/element

Length of output: 67


🏁 Script executed:

cat -n "projects/element-ng/chat-messages/si-tool-message.component.ts" | head -20

Repository: siemens/element

Length of output: 1093


Use isSignal for reliable Signal detection.

The current check typeof data === 'function' && 'call' in data is fragile—any function will match this pattern, not just Angular Signals. Angular 21+ provides the isSignal utility for proper runtime type checking.

♻️ Recommended change
-import { Component, input, Signal, booleanAttribute } from '@angular/core';
+import { Component, input, Signal, booleanAttribute, isSignal } from '@angular/core';

 protected formatData(data: string | object | Signal<string | object> | undefined): string {
   if (data === undefined || data === null) return '';
   // Unwrap signal if provided
-  const unwrappedData =
-    typeof data === 'function' && 'call' in data ? (data as Signal<string | object>)() : data;
+  const unwrappedData = isSignal(data) ? data() : data;
   if (unwrappedData === undefined || unwrappedData === null) return '';
   if (typeof unwrappedData === 'string') return unwrappedData;
   try {
     return JSON.stringify(unwrappedData, null, 2);
   } catch {
     return String(unwrappedData);
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
protected formatData(data: string | object | Signal<string | object> | undefined): string {
if (data === undefined || data === null) return '';
// Unwrap signal if provided
const unwrappedData =
typeof data === 'function' && 'call' in data ? (data as Signal<string | object>)() : data;
if (unwrappedData === undefined || unwrappedData === null) return '';
if (typeof unwrappedData === 'string') return unwrappedData;
try {
return JSON.stringify(unwrappedData, null, 2);
} catch {
return String(unwrappedData);
}
}
protected formatData(data: string | object | Signal<string | object> | undefined): string {
if (data === undefined || data === null) return '';
// Unwrap signal if provided
const unwrappedData = isSignal(data) ? data() : data;
if (unwrappedData === undefined || unwrappedData === null) return '';
if (typeof unwrappedData === 'string') return unwrappedData;
try {
return JSON.stringify(unwrappedData, null, 2);
} catch {
return String(unwrappedData);
}
}
🤖 Prompt for AI Agents
In @projects/element-ng/chat-messages/si-tool-message.component.ts around lines
109 - 121, The runtime check in formatData incorrectly treats any function as a
Signal; replace the fragile typeof+call check with Angular's isSignal utility to
reliably detect Signal values: import and use isSignal(data) when unwrapping the
Signal in formatData (which accepts string | object | Signal<string|object> |
undefined) and then call the Signal only after isSignal returns true; keep the
remaining null/undefined, string and JSON.stringify handling intact.

Comment on lines 132 to 142
protected getLoadingState(): boolean {
const loadingValue = this.loading();

// If explicitly loading
if (loadingValue) {
return true;
}

// If output is empty string (not undefined), show loading
return false;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Simplify getLoadingState method.

The comment on line 140 mentions "If output is empty string (not undefined), show loading" but the code returns false. If this behavior isn't needed, the method can be simplified.

♻️ Simplified implementation
 protected getLoadingState(): boolean {
-  const loadingValue = this.loading();
-
-  // If explicitly loading
-  if (loadingValue) {
-    return true;
-  }
-
-  // If output is empty string (not undefined), show loading
-  return false;
+  return this.loading();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
protected getLoadingState(): boolean {
const loadingValue = this.loading();
// If explicitly loading
if (loadingValue) {
return true;
}
// If output is empty string (not undefined), show loading
return false;
}
protected getLoadingState(): boolean {
return this.loading();
}
🤖 Prompt for AI Agents
In @projects/element-ng/chat-messages/si-tool-message.component.ts around lines
132 - 142, The getLoadingState method contains an outdated comment about
empty-string output but returns false and is unnecessarily verbose; simplify it
to directly return the boolean value of this.loading() (e.g., use
Boolean(this.loading()) or !!this.loading()) and remove the incorrect comment
about empty-string handling; update references in the component to rely on the
simplified getLoadingState implementation.

Comment on lines 108 to 110
const tempDiv = document.createElement('div');
tempDiv.innerHTML = createHtml();
const element = tempDiv.firstElementChild as HTMLElement;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Handle potential null from firstElementChild.

If createHtml() returns an empty string or only text content without an element, firstElementChild will be null, and the function will cache and return null cast as HTMLElement. This could cause issues downstream.

🐛 Proposed fix
   const tempDiv = document.createElement('div');
   tempDiv.innerHTML = createHtml();
-  const element = tempDiv.firstElementChild as HTMLElement;
+  const element = (tempDiv.firstElementChild as HTMLElement) ?? tempDiv;

Alternatively, add a guard to ensure the element exists before caching.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const tempDiv = document.createElement('div');
tempDiv.innerHTML = createHtml();
const element = tempDiv.firstElementChild as HTMLElement;
const tempDiv = document.createElement('div');
tempDiv.innerHTML = createHtml();
const element = (tempDiv.firstElementChild as HTMLElement) ?? tempDiv;
🧰 Tools
🪛 ast-grep (0.40.4)

[warning] 108-108: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: tempDiv.innerHTML = createHtml()
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)


[warning] 108-108: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: tempDiv.innerHTML = createHtml()
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)

🤖 Prompt for AI Agents
In @projects/element-ng/markdown-renderer/markdown-renderer-helpers.ts around
lines 108 - 110, The code assumes tempDiv.firstElementChild is always non-null;
change the logic surrounding tempDiv, createHtml(), and the element variable to
guard against a null firstElementChild: after creating tempDiv and setting
innerHTML, check if tempDiv.firstElementChild exists before casting to
HTMLElement and caching/returning it, and if it's null handle explicitly (e.g.,
return null or wrap text nodes into a container) instead of casting null to
HTMLElement.

Comment on lines 820 to 841
// Add event listeners for copy buttons
div.querySelectorAll('.copy-code-btn').forEach(btn => {
btn.addEventListener('click', e => {
const button = e.target as HTMLButtonElement;
const codeId = button.getAttribute('data-code-id');
if (!codeId) return;

const codeElement = div.querySelector(`#${codeId}`);
if (!codeElement) return;

const code = codeElement.textContent ?? '';
navigator.clipboard.writeText(code).catch(() => {
console.warn('Failed to copy code to clipboard');
});
});
});
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Copy button event listener lacks user feedback.

The copy-to-clipboard functionality silently succeeds or fails. Consider providing visual feedback (e.g., changing button icon temporarily) to indicate success.

🤖 Prompt for AI Agents
In @projects/element-ng/markdown-renderer/markdown-renderer.ts around lines 820
- 835, The copy button handler that adds listeners to '.copy-code-btn' should
provide visual feedback: update the existing event listener (the callback
registered in div.querySelectorAll('.copy-code-btn').forEach(...)) to call
navigator.clipboard.writeText(code).then(() => { change the clicked button’s
label/icon/state to indicate success (e.g., set innerText or add a 'copied' CSS
class) and restore the original state after a short timeout }) and in the
.catch() update the button to indicate failure (e.g., show an error state or
tooltip) and also restore after timeout; ensure you reference the clicked
element (const button = e.target as HTMLButtonElement) so the UI updates only
that button and avoid swallowing errors beyond logging.

@Killusions Killusions force-pushed the feat/add-ai-welcome-screen branch from 2d1237b to 7edff83 Compare January 9, 2026 12:17
@Killusions Killusions force-pushed the feat/add-ai-welcome-screen branch from fcde13b to ef0b805 Compare January 16, 2026 16:28
@Killusions Killusions force-pushed the feat/add-ai-welcome-screen branch from ef0b805 to 415d82f Compare January 16, 2026 16:28
@github-actions
Copy link

Code Coverage

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.

3 participants