Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/chat/angular/src/index.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!doctype html>
<html lang="en">
<html lang="en" data-ngaf-chat-theme="dark">
<head>
<meta charset="utf-8" />
<title>NGAF chat — canonical demo</title>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export type ChatSidenavMode = 'expanded' | 'collapsed' | 'drawer';
<ng-content select="[sidenavHeader]" />
</div>

<div class="chat-sidenav__actions">
<div class="chat-sidenav__topbar">
<button
type="button"
class="chat-sidenav__action chat-sidenav__action--new"
Expand All @@ -64,19 +64,6 @@ export type ChatSidenavMode = 'expanded' | 'collapsed' | 'drawer';
</svg>
<span class="chat-sidenav__action-label">New chat</span>
</button>
<button
type="button"
class="chat-sidenav__action chat-sidenav__action--search"
(click)="searchOpened.emit()"
aria-label="Search conversations"
title="Search conversations (⌘K)"
>
<svg class="chat-sidenav__action-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="11" cy="11" r="7"/>
<line x1="21" y1="21" x2="16.65" y2="16.65"/>
</svg>
<span class="chat-sidenav__action-label">Search</span>
</button>
@if (mode() !== 'drawer') {
<button
type="button"
Expand All @@ -97,6 +84,37 @@ export type ChatSidenavMode = 'expanded' | 'collapsed' | 'drawer';
<span class="chat-sidenav__action-label">{{ mode() === 'collapsed' ? 'Expand' : 'Collapse' }}</span>
</button>
}
@if (mode() === 'drawer') {
<button
type="button"
class="chat-sidenav__action chat-sidenav__action--close"
(click)="openChange.emit(false)"
aria-label="Close conversations"
title="Close conversations"
>
<svg class="chat-sidenav__action-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<line x1="18" y1="6" x2="6" y2="18"/>
<line x1="6" y1="6" x2="18" y2="18"/>
</svg>
<span class="chat-sidenav__action-label">Close</span>
</button>
}
</div>

<div class="chat-sidenav__actions">
<button
type="button"
class="chat-sidenav__action chat-sidenav__action--search"
(click)="searchOpened.emit()"
aria-label="Search conversations"
title="Search conversations (⌘K)"
>
<svg class="chat-sidenav__action-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="11" cy="11" r="7"/>
<line x1="21" y1="21" x2="16.65" y2="16.65"/>
</svg>
<span class="chat-sidenav__action-label">Search</span>
</button>
</div>

<div class="chat-sidenav__primary">
Expand Down
44 changes: 32 additions & 12 deletions libs/chat/src/lib/styles/chat-sidenav.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
Loading