Skip to content

feat(ui): Toast Notification History & Server Logs Enhancements#278

Open
bluelovers wants to merge 10 commits intoNeuralNomadsAI:devfrom
bluelovers:pr/pr-003-toast-notification-history
Open

feat(ui): Toast Notification History & Server Logs Enhancements#278
bluelovers wants to merge 10 commits intoNeuralNomadsAI:devfrom
bluelovers:pr/pr-003-toast-notification-history

Conversation

@bluelovers
Copy link
Copy Markdown
Contributor

@bluelovers bluelovers commented Apr 2, 2026

PR: Enhance UI with Toast Notification History & Server Logs Improvements

中文摘要 (Chinese Summary)

功能概述

本 PR 包含兩個 UI 增強功能:通知歷史面板伺服器日誌改進

功能一:通知歷史面板 (Toast Notification History)

  • 新增 ToastHistoryPanel 組件,顯示所有 Toast 通知的歷史記錄
  • 支援按類型(info/success/warning/error)篩選
  • 支援時間分組(今日/昨日/更早)
  • 支援清除全部、標記已讀、刪除單項
  • 最多保留 50 筆歷史記錄

功能二:伺服器日誌改進 (Server Logs Enhancements)

  • 新增清除日誌按鈕(垃圾桶圖標)
  • 新增返回對話按鈕(箭頭圖標,位於日誌工具列)
  • 新增浮動向上/向下滾動按鈕(圓形小球,與對話介面一致)
  • 滾動按鈕根據位置自動顯示/隱藏
  • 滾動按鈕狀態會隨日誌變化自動同步

English Summary

Overview

This PR introduces two UI enhancements: Toast Notification History Panel and Server Logs Improvements.

Feature 1: Toast Notification History Panel

  • New ToastHistoryPanel component displays all toast notification history
  • Filter by variant type (info/success/warning/error)
  • Time grouping (Today/Yesterday/Earlier)
  • Clear all, mark as read, delete individual items
  • Maximum 50 history records retained

Feature 2: Server Logs Enhancements

  • Clear logs button with Trash2 icon
  • Back to conversation button with ArrowLeft icon (in logs toolbar)
  • Floating scroll-to-top/scroll-to-bottom buttons (circular, consistent with message section)
  • Auto show/hide based on scroll position
  • Scroll button state syncs automatically with log changes

@bluelovers bluelovers changed the base branch from main to dev April 2, 2026 17:42
@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 2, 2026

@CodeNomadBot

I want you to perform the gatekeeper checks for latest PR state

check for regressions
check for better possible implementations
Be the PR gatekeeper
Be ruthless about code quality

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 2, 2026

@CodeNomadBot

Try again

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot bot commented Apr 2, 2026

Reviewed the latest PR state as a gatekeeper pass, focused on regressions and better implementation choices. Assumption: the active server logs UI is still packages/ui/src/components/info-view.tsx, because packages/ui/src/components/logs-view.tsx has no call sites in the current tree.

Findings

  1. High: the 100-item history cap drops the newest toast instead of the oldest one.
    In packages/ui/src/lib/notifications.tsx:105-109, _trimHistory() uses _historyItems.slice(-MAX_HISTORY_ITEMS). But new items are inserted with unshift() at packages/ui/src/lib/notifications.tsx:132, so the array is newest-first. Once the list reaches 101 items, slice(-100) keeps the oldest 100 and discards the brand-new notification that was just added. That makes the history unreliable exactly at the limit.

  2. High: the unread badge in the tab bar is not reactive, so it will not update when history changes.
    packages/ui/src/components/instance-tabs.tsx:37-39 computes unreadCount as createMemo(() => getUnreadToastCount()), but getUnreadToastCount() in packages/ui/src/lib/notifications.tsx:231-233 reads plain module state, not a Solid signal/store. That memo has no reactive dependency, so the badge rendered at packages/ui/src/components/instance-tabs.tsx:103-109 will stay stale after new toasts arrive, after marking items read, and after clearing history.

  3. High: the server-logs enhancements appear to be implemented in an unused component, so the feature is likely not reachable in the real UI.
    This PR modifies packages/ui/src/components/logs-view.tsx, but a repo-wide search shows no imports or usages of that component. The active logs panel is still implemented in packages/ui/src/components/info-view.tsx:93-155, and that file was not changed in this PR. As written, the new clear button, back button, and floating scroll controls are very likely invisible to users.

  4. Medium: scroll button visibility is never initialized or resynced from content changes.
    In packages/ui/src/components/logs-view.tsx:71-95, updateScrollButtons() is only called from handleScroll(). There is no call on mount, after restoring cached scroll position, after logs are cleared, or when new logs change overflow. Even if this component were wired up, the top/bottom buttons can start in the wrong state and stay stale until the user scrolls manually.

