-
Notifications
You must be signed in to change notification settings - Fork 13
feat(chat-messages): add ai-welcome-screen component #1231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
4d544d1 to
3228016
Compare
📝 WalkthroughWalkthroughAdds 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
Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
There was a problem hiding this 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
⛔ Files ignored due to path filters (11)
package-lock.jsonis excluded by!**/package-lock.jsonplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-light-linux.pngis excluded by!**/*.png
📒 Files selected for processing (68)
.npmrcapi-goldens/element-ng/chat-messages/index.api.mdapi-goldens/element-ng/markdown-renderer/index.api.mdapi-goldens/element-ng/translate/index.api.mddocs/components/chat-messages/chat-message.mddocs/patterns/ai/ai-chat.mdpackage.jsonplaywright/e2e/element-examples/static.spec.tsplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message.yamlplaywright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yamlprojects/dashboards-demo/src/styles.scssprojects/element-ng/chat-messages/chat-message.model.tsprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/message-action.model.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/si-ai-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-message.component.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-chat-container.component.tsprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/element-ng/chat-messages/si-chat-input.component.tsprojects/element-ng/chat-messages/si-chat-message.component.scssprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/element-ng/chat-messages/si-tool-message.component.scssprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/chat-messages/si-user-message.component.spec.tsprojects/element-ng/chat-messages/si-user-message.component.tsprojects/element-ng/link/si-link.directive.tsprojects/element-ng/markdown-renderer/markdown-renderer.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.tsprojects/element-ng/status-bar/si-status-bar.component.tsprojects/element-ng/translate/si-translatable-keys.interface.tsprojects/element-theme/src/styles/components/_markdown-hljs-theme.scssprojects/element-theme/src/styles/components/_markdown.scssprojects/element-theme/src/styles/variables/_semantic-tokens.scssprojects/element-theme/src/theme/_theme-element.scsssrc/app/examples/si-chat-messages/si-ai-chat-container.htmlsrc/app/examples/si-chat-messages/si-ai-chat-container.tssrc/app/examples/si-chat-messages/si-ai-message.tssrc/app/examples/si-chat-messages/si-ai-welcome-screen.htmlsrc/app/examples/si-chat-messages/si-ai-welcome-screen.tssrc/app/examples/si-chat-messages/si-chat-container.htmlsrc/app/examples/si-chat-messages/si-chat-container.tssrc/app/examples/si-chat-messages/si-chat-input.htmlsrc/app/examples/si-chat-messages/si-tool-message.htmlsrc/app/examples/si-chat-messages/si-tool-message.tssrc/app/examples/si-chat-messages/si-user-message.tssrc/app/examples/si-markdown-renderer/si-markdown-renderer.htmlsrc/app/examples/si-markdown-renderer/si-markdown-renderer.tssrc/assets/sample-markdown.mdsrc/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.tsdocs/components/chat-messages/chat-message.mdsrc/app/examples/si-chat-messages/si-ai-message.tssrc/app/examples/si-chat-messages/si-ai-chat-container.htmlprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/chat-messages/si-ai-message.component.spec.tsprojects/element-ng/chat-messages/si-chat-message.component.tssrc/app/examples/si-chat-messages/si-tool-message.htmlprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-user-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/element-ng/chat-messages/si-chat-message.component.scssprojects/element-ng/chat-messages/si-chat-container.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlsrc/app/examples/si-chat-messages/si-user-message.tsprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-tool-message.component.tssrc/app/examples/si-chat-messages/si-tool-message.tsprojects/element-ng/chat-messages/si-tool-message.component.scssprojects/element-ng/chat-messages/chat-message.model.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-ai-message.component.tssrc/app/examples/si-chat-messages/si-chat-container.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/index.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/element-ng/chat-messages/si-user-message.component.tssrc/app/examples/si-chat-messages/si-ai-chat-container.tssrc/app/examples/si-chat-messages/si-chat-container.htmlprojects/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.tssrc/app/examples/si-chat-messages/si-chat-input.htmlsrc/app/examples/si-chat-messages/si-ai-chat-container.htmlprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/element-ng/chat-messages/si-chat-container.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/chat-messages/chat-message.model.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-ai-message.component.tssrc/app/examples/si-chat-messages/si-chat-container.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/element-ng/chat-messages/si-user-message.component.tssrc/app/examples/si-chat-messages/si-ai-chat-container.tssrc/app/examples/si-chat-messages/si-chat-container.htmlprojects/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.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsplaywright/e2e/element-examples/static.spec.tsprojects/element-ng/chat-messages/si-ai-message.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/chat-messages/si-user-message.component.spec.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.tssrc/app/examples/si-chat-messages/si-ai-message.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsplaywright/e2e/element-examples/static.spec.tsprojects/element-ng/chat-messages/si-ai-message.component.spec.tsprojects/element-ng/chat-messages/si-chat-message.component.tssrc/app/examples/si-chat-messages/si-ai-welcome-screen.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tssrc/app/examples/si-markdown-renderer/si-markdown-renderer.tsprojects/element-ng/chat-messages/si-user-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/element-ng/chat-messages/si-chat-container.component.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.tssrc/app/examples/si-chat-messages/si-user-message.tsprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/markdown-renderer/markdown-renderer.tssrc/app/examples/si-chat-messages/si-tool-message.tsprojects/element-ng/chat-messages/chat-message.model.tsprojects/element-ng/translate/si-translatable-keys.interface.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/si-ai-message.component.tssrc/app/examples/si-chat-messages/si-chat-container.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/si-user-message.component.tssrc/app/examples/si-chat-messages/si-ai-chat-container.tsprojects/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.tssrc/app/examples/si-chat-messages/si-ai-welcome-screen.tssrc/app/examples/si-markdown-renderer/si-markdown-renderer.tssrc/app/examples/si-chat-messages/si-user-message.tssrc/app/examples/si-chat-messages/si-tool-message.tssrc/app/examples/si-chat-messages/si-chat-container.tssrc/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.htmlprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/chat-messages/si-chat-message.component.scssprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/chat-messages/si-tool-message.component.scssprojects/element-ng/chat-messages/chat-message.model.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/index.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/element-ng/chat-messages/si-user-message.component.tssrc/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.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/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.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/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.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.scssprojects/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.htmlprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/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.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/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.tsprojects/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.tsprojects/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.yamlplaywright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yamlplaywright/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.yamlsrc/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.yamlplaywright/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
| // @public (undocumented) | ||
| export interface PromptCategory { | ||
| // (undocumented) | ||
| label: string; | ||
| } | ||
|
|
||
| // @public (undocumented) | ||
| export interface PromptSuggestion { | ||
| // (undocumented) | ||
| text: string; | ||
| } |
There was a problem hiding this comment.
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 -20Repository: 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 -50Repository: 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/nullRepository: 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.
| private messageActionsCache = new WeakMap< | ||
| ChatMessage, | ||
| { primary: MessageAction[]; secondary: MenuItem[]; version: number } | ||
| >(); | ||
|
|
||
| private messageVersions = new WeakMap<ChatMessage, number>(); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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
doneRepository: 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 -nRepository: 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.tsRepository: 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 2Repository: 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.
| it('should handle signal output', () => { | ||
| const outputSignal = signal('{"result": 20}'); | ||
| fixture.componentRef.setInput('output', outputSignal); | ||
| fixture.detectChanges(); | ||
|
|
||
| expect((component as any).hasOutput()).toBe(true); | ||
| }); |
There was a problem hiding this comment.
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.
| protected hasInputArguments(): boolean { | ||
| return this.inputArguments() !== undefined && this.inputArguments() !== null; | ||
| } | ||
|
|
||
| protected hasOutput(): boolean { | ||
| const outputValue = this.output(); | ||
| return outputValue !== undefined && outputValue !== null; | ||
| } |
There was a problem hiding this comment.
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.
| 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.
| protected getOutputValue(): string | object | undefined { | ||
| const outputValue = this.output(); | ||
| return outputValue as string | object | undefined; | ||
| } |
There was a problem hiding this comment.
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.
| 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.
| 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'); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
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.
| 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); |
There was a problem hiding this comment.
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=tsRepository: 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 -20Repository: 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.tsRepository: 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.
| 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); |
There was a problem hiding this comment.
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.
| 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); |
There was a problem hiding this comment.
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.
3228016 to
912a98e
Compare
912a98e to
60b0a60
Compare
There was a problem hiding this 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()returnstrue. Consider addressing that feedback.projects/element-ng/chat-messages/si-chat-container.component.scss (1)
23-29: Remove the unnecessary::ng-deeppseudo-class.The
::ng-deep &:has(si-ai-welcome-screen)selector makes the rule global when likely not intended. Since the&refers to.chat-containerwithin the component's own template, the::ng-deepis 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-deepselector.The
::ng-deepselector is deprecated and should be avoided. Consider using CSS custom properties, adding a CSS class directly to the button elements, or settingViewEncapsulation.Noneif cross-component styling is required.src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (2)
21-28: Mismatch betweenselectedCategoryand category labels (previously flagged).As noted in previous reviews, the
selectedCategoryis 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
promptSuggestionsis 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,
filteredPromptSuggestionsis initialized as a static signal and doesn't update whenselectedCategorychanges. For demonstration purposes showing the simple pattern, this is acceptable, though acomputed()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; preferisSignalfrom Angular core.The check
typeof data === 'function' && 'call' in datais unreliable since all functions have acallproperty. Angular providesisSignal()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:getLoadingStatecontains 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 ingetOutputValue.The cast
as string | object | undefinedmatches the declared return type and serves no purpose.
📜 Review details
Configuration used: Path: .coderabbit.yml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (11)
package-lock.jsonis excluded by!**/package-lock.jsonplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-light-linux.pngis excluded by!**/*.png
📒 Files selected for processing (70)
.npmrcangular.jsonapi-goldens/element-ng/chat-messages/index.api.mdapi-goldens/element-ng/markdown-renderer/index.api.mdapi-goldens/element-ng/translate/index.api.mddocs/components/chat-messages/chat-message.mddocs/patterns/ai/ai-chat.mdpackage.jsonplaywright/e2e/element-examples/static.spec.tsplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message.yamlplaywright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yamlprojects/dashboards-demo/src/styles.scssprojects/element-ng/chat-messages/chat-message.model.tsprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/message-action.model.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/si-ai-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-message.component.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-chat-container.component.tsprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/element-ng/chat-messages/si-chat-input.component.tsprojects/element-ng/chat-messages/si-chat-message.component.scssprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/element-ng/chat-messages/si-tool-message.component.scssprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/chat-messages/si-user-message.component.spec.tsprojects/element-ng/chat-messages/si-user-message.component.tsprojects/element-ng/link/si-link.directive.tsprojects/element-ng/markdown-renderer/markdown-renderer-helpers.tsprojects/element-ng/markdown-renderer/markdown-renderer.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.tsprojects/element-ng/status-bar/si-status-bar.component.tsprojects/element-ng/translate/si-translatable-keys.interface.tsprojects/element-theme/src/styles/components/_markdown-hljs-theme.scssprojects/element-theme/src/styles/components/_markdown.scssprojects/element-theme/src/styles/variables/_semantic-tokens.scssprojects/element-theme/src/theme/_theme-element.scsssrc/app/examples/si-chat-messages/si-ai-chat-container.htmlsrc/app/examples/si-chat-messages/si-ai-chat-container.tssrc/app/examples/si-chat-messages/si-ai-message.tssrc/app/examples/si-chat-messages/si-ai-welcome-screen.htmlsrc/app/examples/si-chat-messages/si-ai-welcome-screen.tssrc/app/examples/si-chat-messages/si-chat-container.htmlsrc/app/examples/si-chat-messages/si-chat-container.tssrc/app/examples/si-chat-messages/si-chat-input.htmlsrc/app/examples/si-chat-messages/si-tool-message.htmlsrc/app/examples/si-chat-messages/si-tool-message.tssrc/app/examples/si-chat-messages/si-user-message.tssrc/app/examples/si-markdown-renderer/si-markdown-renderer.htmlsrc/app/examples/si-markdown-renderer/si-markdown-renderer.tssrc/assets/sample-markdown.mdsrc/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.htmlprojects/element-ng/chat-messages/si-ai-message.component.spec.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-chat-container.component.tsprojects/element-ng/chat-messages/si-user-message.component.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/app/examples/si-chat-messages/si-chat-container.tsprojects/element-ng/chat-messages/si-tool-message.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scsssrc/app/examples/si-chat-messages/si-tool-message.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/chat-message.model.tsprojects/element-ng/chat-messages/si-chat-message.component.scsssrc/app/examples/si-chat-messages/si-ai-chat-container.htmlprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlsrc/app/examples/si-chat-messages/si-chat-container.htmlprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-chat-input.component.tsprojects/element-ng/chat-messages/si-user-message.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.tssrc/app/examples/si-chat-messages/si-ai-chat-container.tsprojects/element-ng/chat-messages/si-ai-message.component.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/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.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsplaywright/e2e/element-examples/static.spec.tsprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/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.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-chat-container.component.tssrc/app/examples/si-markdown-renderer/si-markdown-renderer.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.tsprojects/element-ng/chat-messages/si-user-message.component.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/translate/si-translatable-keys.interface.tssrc/app/examples/si-chat-messages/si-chat-container.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tssrc/app/examples/si-chat-messages/si-tool-message.tsplaywright/e2e/element-examples/static.spec.tsprojects/element-ng/markdown-renderer/markdown-renderer-helpers.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/chat-message.model.tssrc/app/examples/si-chat-messages/si-user-message.tssrc/app/examples/si-chat-messages/si-ai-message.tssrc/app/examples/si-chat-messages/si-ai-welcome-screen.tsprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/element-ng/markdown-renderer/markdown-renderer.tsprojects/element-ng/chat-messages/si-chat-input.component.tsprojects/element-ng/chat-messages/si-user-message.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.tssrc/app/examples/si-chat-messages/si-ai-chat-container.tsprojects/element-ng/chat-messages/si-ai-message.component.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.tsprojects/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.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/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.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tssrc/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.htmlprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/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.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/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.tsprojects/element-ng/chat-messages/si-tool-message.component.spec.tssrc/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.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yamlplaywright/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.tsprojects/element-ng/chat-messages/si-chat-container.component.tssrc/app/examples/si-chat-messages/si-chat-input.htmlprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/app/examples/si-chat-messages/si-chat-container.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/chat-message.model.tssrc/app/examples/si-chat-messages/si-ai-chat-container.htmlprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlsrc/app/examples/si-chat-messages/si-chat-container.htmlprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-chat-input.component.tsprojects/element-ng/chat-messages/si-tool-message.component.tssrc/app/examples/si-chat-messages/si-ai-chat-container.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/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.tssrc/app/examples/si-chat-messages/si-chat-container.tssrc/app/examples/si-chat-messages/si-tool-message.tssrc/app/examples/si-chat-messages/si-user-message.tssrc/app/examples/si-chat-messages/si-ai-message.tssrc/app/examples/si-chat-messages/si-ai-welcome-screen.tssrc/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.tsprojects/element-ng/translate/si-translatable-keys.interface.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/element-ng/chat-messages/si-tool-message.component.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/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.tsprojects/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.tsprojects/element-ng/chat-messages/si-tool-message.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/chat-messages/chat-message.model.tsprojects/element-ng/chat-messages/si-chat-message.component.scsssrc/app/examples/si-chat-messages/si-ai-chat-container.htmlsrc/app/examples/si-chat-messages/si-chat-container.htmlprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/chat-messages/si-ai-message.component.tsapi-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.tsprojects/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.tsprojects/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.scssprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/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.yamlplaywright/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.scssprojects/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.mdplaywright/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
| beforeEach(async () => { | ||
| await TestBed.configureTestingModule({ | ||
| imports: [SiAiWelcomeScreenComponent] | ||
| }).compileComponents(); |
There was a problem hiding this comment.
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.
| 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.
| 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'); |
There was a problem hiding this comment.
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').
| export interface PromptCategory { | ||
| label: string; | ||
| } | ||
|
|
||
| export interface PromptSuggestion { | ||
| text: string; | ||
| } |
There was a problem hiding this comment.
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.
| ::ng-deep &:not(:has(si-ai-welcome-screen)) { | ||
| max-inline-size: 720px; | ||
| } | ||
|
|
||
| ::ng-deep &:has(si-ai-welcome-screen) { | ||
| inline-size: 100%; | ||
| } |
There was a problem hiding this comment.
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.
| ::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.
| const orderIndex = cacheOrder.indexOf(key); | ||
| if (orderIndex > -1) { | ||
| cacheOrder.splice(orderIndex, 1); | ||
| } | ||
| cacheOrder.push(key); |
There was a problem hiding this comment.
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.
| 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; | ||
| }; |
There was a problem hiding this comment.
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.
| // 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'); | ||
| }); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
60b0a60 to
252d106
Compare
There was a problem hiding this 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()returnstruewhen 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 whencreateHtml()returns empty or text-only content.
tempDiv.firstElementChildcan benullifcreateHtml()returns an empty string or text-only content without element nodes. The type assertionas HTMLElementmasks 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-btnelement but never removed. When the returneddivis 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-deeppseudo-class.The
::ng-deepis 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-deepfrom messages-container selectors.The
:has()pseudo-class already checks for descendant elements, so::ng-deepis 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 $indexcan cause unnecessary re-renders if categories are reordered.src/app/examples/si-chat-messages/si-ai-welcome-screen.ts (1)
21-28: Potential mismatch betweenselectedCategoryand category labels.This concern was raised in a previous review -
selectedCategoryis initialized to'all'but the categories array uses{ label: 'All prompts' }, causing a mismatch sinceonCategoryClickuses the label property.projects/element-ng/chat-messages/si-ai-welcome-screen.component.ts (1)
11-17: Consider adding anidfield toPromptCategory.The JSDoc at line 52-53 references "category ID" but the interface only has
label. The component useslabelas 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:filteredPromptSuggestionsdoes not update whenselectedCategorychanges.The signal is initialized statically with
allPromptSuggestionsbut never reacts to category selection. If filtering is intended, use acomputedsignal.🔎 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; preferisSignalfrom Angular core.The check
typeof data === 'function' && 'call' in datais unreliable since all functions have acallproperty. Use Angular'sisSignal()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()readsthis.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 | undefinedmatches 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:sendingandinterruptibleno longer coerce non-boolean values.This was previously flagged. The change from
input(false, { transform: booleanAttribute })tomodel(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
actioncallback usesanyfor its first parameter. This was previously flagged—consider usingunknownfor better type safety.src/app/examples/si-chat-messages/si-ai-chat-container.ts (2)
255-259: Loose typing onmessagesSignalparameter.This was previously flagged. Using
anyloses type safety. ConsiderWritableSignal<ChatMessage[]>for better documentation in example code.
262-279: NestedsetTimeoutcalls lack cleanup on component destroy.This was previously flagged. If the component is destroyed mid-simulation, these timeouts will still fire. Consider adding
ngOnDestroyfor lifecycle cleanup, or add a comment noting this simplification.projects/element-ng/chat-messages/si-ai-chat-container.component.ts (2)
110-116:messageVersionsWeakMap is never updated, breaking cache invalidation.This was previously flagged. The
messageVersions.get()on line 408 always returnsundefined(defaulting to0) sincemessageVersions.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 ingetContentValuereturns empty string for falsy content.The function returns
'' as Twhen content is falsy, butTcould beobject. 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.
projects/element-ng/chat-messages/si-ai-chat-container.component.ts
Outdated
Show resolved
Hide resolved
| <button si-action-card type="button" class="w-100" (click)="onPromptClick(suggestion)"> | ||
| <div body class="card-body card-text text-white"> | ||
| {{ suggestion.text }} | ||
| </div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 2Repository: 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 -30Repository: 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 -40Repository: 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 -20Repository: siemens/element
Length of output: 713
🏁 Script executed:
# Read the si-action-card component implementation
cat ./projects/element-ng/card/si-action-card.component.tsRepository: siemens/element
Length of output: 2079
🏁 Script executed:
# Read the si-action-card component template
cat ./projects/element-ng/card/si-action-card.component.htmlRepository: 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.scssRepository: 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 -50Repository: siemens/element
Length of output: 4751
🏁 Script executed:
# Read the si-card.component.scss file
cat ./projects/element-ng/card/si-card.component.scssRepository: 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 -200Repository: 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 -100Repository: 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 -50Repository: 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.tsRepository: 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 -20Repository: 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 -30Repository: 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 -20Repository: 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.scssRepository: siemens/element
Length of output: 866
🏁 Script executed:
# Check the full card styling including default background
cat ./projects/element-theme/src/styles/bootstrap/_card.scssRepository: 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 -40Repository: 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 -20Repository: 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 -30Repository: 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.
projects/element-ng/chat-messages/si-attachment-list.component.ts
Outdated
Show resolved
Hide resolved
| // Add temporary closing backticks at the end to handle incomplete code blocks during streaming | ||
| const tempClosingMarker = `\n\`\`\`--TEMP-CLOSE--\n`; | ||
| html = html + tempClosingMarker; |
There was a problem hiding this comment.
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.
| <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" | ||
| > |
There was a problem hiding this comment.
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.
| ## Images | ||
|
|
||
| Images can be included as follows: | ||
|
|
||
|  | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 -30Repository: 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.
|
Documentation. Coverage Reports: |
252d106 to
33d9fb0
Compare
There was a problem hiding this 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 $indexoptimization (considertrack category.label) and thetext-whitecontrast 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:
- Line 89: The fixed height requirement phrasing could be clearer
- Lines 95-97: The relationship between "built-in" and "slotted" is ambiguous
Please address the previous review suggestions to clarify whether
si-ai-welcome-screenis 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-cancelclass 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:messageVersionsWeakMap is never updated, preventing cache invalidation.The caching mechanism retrieves a version from
messageVersions(line 421) but never callsmessageVersions.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
⛔ 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.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-light-linux.pngis excluded by!**/*.png
📒 Files selected for processing (12)
api-goldens/element-ng/chat-messages/index.api.mdapi-goldens/element-ng/translate/index.api.mddocs/patterns/ai/ai-chat.mdplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yamlprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/translate/si-translatable-keys.interface.tssrc/app/examples/si-chat-messages/si-ai-chat-container.htmlsrc/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.htmlprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tssrc/app/examples/si-chat-messages/si-ai-chat-container.htmlprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlsrc/app/examples/si-chat-messages/si-ai-chat-container.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/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.htmlprojects/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.htmlprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tssrc/app/examples/si-chat-messages/si-ai-chat-container.htmlprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlsrc/app/examples/si-chat-messages/si-ai-chat-container.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/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.tssrc/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.tssrc/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.tssrc/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.tssrc/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.tssrc/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/translate/si-translatable-keys.interface.tssrc/app/examples/si-chat-messages/si-ai-chat-container.tsprojects/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.mdapi-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.mdapi-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.mdapi-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.htmlapi-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.tsapi-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.ACTIONnaming 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
filteredPromptSuggestionscomputed property correctly handles both input types:
- Returns array as-is when
promptSuggestionsis 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 messagefor object identity tracking (per project guidelines)- Uses nested
@ifblocks instead of@switchfor 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 testingprovideNoopAnimations()for animation handling- Standard
TestBed.configureTestingModulepatternThis 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 unnecessarycontentproperty from tool message test.The
contentproperty is optional in theToolChatMessageinterface (inherited fromBaseChatMessage), so thecontent: ''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
messagesSignaltyping issue from previous reviews has been resolved (line 256). The nestedsetTimeoutcalls insimulateAiResponse(lines 280-297) lack lifecycle cleanup, but this simplification is acceptable for demonstration purposes.
| <p class="h1 mb-0 text-white"> | ||
| <strong>{{ greeting() | translate }}</strong> | ||
| </p> | ||
| <p class="h1 mb-0 text-white">{{ welcomeMessage() | translate }}</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| <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.
ff44574 to
6ec8dde
Compare
There was a problem hiding this 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-deepfrom 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-deepto 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-deepfrom messages-container selectors.Same issue as above:
::ng-deepbefore&: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-deepis 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-cancelclass. 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. Considertrack category.labelfor more stable tracking, assuming labels are unique.
25-25: Replace hardcodedtext-whitewith theme-aware text color.The
text-whiteclass creates poor contrast in light themes where the action card background is light. Remove thetext-whiteclass 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 $indexfor suggestions can cause unnecessary re-renders if the array is reordered. If suggestions have a unique identifier (e.g.,idortext), consider tracking by that property instead.projects/element-ng/chat-messages/si-ai-chat-container.component.html (1)
10-13: Replace hardcodedtext-whitewith theme-aware text color.The hardcoded
text-whiteclass 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-deepfor child component styling.While
::ng-deepis 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-deepfor collapsible panel styling.Similar to the spinner styling,
::ng-deepis 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()returnstruewhen 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 betweenselectedCategoryand category labels.The
selectedCategorysignal is initialized to'all', butpromptCategoriescontains{ label: 'All prompts' }. SinceonCategoryClick(in the component being demonstrated) setsselectedCategoryusing the category'slabelproperty, 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
promptSuggestionsuses a flat array format, which doesn't showcase theSiAiWelcomeScreenComponent's category filtering feature. Consider using theRecord<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:
- Testing the observable effects these signals drive (e.g., input component state, UI elements)
- 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 anidfield toPromptCategory.The
PromptCategoryinterface useslabelfor both display and identification. As noted in the past review, the example code showsselectedCategoryinitialized 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
divis removed from the DOM, the buttons and their listeners become unreachable and will be garbage collected. Event delegation on the containerdivwould 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:filteredPromptSuggestionsremains static despiteselectedCategorychanges.As noted in the past review,
filteredPromptSuggestionsis initialized with all suggestions but never updates whenselectedCategorychanges. If category-based filtering is intended for this demo, consider using acomputedsignal. 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; preferisSignalfrom Angular core.As noted in the past review, the check
typeof data === 'function' && 'call' in datais unreliable since all functions have acallproperty. Angular providesisSignal()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()invokesthis.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:getLoadingStatecontains 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 ingetOutputValue.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 onmessagesSignalparameter; considerWritableSignal<ChatMessage[]>.As noted in the past review, using
anyloses type safety. Since this is example code demonstrating proper usage patterns, stronger typing would serve as better documentation.
280-297: NestedsetTimeoutcalls 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
ngOnDestroyfor 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:sendingandinterruptibleno longer coerce non-boolean values.As noted in the past review, changing from
input(false, { transform: booleanAttribute })tomodel(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]messageVersionsWeakMap 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.
| // 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; | ||
| } |
There was a problem hiding this comment.
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.
| 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; | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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
- highlightjs.org — Usage / import core & languages.
- highlight.js GitHub README — CDN assets, ES module examples, importmap.
- 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 -50Repository: 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.
|
@Killusions Love iiiiit! I have only two points:
When there is no space, the summary chips should stack:
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:
|
Don't worry it's just rebased on top, I won't merge it before this one. |
6ec8dde to
177e1e8
Compare
There was a problem hiding this 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
⛔ Files ignored due to path filters (7)
package-lock.jsonis excluded by!**/package-lock.jsonplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-light-linux.pngis excluded by!**/*.png
📒 Files selected for processing (31)
.npmrcapi-goldens/element-ng/chat-messages/index.api.mdapi-goldens/element-ng/translate/index.api.mddocs/patterns/ai/ai-chat.mdpackage.jsonplaywright/e2e/element-examples/static.spec.tsplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yamlprojects/dashboards-demo/src/styles.scssprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/style-mappings.tsprojects/element-ng/translate/si-translatable-keys.interface.tsprojects/element-theme/src/styles/variables/_semantic-tokens.scssprojects/element-theme/src/theme/_theme-element.scsssrc/app/examples/si-chat-messages/si-ai-chat-container.htmlsrc/app/examples/si-chat-messages/si-ai-chat-container.tssrc/app/examples/si-chat-messages/si-ai-welcome-screen.htmlsrc/app/examples/si-chat-messages/si-ai-welcome-screen.tssrc/app/examples/si-chat-messages/si-chat-container.htmlsrc/app/examples/si-chat-messages/si-chat-container.tssrc/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.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yamlplaywright/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/translate/si-translatable-keys.interface.tsapi-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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/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.tsplaywright/e2e/element-examples/static.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/app/examples/si-chat-messages/si-ai-welcome-screen.tssrc/app/examples/si-chat-messages/si-ai-chat-container.tsprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tssrc/app/examples/si-chat-messages/si-chat-container.tsprojects/element-ng/translate/si-translatable-keys.interface.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/translate/si-translatable-keys.interface.tsprojects/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.scsssrc/app/examples/si-chat-messages/si-chat-container.htmlsrc/app/examples/si-chat-messages/si-ai-chat-container.htmlprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/si-chat-container.component.scssapi-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.scsssrc/app/examples/si-chat-messages/si-chat-container.htmlsrc/app/examples/si-chat-messages/si-ai-chat-container.htmlprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/app/examples/si-chat-messages/si-ai-welcome-screen.htmlprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlsrc/app/examples/si-chat-messages/si-ai-chat-container.tsprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tssrc/app/examples/si-chat-messages/si-chat-container.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/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.scssprojects/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.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tsprojects/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:
.npmrcprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tssrc/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.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/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.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/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.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/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.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/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.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/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.tsprojects/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.tsprojects/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.tsprojects/element-ng/schematics/scss-import-to-siemens-migration/index.spec.tssrc/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.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tssrc/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.htmlsrc/app/examples/si-chat-messages/si-ai-chat-container.htmlprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlsrc/app/examples/si-chat-messages/si-ai-chat-container.tsprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tssrc/app/examples/si-chat-messages/si-chat-container.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/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.htmlprojects/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.htmlprojects/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.htmlprojects/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.tssrc/app/examples/si-chat-messages/si-ai-chat-container.tssrc/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.tssrc/app/examples/si-chat-messages/si-ai-chat-container.tssrc/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.mdapi-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.mdapi-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.mdapi-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.tshave 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/brandpackage is already declared in the rootpackage.jsonwith version2.3.0, and the.npmrcis correctly configured with the@linusregistry pointing to the Siemens NPM registry. The migration from@simpl/brandto@linus/brandis 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. Thecolor-contrastandlink-in-text-blockrule suppressions are appropriate for this component.SiMarkdownRendererComponentis a content renderer that transforms user-provided markdown input into HTML. Thelink-in-text-blocksuppression reflects the intended behavior of rendered markdown links, and thecolor-contrastsuppression 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
#chatContainerenables 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-visualis correctly defined in_semantic-tokens.scss:190with appropriate theme-specific values in_theme-element.scss(black SVG in light theme, white SVG in dark theme). The componentsi-ai-welcome-screen.component.scssproperly consumes the token viabackground-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
:hostselector (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 forcategoriesandpromptSuggestions, and event binding forpromptSelectedalign 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:
- Removing the async/await pattern in the beforeEach (lines 14-18)
- 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-containerwith appropriate bindings for status, messages, loading states, and configurationssi-chat-inputproperly 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-cancelclass 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-visualtoken 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-deepselector.The deprecated
::ng-deepselector 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
SiResponsiveContainerDirectiveviahostDirectives, which automatically applies thesi-container-*classes. Thevariables.$element-ai-key-visualis properly defined as an SVG in the theme files. The::beforepseudo-element should only be hidden on xs and sm breakpoints and should display at larger sizes (md, lg, xl, xxl).However, the absolutely-positioned
::beforeextends 104px to the left (inset-inline-start: -104px). Verify that:
- The component's parent container doesn't have
overflow: hiddenor 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 hardcodedtext-whitewith a theme-aware text color.The hardcoded
text-whiteclass creates poor contrast in light themes where the action card background uses a light experimental blue color. Replace withtext-primaryor 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 $indexcan cause unnecessary re-renders when the categories array is reordered. Consider tracking by a stable property such ascategory.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:promptSuggestionssignal doesn't leverage category filtering.The component has
promptCategoriesdefined butpromptSuggestionsis a flat array. To demonstrate the category filtering feature ofSiAiWelcomeScreenComponent, consider using theRecord<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 anidfield toPromptCategoryfor better separation of concerns.The
PromptCategoryinterface only has alabelfield, which is used both for display and as the selection identifier. This creates confusion (as seen in example code whereselectedCategoryis initialized to'all'but categories use'All prompts'). Consider adding an optionalidfield 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-whiteclass 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
onPromptSelectedhandler 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/ | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 5Repository: 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.
| 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); | ||
| }); |
There was a problem hiding this comment.
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:
- Exposing these as public for testing if they represent important component behavior
- 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.
| > div:first-child { | ||
| flex-wrap: wrap; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| } @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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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.scssRepository: 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.
177e1e8 to
2d1237b
Compare
There was a problem hiding this 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
⛔ Files ignored due to path filters (13)
package-lock.jsonis excluded by!**/package-lock.jsonplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-user-message-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-user-message-element-examples-chromium-light-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-dark-linux.pngis excluded by!**/*.pngplaywright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer-element-examples-chromium-light-linux.pngis excluded by!**/*.png
📒 Files selected for processing (47)
angular.jsonapi-goldens/element-ng/chat-messages/index.api.mdapi-goldens/element-ng/markdown-renderer/index.api.mdapi-goldens/element-ng/translate/index.api.mddocs/components/chat-messages/chat-message.mddocs/patterns/ai/ai-chat.mdpackage.jsonplaywright/e2e/element-examples/static.spec.tsplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-input.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-tool-message.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-user-message.yamlplaywright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yamlprojects/element-ng/chat-messages/chat-message.model.tsprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/message-action.model.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/si-ai-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-message.component.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-chat-container.component.tsprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/element-ng/chat-messages/si-chat-input.component.tsprojects/element-ng/chat-messages/si-chat-message.component.scssprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/element-ng/chat-messages/si-tool-message.component.scssprojects/element-ng/chat-messages/si-tool-message.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/chat-messages/si-user-message.component.spec.tsprojects/element-ng/chat-messages/si-user-message.component.tsprojects/element-ng/link/si-link.directive.tsprojects/element-ng/markdown-renderer/markdown-renderer-helpers.tsprojects/element-ng/markdown-renderer/markdown-renderer.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-message.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/chat-messages/si-ai-chat-container.component.htmlprojects/element-ng/chat-messages/si-chat-container.component.tsprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/element-ng/chat-messages/si-ai-message.component.tsprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/element-ng/chat-messages/si-user-message.component.tsprojects/element-ng/chat-messages/si-chat-message.component.scssplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-user-message.yamlprojects/element-ng/chat-messages/index.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/element-ng/chat-messages/si-chat-input.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/chat-message.model.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/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.tsplaywright/e2e/element-examples/static.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/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.tsplaywright/e2e/element-examples/static.spec.tsprojects/element-ng/chat-messages/si-ai-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/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.tsplaywright/e2e/element-examples/static.spec.tsprojects/element-ng/chat-messages/si-ai-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/chat-messages/si-chat-container.component.tsprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.tsprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/element-ng/chat-messages/si-ai-message.component.tsprojects/element-ng/chat-messages/si-user-message.component.tsprojects/element-ng/markdown-renderer/markdown-renderer.tsprojects/element-ng/markdown-renderer/markdown-renderer-helpers.tsprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/si-chat-input.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/chat-message.model.tsprojects/element-ng/translate/si-translatable-keys.interface.tsprojects/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.tsprojects/element-ng/chat-messages/si-ai-message.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.spec.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.spec.tsprojects/element-ng/chat-messages/si-chat-container.component.tsprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/si-attachment-list.component.spec.tsprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.tsprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/element-ng/chat-messages/si-ai-message.component.tsprojects/element-ng/chat-messages/si-user-message.component.tsprojects/element-ng/markdown-renderer/markdown-renderer.tsprojects/element-ng/markdown-renderer/markdown-renderer-helpers.tsprojects/element-ng/chat-messages/index.tsprojects/element-ng/chat-messages/si-chat-input.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/element-ng/chat-messages/chat-message.model.tsprojects/element-ng/translate/si-translatable-keys.interface.tsprojects/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.mddocs/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.tsprojects/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.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/chat-messages/si-ai-message.component.tsprojects/element-ng/chat-messages/si-user-message.component.tsprojects/element-ng/chat-messages/si-chat-message.component.scssprojects/element-ng/chat-messages/index.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/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.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/markdown-renderer/si-markdown-renderer.component.tsprojects/element-ng/chat-messages/si-tool-message.component.htmlapi-goldens/element-ng/chat-messages/index.api.mdprojects/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.scssprojects/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.scssprojects/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.htmlprojects/element-ng/chat-messages/si-chat-container.component.tsprojects/element-ng/chat-messages/si-chat-message.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.spec.tsprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/element-ng/chat-messages/si-attachment-list.component.tsprojects/element-ng/chat-messages/si-chat-container.component.scssprojects/element-ng/chat-messages/si-ai-welcome-screen.component.tsprojects/element-ng/chat-messages/si-tool-message.component.tsprojects/element-ng/chat-messages/si-chat-input.component.spec.tsprojects/element-ng/chat-messages/si-ai-message.component.tsprojects/element-ng/chat-messages/si-tool-message.component.htmlprojects/element-ng/chat-messages/si-user-message.component.tsprojects/element-ng/chat-messages/index.tsapi-goldens/element-ng/chat-messages/index.api.mdprojects/element-ng/chat-messages/si-chat-input.component.tsprojects/element-ng/chat-messages/si-ai-chat-container.component.tsprojects/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.htmlprojects/element-ng/chat-messages/si-ai-welcome-screen.component.htmlprojects/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.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-chat-container.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-ai-welcome-screen.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-chat-container.yamlplaywright/snapshots/static.spec.ts-snapshots/si-markdown-renderer--si-markdown-renderer.yamlplaywright/snapshots/static.spec.ts-snapshots/si-chat-messages--si-user-message.yamlplaywright/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.tsapi-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.mdapi-goldens/element-ng/chat-messages/index.api.mdapi-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.mdapi-goldens/element-ng/chat-messages/index.api.mdapi-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.mdapi-goldens/element-ng/chat-messages/index.api.mdapi-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.yamlplaywright/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 |
There was a problem hiding this comment.
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 messageThis 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.
| ## 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.
| export interface TemplateChatMessage { | ||
| /** | ||
| * Template to render the message | ||
| */ | ||
| template: TemplateRef<any>; | ||
|
|
||
| /** Context data to pass to the template */ | ||
| templateContext?: any; | ||
| } |
There was a problem hiding this comment.
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.
| 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.
| 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; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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; | ||
| } |
There was a problem hiding this comment.
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.
| 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).
| .message-wrapper { | ||
| min-inline-size: 0; | ||
| max-inline-size: 100%; | ||
| } |
There was a problem hiding this comment.
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.
| 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); | ||
| } | ||
| } |
There was a problem hiding this comment.
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.jsonRepository: 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 -5Repository: siemens/element
Length of output: 67
🏁 Script executed:
cat -n "projects/element-ng/chat-messages/si-tool-message.component.ts" | head -20Repository: 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.
| 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.
| 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; | ||
| } |
There was a problem hiding this comment.
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.
| 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.
| const tempDiv = document.createElement('div'); | ||
| tempDiv.innerHTML = createHtml(); | ||
| const element = tempDiv.firstElementChild as HTMLElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| // 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'); | ||
| }); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
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.
2d1237b to
7edff83
Compare
…markdown renderer
…ulti-line formulas
fcde13b to
ef0b805
Compare
ef0b805 to
415d82f
Compare






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
Models & types
Markdown renderer
Other notable changes
Notes / open items