diff --git a/examples/chat/angular/src/index.html b/examples/chat/angular/src/index.html index 5075242f..30b61a4c 100644 --- a/examples/chat/angular/src/index.html +++ b/examples/chat/angular/src/index.html @@ -1,5 +1,5 @@ - + NGAF chat — canonical demo diff --git a/libs/chat/src/lib/compositions/chat-sidenav/chat-sidenav.component.spec.ts b/libs/chat/src/lib/compositions/chat-sidenav/chat-sidenav.component.spec.ts index 9e53dc6b..3047a3b7 100644 --- a/libs/chat/src/lib/compositions/chat-sidenav/chat-sidenav.component.spec.ts +++ b/libs/chat/src/lib/compositions/chat-sidenav/chat-sidenav.component.spec.ts @@ -139,6 +139,39 @@ describe('ChatSidenavComponent', () => { expect(fixture.nativeElement.querySelector('.chat-sidenav__action--collapse')).toBeNull(); }); + it('renders a topbar containing the new-chat and collapse buttons in expanded mode', () => { + const fixture = render({ mode: 'expanded' }); + const topbar = fixture.nativeElement.querySelector('.chat-sidenav__topbar') as HTMLElement; + expect(topbar).not.toBeNull(); + expect(topbar.querySelector('.chat-sidenav__action--new')).not.toBeNull(); + expect(topbar.querySelector('.chat-sidenav__action--collapse')).not.toBeNull(); + }); + + it('search button is the only action in .chat-sidenav__actions row', () => { + const fixture = render({ mode: 'expanded' }); + const actions = fixture.nativeElement.querySelector('.chat-sidenav__actions') as HTMLElement; + const buttons = actions.querySelectorAll('button'); + expect(buttons.length).toBe(1); + expect(buttons[0].classList.contains('chat-sidenav__action--search')).toBe(true); + }); + + it('drawer mode: renders a close button in the topbar that emits openChange(false)', () => { + const fixture = render({ mode: 'drawer', open: true }); + const topbar = fixture.nativeElement.querySelector('.chat-sidenav__topbar') as HTMLElement; + const close = topbar.querySelector('.chat-sidenav__action--close') as HTMLButtonElement; + expect(close).not.toBeNull(); + expect(close.getAttribute('aria-label')).toBe('Close conversations'); + let lastOpen: boolean | undefined; + fixture.componentInstance.openChange.subscribe((v: boolean) => { lastOpen = v; }); + close.click(); + expect(lastOpen).toBe(false); + }); + + it('non-drawer modes: no close button is rendered', () => { + expect(render({ mode: 'expanded' }).nativeElement.querySelector('.chat-sidenav__action--close')).toBeNull(); + expect(render({ mode: 'collapsed' }).nativeElement.querySelector('.chat-sidenav__action--close')).toBeNull(); + }); + it('clicking the chevron in expanded mode emits modeChange="collapsed"', () => { const fixture = render({ mode: 'expanded' }); let last: string | undefined; diff --git a/libs/chat/src/lib/compositions/chat-sidenav/chat-sidenav.component.ts b/libs/chat/src/lib/compositions/chat-sidenav/chat-sidenav.component.ts index d439e14d..18999da7 100644 --- a/libs/chat/src/lib/compositions/chat-sidenav/chat-sidenav.component.ts +++ b/libs/chat/src/lib/compositions/chat-sidenav/chat-sidenav.component.ts @@ -50,7 +50,7 @@ export type ChatSidenavMode = 'expanded' | 'collapsed' | 'drawer'; -
+
- @if (mode() !== 'drawer') { } + @if (mode() === 'drawer') { + + } +
+ +
+
diff --git a/libs/chat/src/lib/styles/chat-sidenav.styles.ts b/libs/chat/src/lib/styles/chat-sidenav.styles.ts index 45fff77d..65879817 100644 --- a/libs/chat/src/lib/styles/chat-sidenav.styles.ts +++ b/libs/chat/src/lib/styles/chat-sidenav.styles.ts @@ -33,7 +33,12 @@ export const CHAT_SIDENAV_STYLES = ` width: 100%; } :host([data-mode="drawer"]) { - position: relative; + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: var(--ngaf-chat-sidenav-width-drawer); + z-index: 1001; } .chat-sidenav { display: flex; @@ -54,28 +59,43 @@ export const CHAT_SIDENAV_STYLES = ` cursor: pointer; } :host([data-mode="drawer"]) .chat-sidenav { - position: fixed; - top: 0; - bottom: 0; - left: 0; - width: var(--ngaf-chat-sidenav-width-drawer); - z-index: 1001; + width: 100%; + height: 100%; transition: transform 200ms ease; transform: translateX(-100%); } :host([data-mode="drawer"][data-open="true"]) .chat-sidenav { transform: translateX(0); } - @media (max-width: 767px) { - :host([data-mode="drawer"]) .chat-sidenav { - width: 100%; - } - } .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; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: 4px; + padding: var(--ngaf-chat-space-2) var(--ngaf-chat-space-3); + border-bottom: 1px solid var(--ngaf-chat-separator); + } + :host([data-mode="collapsed"]) .chat-sidenav__topbar { + justify-content: center; + padding: var(--ngaf-chat-space-2); + } + .chat-sidenav__topbar .chat-sidenav__action { + width: 36px; + height: 36px; + padding: 0; + justify-content: center; + flex: 0 0 auto; + } + .chat-sidenav__topbar .chat-sidenav__action-label { + display: none; + } .chat-sidenav__actions { flex-shrink: 0; display: flex;