diff --git a/libs/chat/src/lib/primitives/chat-checkpoint-marker/chat-checkpoint-marker.component.spec.ts b/libs/chat/src/lib/primitives/chat-checkpoint-marker/chat-checkpoint-marker.component.spec.ts index 28cc39a4..54c81f38 100644 --- a/libs/chat/src/lib/primitives/chat-checkpoint-marker/chat-checkpoint-marker.component.spec.ts +++ b/libs/chat/src/lib/primitives/chat-checkpoint-marker/chat-checkpoint-marker.component.spec.ts @@ -55,4 +55,11 @@ describe('ChatCheckpointMarkerComponent', () => { (fx.nativeElement.querySelector('[data-action="fork"]') as HTMLButtonElement).click(); expect(fx.componentInstance.forked).toEqual(['cp-1']); }); + + it('positions the host as a containing block so the hover pill anchors to the dot', () => { + const fx = TestBed.createComponent(HostComponent); + fx.detectChanges(); + const host = fx.nativeElement.querySelector('chat-checkpoint-marker') as HTMLElement; + expect(getComputedStyle(host).position).toBe('relative'); + }); }); diff --git a/libs/chat/src/lib/primitives/chat-checkpoint-marker/chat-checkpoint-marker.component.ts b/libs/chat/src/lib/primitives/chat-checkpoint-marker/chat-checkpoint-marker.component.ts index f7d15a66..0e81c266 100644 --- a/libs/chat/src/lib/primitives/chat-checkpoint-marker/chat-checkpoint-marker.component.ts +++ b/libs/chat/src/lib/primitives/chat-checkpoint-marker/chat-checkpoint-marker.component.ts @@ -16,6 +16,7 @@ import { CHAT_HOST_TOKENS } from '../../styles/chat-tokens'; width: 14px; height: 100%; flex: 0 0 14px; + position: relative; } .chat-checkpoint-marker__dot { width: 10px; diff --git a/libs/chat/src/lib/primitives/chat-confirm-dialog/chat-confirm-dialog.component.spec.ts b/libs/chat/src/lib/primitives/chat-confirm-dialog/chat-confirm-dialog.component.spec.ts index 9a58b89c..184dca84 100644 --- a/libs/chat/src/lib/primitives/chat-confirm-dialog/chat-confirm-dialog.component.spec.ts +++ b/libs/chat/src/lib/primitives/chat-confirm-dialog/chat-confirm-dialog.component.spec.ts @@ -3,6 +3,7 @@ import { TestBed } from '@angular/core/testing'; import { describe, expect, it } from 'vitest'; import { ChatConfirmDialogComponent } from './chat-confirm-dialog.component'; +import { CHAT_CONFIRM_DIALOG_STYLES } from '../../styles/chat-confirm-dialog.styles'; function render(opts: { open?: boolean; @@ -89,6 +90,19 @@ describe('ChatConfirmDialogComponent', () => { expect(confirm.classList.contains('chat-confirm-dialog__confirm--destructive')).toBe(true); }); + it('destructive confirm button uses the new --ngaf-chat-destructive token, not --ngaf-chat-error-text', () => { + // Regression guard: error-text is light pink (#fca5a5) in dark mode, which gave + // white-text-on-pink unreadable contrast. The destructive button must use a + // dedicated token that resolves to a saturated red on both themes. + expect(CHAT_CONFIRM_DIALOG_STYLES).toContain('.chat-confirm-dialog__confirm--destructive'); + const destructiveBlock = CHAT_CONFIRM_DIALOG_STYLES + .split('.chat-confirm-dialog__confirm--destructive') + .slice(1) + .join('.chat-confirm-dialog__confirm--destructive'); + expect(destructiveBlock).toContain('var(--ngaf-chat-destructive)'); + expect(destructiveBlock).not.toContain('var(--ngaf-chat-error-text)'); + }); + it('confirm button has labelled text from confirmLabel input', () => { const fixture = render({ confirmLabel: 'Yes do it' }); const confirm = fixture.nativeElement.querySelector('.chat-confirm-dialog__confirm'); diff --git a/libs/chat/src/lib/styles/chat-confirm-dialog.styles.ts b/libs/chat/src/lib/styles/chat-confirm-dialog.styles.ts index 96293c3d..eecdbda6 100644 --- a/libs/chat/src/lib/styles/chat-confirm-dialog.styles.ts +++ b/libs/chat/src/lib/styles/chat-confirm-dialog.styles.ts @@ -59,8 +59,12 @@ export const CHAT_CONFIRM_DIALOG_STYLES = ` border-color: transparent; } .chat-confirm-dialog__confirm--destructive { - background: var(--ngaf-chat-error-text); + background: var(--ngaf-chat-destructive); color: #fff; + border-color: transparent; + } + .chat-confirm-dialog__confirm--destructive:hover { + filter: brightness(1.1); } .chat-confirm-dialog__cancel:focus-visible, .chat-confirm-dialog__confirm:focus-visible { diff --git a/libs/chat/src/lib/styles/chat-sidenav.styles.ts b/libs/chat/src/lib/styles/chat-sidenav.styles.ts index e6f67f53..37caea2c 100644 --- a/libs/chat/src/lib/styles/chat-sidenav.styles.ts +++ b/libs/chat/src/lib/styles/chat-sidenav.styles.ts @@ -151,10 +151,10 @@ export const CHAT_SIDENAV_STYLES = ` } .chat-sidenav__threads-heading { padding: 8px 12px 4px; - font-size: var(--ngaf-chat-font-size-xs); + font-size: 11px; color: var(--ngaf-chat-text-muted); text-transform: uppercase; - letter-spacing: 0.05em; + letter-spacing: 0.4px; } :host([data-mode="collapsed"]) .chat-sidenav__threads-heading { display: none; @@ -178,9 +178,9 @@ export const CHAT_SIDENAV_STYLES = ` background: transparent; color: var(--ngaf-chat-text-muted); font: inherit; - font-size: var(--ngaf-chat-font-size-xs); + font-size: 11px; text-transform: uppercase; - letter-spacing: 0.05em; + letter-spacing: 0.4px; text-align: left; cursor: pointer; } diff --git a/libs/chat/src/lib/styles/chat-tokens.ts b/libs/chat/src/lib/styles/chat-tokens.ts index 2438b0aa..f3c5dde1 100644 --- a/libs/chat/src/lib/styles/chat-tokens.ts +++ b/libs/chat/src/lib/styles/chat-tokens.ts @@ -14,6 +14,7 @@ const LIGHT_TOKENS = ` --ngaf-chat-error-bg: #fef2f2; --ngaf-chat-error-border: #fecaca; --ngaf-chat-error-text: #dc2626; + --ngaf-chat-destructive: #dc2626; --ngaf-chat-warning-bg: #fffbeb; --ngaf-chat-warning-text: #b45309; --ngaf-chat-success: #16a34a; @@ -35,6 +36,7 @@ const DARK_TOKENS = ` --ngaf-chat-error-bg: rgb(45, 21, 21); --ngaf-chat-error-border: #dc2626; --ngaf-chat-error-text: #fca5a5; + --ngaf-chat-destructive: #ef4444; --ngaf-chat-warning-bg: rgb(45, 35, 21); --ngaf-chat-warning-text: #fbbf24; --ngaf-chat-success: #4ade80; diff --git a/libs/chat/src/lib/styles/chat.css b/libs/chat/src/lib/styles/chat.css index 7c75afa1..bc0b5107 100644 --- a/libs/chat/src/lib/styles/chat.css +++ b/libs/chat/src/lib/styles/chat.css @@ -27,6 +27,7 @@ --ngaf-chat-error-bg: #fef2f2; --ngaf-chat-error-border: #fecaca; --ngaf-chat-error-text: #dc2626; + --ngaf-chat-destructive: #dc2626; --ngaf-chat-warning-bg: #fffbeb; --ngaf-chat-warning-text: #b45309; --ngaf-chat-success: #16a34a; @@ -157,6 +158,7 @@ --ngaf-chat-error-bg: rgb(45, 21, 21); --ngaf-chat-error-border: #dc2626; --ngaf-chat-error-text: #fca5a5; + --ngaf-chat-destructive: #ef4444; --ngaf-chat-warning-bg: rgb(45, 35, 21); --ngaf-chat-warning-text: #fbbf24; --ngaf-chat-success: #4ade80; @@ -176,6 +178,7 @@ --ngaf-chat-error-bg: rgb(45, 21, 21); --ngaf-chat-error-border: #dc2626; --ngaf-chat-error-text: #fca5a5; + --ngaf-chat-destructive: #ef4444; --ngaf-chat-warning-bg: rgb(45, 35, 21); --ngaf-chat-warning-text: #fbbf24; --ngaf-chat-success: #4ade80;