Verification notes

  • I was not able to complete a clean local typecheck/build in this workspace because dependencies are not installed here (solid-js, vite, etc. are missing), so this review is based on code inspection and repo search rather than a full runtime verification pass.

Non-blocking suggestions

  • packages/ui/src/styles/components/toast-history.css is now about 507 lines, which is over the repo’s style-file warning threshold called out in AGENTS.md. I would not block on size alone, but it is a refactor signal.
  • There is some dead/unused code in the new implementation (historyId in notifications.tsx, unused imports in logs-view.tsx, unused imports in toast-history-panel.tsx). Not release-critical, but worth cleaning once the functional issues above are fixed.

--
Yours,
CodeNomadBot

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 3, 2026

@bluelovers - Please review the findings and improve

- Add toast history store with in-memory storage (max 100 items)
- Implement ToastHistoryPanel component with filtering, grouping, and delete
- Add unread badge indicator on notification bell button
- Integrate history panel with ESC/click-outside dismiss
- Add i18n translations for 7 languages (en, zh-Hans, ja, fr, es, ru, he)
- Refactor notification button to show history instead of settings
- Add clear logs button with Trash2 icon
- Add optional back to conversation button with ArrowLeft icon
- Add floating scroll-to-top/scroll-to-bottom buttons
- Style scroll buttons consistent with message section
- Add i18n translations for 7 languages
@bluelovers bluelovers force-pushed the pr/pr-003-toast-notification-history branch from acf744c to bd9ea2d Compare April 3, 2026 05:14
@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 3, 2026

@CodeNomadBot

Do your thing again

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot bot commented Apr 3, 2026

Fresh gatekeeper pass on the latest PR state. Assumptions: I reviewed the branch as it exists now against origin/dev, and I treated packages/ui/src/components/info-view.tsx as the active server-logs UI because the old logs-view.tsx implementation has effectively been removed from use.

Findings

  1. High: the + new-tab/new-instance action has been removed from the tab bar.
    In packages/ui/src/components/instance-tabs.tsx:15-20, the component still accepts an onNew callback, and App.tsx still passes it. But in the rendered tab strip (packages/ui/src/components/instance-tabs.tsx:47-124), there is no button invoking props.onNew() anymore. The previous implementation had a Plus button there. This is a direct user-facing regression: the primary way to create a new instance from the top tab bar is gone.

  2. Medium: the legacy bottom CTA is still rendered alongside the new floating scroll controls, and it no longer has any matching style definition.
    packages/ui/src/components/info-view.tsx:192-200 still renders the old scroll-to-bottom button, while packages/ui/src/components/info-view.tsx:202-232 now also renders the new floating up/down controls. I could not find any scroll-to-bottom CSS rule in packages/ui/src/styles, so this leaves you with duplicate controls and one of them likely rendered as an unstyled native button.

  3. Medium: the floating scroll-button state is still not kept in sync with log-content changes.
    In packages/ui/src/components/info-view.tsx:53-67, button visibility is derived in updateScrollButtons(), but that function is only called on mount and from handleScroll() (packages/ui/src/components/info-view.tsx:77-84). It is not called when logs are appended, when logs are cleared, or after scrollToTop() / scrollToBottom() mutate the scroll position programmatically. Result: the button visibility can stay stale until the user manually scrolls again.

  4. Medium: the toast history capacity changed from the documented 100 items to 50 items.
    packages/ui/src/lib/notifications.tsx:71 now sets MAX_HISTORY_ITEMS = 50, but the PR description still says the feature stores up to 100 records. If 50 is intentional, the PR description needs updating; if not, this is a functional regression relative to the stated behavior.

What improved since the last pass

  • The previous newest-item trimming bug is fixed: packages/ui/src/lib/notifications.tsx:133-137 now keeps the newest entries correctly.
  • The unread badge is now reactive via getUnreadToastCountSignal() and packages/ui/src/components/instance-tabs.tsx:37-38.
  • The server-log changes are now applied in info-view.tsx, which resolves the earlier issue where the work was done in an apparently unused component.

