From 1a39c5f7dc965709a55899d0e69d124c8708389f Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 18 May 2026 10:39:43 -0700 Subject: [PATCH 1/5] fix(chat): drop absolute positioning on chat-message controls --- .../src/lib/styles/chat-message.styles.spec.ts | 18 ++++++++++++++++++ .../chat/src/lib/styles/chat-message.styles.ts | 3 --- 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 libs/chat/src/lib/styles/chat-message.styles.spec.ts diff --git a/libs/chat/src/lib/styles/chat-message.styles.spec.ts b/libs/chat/src/lib/styles/chat-message.styles.spec.ts new file mode 100644 index 000000000..8a254d242 --- /dev/null +++ b/libs/chat/src/lib/styles/chat-message.styles.spec.ts @@ -0,0 +1,18 @@ +// libs/chat/src/lib/styles/chat-message.styles.spec.ts +// SPDX-License-Identifier: MIT +import { describe, it, expect } from 'vitest'; +import { CHAT_MESSAGE_STYLES } from './chat-message.styles'; + +describe('CHAT_MESSAGE_STYLES — controls positioning', () => { + const normalized = CHAT_MESSAGE_STYLES.replace(/\s+/g, ' '); + it('does NOT absolute-position the actions controls (so they flow inside .chat-message__main, indented past the gutter)', () => { + expect(normalized).not.toMatch( + /\.chat-message__controls\s*\{[^}]*position:\s*absolute/, + ); + }); + it('does NOT pin the controls to a negative bottom offset (would overlap with the next message)', () => { + expect(normalized).not.toMatch( + /\.chat-message__controls\s*\{[^}]*bottom:\s*-/, + ); + }); +}); diff --git a/libs/chat/src/lib/styles/chat-message.styles.ts b/libs/chat/src/lib/styles/chat-message.styles.ts index 698c1bcae..68ef2d91b 100644 --- a/libs/chat/src/lib/styles/chat-message.styles.ts +++ b/libs/chat/src/lib/styles/chat-message.styles.ts @@ -90,9 +90,6 @@ export const CHAT_MESSAGE_STYLES = ` .chat-message__controls { display: none; - position: absolute; - left: 0; - bottom: -28px; gap: 1rem; opacity: 0; transition: opacity 200ms ease; From ddb7b84adab9cf954a8a828201c4890b48476d69 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 18 May 2026 10:40:31 -0700 Subject: [PATCH 2/5] feat(chat): unify sidenav action button font family + size --- .../styles/chat-project-list.styles.spec.ts | 22 +++++++++++++++ .../lib/styles/chat-project-list.styles.ts | 4 ++- .../lib/styles/chat-sidenav.styles.spec.ts | 28 +++++++++++++++++++ .../src/lib/styles/chat-sidenav.styles.ts | 8 ++++-- 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/libs/chat/src/lib/styles/chat-project-list.styles.spec.ts b/libs/chat/src/lib/styles/chat-project-list.styles.spec.ts index 4fc4bbbc1..9472ea139 100644 --- a/libs/chat/src/lib/styles/chat-project-list.styles.spec.ts +++ b/libs/chat/src/lib/styles/chat-project-list.styles.spec.ts @@ -42,6 +42,28 @@ describe('CHAT_PROJECT_LIST_STYLES — New project button', () => { }); }); +describe('CHAT_PROJECT_LIST_STYLES — New project button font', () => { + const normalized = CHAT_PROJECT_LIST_STYLES.replace(/\s+/g, ' '); + + it('uses font-family: inherit (matches sidenav action buttons)', () => { + expect(normalized).toMatch( + /\.chat-project-list__new\s*\{[^}]*font-family:\s*inherit\s*;/, + ); + }); + + it('uses font-size: var(--ngaf-chat-font-size-sm) (not hard-coded 12px)', () => { + expect(normalized).toMatch( + /\.chat-project-list__new\s*\{[^}]*font-size:\s*var\(--ngaf-chat-font-size-sm\)\s*;/, + ); + }); + + it('does NOT use hard-coded 12px for font-size', () => { + expect(normalized).not.toMatch( + /\.chat-project-list__new\s*\{[^}]*font-size:\s*12px/, + ); + }); +}); + describe('CHAT_PROJECT_LIST_STYLES — active item', () => { const normalized = CHAT_PROJECT_LIST_STYLES.replace(/\s+/g, ' '); it('does NOT use a left-accent box-shadow for the active item (symmetric bg-only indication)', () => { diff --git a/libs/chat/src/lib/styles/chat-project-list.styles.ts b/libs/chat/src/lib/styles/chat-project-list.styles.ts index ab57a684d..2d9425e89 100644 --- a/libs/chat/src/lib/styles/chat-project-list.styles.ts +++ b/libs/chat/src/lib/styles/chat-project-list.styles.ts @@ -79,7 +79,9 @@ export const CHAT_PROJECT_LIST_STYLES = ` border: 0; padding: 10px 16px; border-radius: 8px; - font-size: 12px; + font-family: inherit; + font-size: var(--ngaf-chat-font-size-sm); + font-weight: 400; display: flex; align-items: center; gap: 8px; diff --git a/libs/chat/src/lib/styles/chat-sidenav.styles.spec.ts b/libs/chat/src/lib/styles/chat-sidenav.styles.spec.ts index 7ee7a53b1..d207a1b59 100644 --- a/libs/chat/src/lib/styles/chat-sidenav.styles.spec.ts +++ b/libs/chat/src/lib/styles/chat-sidenav.styles.spec.ts @@ -42,6 +42,34 @@ describe('CHAT_SIDENAV_STYLES — New chat button', () => { }); }); +describe('CHAT_SIDENAV_STYLES — action button font', () => { + const normalized = CHAT_SIDENAV_STYLES.replace(/\s+/g, ' '); + + it('generic .chat-sidenav__action has font-family: inherit', () => { + expect(normalized).toMatch( + /\.chat-sidenav__action\s*\{[^}]*font-family:\s*inherit\s*;/, + ); + }); + + it('generic .chat-sidenav__action has font-size: var(--ngaf-chat-font-size-sm)', () => { + expect(normalized).toMatch( + /\.chat-sidenav__action\s*\{[^}]*font-size:\s*var\(--ngaf-chat-font-size-sm\)\s*;/, + ); + }); + + it('late-cascade New chat uses font-size: var(--ngaf-chat-font-size-sm) (not 13px)', () => { + expect(normalized).toMatch( + /\.chat-sidenav__action\.chat-sidenav__action--new\s*\{[^}]*font-size:\s*var\(--ngaf-chat-font-size-sm\)\s*;/, + ); + }); + + it('does NOT use hard-coded 13px for New chat font-size', () => { + expect(normalized).not.toMatch( + /\.chat-sidenav__action\.chat-sidenav__action--new\s*\{[^}]*font-size:\s*13px/, + ); + }); +}); + describe('CHAT_SIDENAV_STYLES — Archived disclosure', () => { const normalized = CHAT_SIDENAV_STYLES.replace(/\s+/g, ' '); diff --git a/libs/chat/src/lib/styles/chat-sidenav.styles.ts b/libs/chat/src/lib/styles/chat-sidenav.styles.ts index ee9a87de1..eba048ed0 100644 --- a/libs/chat/src/lib/styles/chat-sidenav.styles.ts +++ b/libs/chat/src/lib/styles/chat-sidenav.styles.ts @@ -105,7 +105,7 @@ export const CHAT_SIDENAV_STYLES = ` border: 0; padding: 12px 18px; border-radius: 8px; - font-size: 13px; + font-size: var(--ngaf-chat-font-size-sm); font-weight: 600; display: flex; align-items: center; @@ -150,7 +150,9 @@ export const CHAT_SIDENAV_STYLES = ` color: var(--ngaf-chat-text); border-radius: 8px; cursor: pointer; - font: inherit; + font-family: inherit; + font-size: var(--ngaf-chat-font-size-sm); + font-weight: 400; text-align: left; } .chat-sidenav__action:hover { background: var(--ngaf-chat-surface-alt); } @@ -178,7 +180,7 @@ export const CHAT_SIDENAV_STYLES = ` border-radius: 8px; padding: 12px 18px; font-weight: 600; - font-size: 13px; + font-size: var(--ngaf-chat-font-size-sm); } .chat-sidenav__action.chat-sidenav__action--new:hover { background: var(--ngaf-chat-text); From 5eaff1af5bb844eb822f3e39e3d418ec85834446 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 18 May 2026 10:40:46 -0700 Subject: [PATCH 3/5] feat(chat): drop top border above New chat (remove sidenav header underline) --- libs/chat/src/lib/styles/chat-sidenav.styles.spec.ts | 9 +++++++++ libs/chat/src/lib/styles/chat-sidenav.styles.ts | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libs/chat/src/lib/styles/chat-sidenav.styles.spec.ts b/libs/chat/src/lib/styles/chat-sidenav.styles.spec.ts index d207a1b59..deb08176f 100644 --- a/libs/chat/src/lib/styles/chat-sidenav.styles.spec.ts +++ b/libs/chat/src/lib/styles/chat-sidenav.styles.spec.ts @@ -42,6 +42,15 @@ describe('CHAT_SIDENAV_STYLES — New chat button', () => { }); }); +describe('CHAT_SIDENAV_STYLES — header chrome', () => { + const normalized = CHAT_SIDENAV_STYLES.replace(/\s+/g, ' '); + it('does NOT draw a border-bottom on .chat-sidenav__header (removes the line above New chat)', () => { + expect(normalized).not.toMatch( + /\.chat-sidenav__header\s*\{[^}]*border-bottom:/, + ); + }); +}); + describe('CHAT_SIDENAV_STYLES — action button font', () => { const normalized = CHAT_SIDENAV_STYLES.replace(/\s+/g, ' '); diff --git a/libs/chat/src/lib/styles/chat-sidenav.styles.ts b/libs/chat/src/lib/styles/chat-sidenav.styles.ts index eba048ed0..4f72b2b92 100644 --- a/libs/chat/src/lib/styles/chat-sidenav.styles.ts +++ b/libs/chat/src/lib/styles/chat-sidenav.styles.ts @@ -70,7 +70,6 @@ export const CHAT_SIDENAV_STYLES = ` .chat-sidenav__header { flex-shrink: 0; padding: var(--ngaf-chat-space-3); - border-bottom: 1px solid var(--ngaf-chat-separator); } .chat-sidenav__topbar { flex-shrink: 0; From 69947250ebe171833e7f916e4b0c8762e2cb4e2a Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 18 May 2026 10:41:10 -0700 Subject: [PATCH 4/5] feat(demo): widen More prompts dropdown menu to fit long labels --- .../app/modes/welcome-suggestions.component.spec.ts | 10 ++++++++++ .../src/app/modes/welcome-suggestions.component.ts | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/examples/chat/angular/src/app/modes/welcome-suggestions.component.spec.ts b/examples/chat/angular/src/app/modes/welcome-suggestions.component.spec.ts index e7ff2ab04..8437191e2 100644 --- a/examples/chat/angular/src/app/modes/welcome-suggestions.component.spec.ts +++ b/examples/chat/angular/src/app/modes/welcome-suggestions.component.spec.ts @@ -52,6 +52,16 @@ describe('WelcomeSuggestionsComponent', () => { expect(captured).toBe(FEATURED_SUGGESTIONS[0].value); }); + // JSDOM does not cascade ::ng-deep overrides from Angular component