Non-blocking suggestions

  • packages/ui/src/components/toast-history-panel.tsx still imports getToastHistory and getToastVariantClasses without using them.
  • packages/ui/src/styles/components/toast-history.css is about 507 lines, which is above the repo’s style-file warning threshold in AGENTS.md. Not a blocker by itself, but worth splitting later.

I did not rely on local build/typecheck results for this pass because the workspace still does not have the UI dependencies installed (vite, solid-js, etc.), so this review is based on current code inspection and repo search.

--
Yours,
CodeNomadBot

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 3, 2026

@CodeNomadBot

Do your thing again

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot bot commented Apr 3, 2026

Fresh gatekeeper pass on the latest PR state. Assumptions: I reviewed the current branch against origin/dev, and I evaluated the shipped behavior from the active UI components (instance-tabs.tsx and info-view.tsx) rather than the earlier superseded logs-view.tsx work.

Findings

  1. Medium: the PR still claims a server-logs back button feature that is not present in the actual UI.
    The PR description says this change adds a back button and even documents a new onBackToConversation?: () => void prop on LogsViewProps. But the active logs UI is in packages/ui/src/components/info-view.tsx, and there is no back button there now. I also do not see any corresponding i18n key such as infoView.logs.actions.back. If the feature was intentionally dropped, the PR description should be updated; if not, the implementation is still incomplete relative to what this PR claims to deliver.

  2. Medium: the toast history capacity still conflicts with the documented behavior.
    packages/ui/src/lib/notifications.tsx:71 sets MAX_HISTORY_ITEMS = 50, while the PR body says the feature stores up to 100 history records. This is either a behavior regression relative to the stated scope or an inaccurate PR description. Either way, it should be reconciled before merge.

What improved since the last pass

  • The new-instance + tab button is back in packages/ui/src/components/instance-tabs.tsx:74-81.
  • The old duplicate bottom scroll-to-bottom CTA has been removed from info-view.tsx.
  • Scroll-button visibility is now updated on log changes, clear, and programmatic scroll actions in packages/ui/src/components/info-view.tsx:27-30, 56-60, 79-84, and 96-101.
  • The unused imports previously noted in toast-history-panel.tsx have been cleaned up.

Non-blocking suggestion

  • packages/ui/src/styles/components/toast-history.css is still about 507 lines, which is above the style-file warning threshold in AGENTS.md. I would not block merge on that alone, but it is still a refactor signal.

I did not rely on local build/typecheck results for this pass because the workspace still does not have the UI dependencies installed (vite, solid-js, etc.), so this review is based on current code inspection and repo search.

--
Yours,
CodeNomadBot

- Add ArrowLeft back button in InfoView logs toolbar
- Add onBackToConversation optional prop to InfoViewProps
- Wire callback in instance-shell2 to return to last session
- Add i18n translations for 7 languages (en, zh-Hans, ja, fr, es, ru, he)
@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 3, 2026

@CodeNomadBot

I want you to perform the gatekeeper checks for latest PR state

check for regressions
check for better possible implementations
Be the PR gatekeeper
Be ruthless about code quality

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot bot commented Apr 3, 2026

Fresh gatekeeper pass on the latest PR state. Assumptions: I reviewed the current branch against origin/dev, and I treated packages/ui/src/components/info-view.tsx plus packages/ui/src/components/instance/instance-shell2.tsx as the active implementation for the server-logs feature.

Findings

  1. High: the new back-button change in info-view.tsx is malformed and appears to break the component.
    In packages/ui/src/components/info-view.tsx:144-166, there is a valid Show when={props.onBackToConversation} block, but it is immediately followed by a second malformed block under Show when={logs().length > 0} that renders another ArrowLeft button using onClick={onBack} even though onBack is not in scope there. The snippet also contains a stray )} without a matching render-function wrapper. This is not just a polish issue; it looks like a bad paste/merge that would leave the component in an invalid state and likely fail compilation or render incorrectly.

What improved since the last pass

  • The PR description now matches the MAX_HISTORY_ITEMS = 50 implementation.
  • The back-to-conversation feature is now actually wired from packages/ui/src/components/instance/instance-shell2.tsx:670-676 and passed into InfoView at packages/ui/src/components/instance/instance-shell2.tsx:913.
  • The tab-bar + button and log scroll-state sync fixes are still present.

Non-blocking suggestion

  • packages/ui/src/styles/components/toast-history.css is still about 507 lines, which is above the style-file warning threshold in AGENTS.md. I would not block merge on that alone, but it remains a refactor signal.

I did not rely on local build/typecheck output for this pass because the workspace still does not have the UI dependencies installed (vite, solid-js, etc.), but this particular finding is source-level and high-confidence from direct code inspection.

--
Yours,
CodeNomadBot

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 4, 2026

@CodeNomadBot

Do your thing again

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot bot commented Apr 4, 2026

Fresh gatekeeper pass on the latest PR state. Assumptions: I reviewed the current branch against origin/dev, and I treated packages/ui/src/components/info-view.tsx, packages/ui/src/components/instance/instance-shell2.tsx, and packages/ui/src/components/toast-history-panel.tsx as the active implementation.

Findings

  1. Medium: toast history rows are interactive with the mouse but not keyboard-accessible.
    In packages/ui/src/components/toast-history-panel.tsx:336-384, each history row is rendered as a plain <div class="toast-history-item" role="listitem" onClick={...}>. Clicking the row marks the item read and may open the action link, but the element is not focusable and has no keyboard handler. That means keyboard users cannot activate the primary row action at all. This should be a semantic <button>/<a>, or at minimum a focusable element with keyboard activation support.

  2. Medium: the filter controls use tab semantics, but they are not implemented as a tab interface.
    In packages/ui/src/components/toast-history-panel.tsx:293-310, the filter bar uses role="tablist" and each filter uses role="tab", but there are no corresponding tabpanel relationships, no aria-controls, and no tab-style keyboard navigation model. This is misleading for assistive technology and is the wrong semantic pattern for a simple filter toggle group. A better implementation would use ordinary buttons with aria-pressed for the active filter.

What improved since the last pass

  • The malformed duplicated back-button block in info-view.tsx is fixed.
  • The back-to-conversation wiring is present and localized in the active UI.
  • The earlier tab-bar and log-scroll regressions remain fixed.

Non-blocking suggestion

  • packages/ui/src/lib/notifications.tsx:436-458 still exports getToastVariantLabel and getToastVariantClasses, but I do not see any current usage for either helper.
  • packages/ui/src/styles/components/toast-history.css is still about 507 lines, above the style-file warning threshold in AGENTS.md. Not a merge blocker by itself, but still a refactor signal.

I did not rely on local build/typecheck output for this pass because the workspace still does not have the UI dependencies installed (vite, solid-js, etc.), so this review is based on direct code inspection of the current branch.

--
Yours,
CodeNomadBot

- Replace layout/spacing/color CSS with Tailwind utility classes in TSX
- Keep only animations, color-mix, nested selectors, and responsive in CSS
- Fix filter semantics: use aria-pressed instead of role=tab/tablist
- Fix toast-history-item: change div to button for keyboard accessibility
- Remove unused exports: getToastVariantLabel, getToastVariantClasses
- CSS reduced from 512 to 204 lines (-60%)
@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 4, 2026

@CodeNomadBot

Do your thing

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot bot commented Apr 4, 2026

Fresh gatekeeper pass on the latest PR state. Assumptions: I reviewed the current branch against origin/dev, and I evaluated the shipped implementation in packages/ui/src/components/toast-history-panel.tsx, packages/ui/src/components/info-view.tsx, and related callers.

Findings

  1. Medium: each toast-history row is now a <button>, but it contains nested <button> elements for the action link and delete control.
    In packages/ui/src/components/toast-history-panel.tsx:349-397, the outer row is rendered as a <button> and inside it there is another <button> for the external action (370-382) and another <button> for delete (385-393). Nested interactive controls are invalid HTML and produce inconsistent browser/accessibility behavior. Even with stopPropagation(), this structure is still semantically broken and can lead to double-activation or unusable keyboard/screen-reader interaction. The row container needs to stop being a button, or the inner controls need to be restructured so there is only one interactive root.

What improved since the last pass

  • The previous mouse-only row interaction issue is fixed: the rows are now keyboard-focusable buttons.
  • The previous fake tab semantics on the filter controls are fixed: the filter buttons now use aria-pressed instead of tablist/tab roles.
  • The earlier back-button and scroll-state regressions remain fixed.

Non-blocking suggestion

  • packages/ui/src/lib/notifications.tsx still contains getToastVariantLabel / getToastVariantClasses, and I still do not see any current usage for them.

I did not rely on local build/typecheck output for this pass because the workspace still does not have the UI dependencies installed (vite, solid-js, etc.), but this finding is high-confidence from direct inspection of the current JSX structure.

--
Yours,
CodeNomadBot

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 10, 2026

@bluelovers - Check the review please

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants