fix: main chat now fillup space when sidebar is closed.
This commit is contained in:
parent
ad0f0bf67b
commit
e134d67cec
@ -1,5 +1,6 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600&display=swap');
|
:host {
|
||||||
|
min-width: 100%;
|
||||||
|
}
|
||||||
.custom-scrollbar::-webkit-scrollbar {
|
.custom-scrollbar::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
}
|
}
|
||||||
@ -36,17 +37,35 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes typing {
|
@keyframes typing {
|
||||||
0%, 80%, 100% { transform: scale(0); opacity: 0.3; }
|
0%,
|
||||||
40% { transform: scale(1); opacity: 1; }
|
80%,
|
||||||
|
100% {
|
||||||
|
transform: scale(0);
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0% { box-shadow: 0 0 0 0 rgba(79, 172, 254, 0.4); }
|
0% {
|
||||||
70% { box-shadow: 0 0 0 10px rgba(79, 172, 254, 0); }
|
box-shadow: 0 0 0 0 rgba(79, 172, 254, 0.4);
|
||||||
100% { box-shadow: 0 0 0 0 rgba(79, 172, 254, 0); }
|
}
|
||||||
|
70% {
|
||||||
|
box-shadow: 0 0 0 10px rgba(79, 172, 254, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 0 0 rgba(79, 172, 254, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeIn {
|
@keyframes fadeIn {
|
||||||
from { opacity: 0; }
|
from {
|
||||||
to { opacity: 1; }
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
<div class="h-screen flex flex-col bg-white/5 backdrop-blur-[20px] border border-white/10 relative">
|
<div class="h-screen w-full flex flex-col backdrop-blur-[20px] relative">
|
||||||
<div class="flex-1 overflow-y-auto p-8 flex flex-col gap-6 scroll-smooth custom-scrollbar" #scrollContainer>
|
<div
|
||||||
|
class="flex-1 overflow-y-auto p-8 flex flex-col gap-6 scroll-smooth custom-scrollbar"
|
||||||
|
#scrollContainer
|
||||||
|
>
|
||||||
@for (msg of messageStore.messages(); track msg.id) {
|
@for (msg of messageStore.messages(); track msg.id) {
|
||||||
<div
|
<div
|
||||||
class="flex flex-col max-w-[80%] animate-[messageAppear_0.5s_cubic-bezier(0.16,1,0.3,1)]"
|
class="flex flex-col max-w-[80%] animate-[messageAppear_0.5s_cubic-bezier(0.16,1,0.3,1)]"
|
||||||
@ -15,25 +18,35 @@
|
|||||||
{{ msg.attributes.createdAt | date:'shortTime' }}
|
{{ msg.attributes.createdAt | date:'shortTime' }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
} @if (messageStore.isLoading()) {
|
||||||
|
<div
|
||||||
@if (messageStore.isLoading()) {
|
class="flex items-center gap-1.5 px-5 py-4 bg-white/5 rounded-2xl rounded-bl-sm self-start animate-[fadeIn_0.3s_ease-in-out]"
|
||||||
<div class="flex items-center gap-1.5 px-5 py-4 bg-white/5 rounded-2xl rounded-bl-sm self-start animate-[fadeIn_0.3s_ease-in-out]">
|
>
|
||||||
<div class="w-2 h-2 bg-[#4facfe] rounded-full animate-[typing_1.4s_infinite_ease-in-out_both] delay-[-0.32s]"></div>
|
<div
|
||||||
<div class="w-2 h-2 bg-[#4facfe] rounded-full animate-[typing_1.4s_infinite_ease-in-out_both] delay-[-0.16s]"></div>
|
class="w-2 h-2 bg-[#4facfe] rounded-full animate-[typing_1.4s_infinite_ease-in-out_both] delay-[-0.32s]"
|
||||||
<div class="w-2 h-2 bg-[#4facfe] rounded-full animate-[typing_1.4s_infinite_ease-in-out_both] delay-0"></div>
|
></div>
|
||||||
|
<div
|
||||||
|
class="w-2 h-2 bg-[#4facfe] rounded-full animate-[typing_1.4s_infinite_ease-in-out_both] delay-[-0.16s]"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
class="w-2 h-2 bg-[#4facfe] rounded-full animate-[typing_1.4s_infinite_ease-in-out_both] delay-0"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="px-8 py-3">
|
<div class="px-8 py-3">
|
||||||
@if (errorMessage) {
|
@if (errorMessage) {
|
||||||
<div class="text-[#ff6b6b] text-sm mb-3 px-4 py-2 bg-[#ff6b6b]/10 rounded-lg border border-[#ff6b6b]/20 animate-[fadeIn_0.3s_ease-in-out]">
|
<div
|
||||||
|
class="text-[#ff6b6b] text-sm mb-3 px-4 py-2 bg-[#ff6b6b]/10 rounded-lg border border-[#ff6b6b]/20 animate-[fadeIn_0.3s_ease-in-out]"
|
||||||
|
>
|
||||||
{{ errorMessage }}
|
{{ errorMessage }}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="w-full flex gap-4 bg-white/5 px-4 py-2 rounded-full border border-white/10 transition-all duration-300 focus-within:bg-white/10 focus-within:border-[#4facfe]/50 focus-within:shadow-[0_0_20px_rgba(79,172,254,0.2)]">
|
<div
|
||||||
|
class="w-full flex gap-4 bg-white/5 px-4 py-2 rounded-full border border-white/10 transition-all duration-300 focus-within:bg-white/10 focus-within:border-[#4facfe]/50 focus-within:shadow-[0_0_20px_rgba(79,172,254,0.2)]"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
class="flex-1 bg-transparent border-none text-white text-base py-1 px-2 outline-none font-inherit placeholder-slate-500"
|
class="flex-1 bg-transparent border-none text-white text-base py-1 px-2 outline-none font-inherit placeholder-slate-500"
|
||||||
type="text"
|
type="text"
|
||||||
@ -48,7 +61,7 @@
|
|||||||
[disabled]="!messageControl.value || messageStore.isLoading()"
|
[disabled]="!messageControl.value || messageStore.isLoading()"
|
||||||
>
|
>
|
||||||
<svg class="w-3 h-3 fill-current" viewBox="0 0 24 24">
|
<svg class="w-3 h-3 fill-current" viewBox="0 0 24 24">
|
||||||
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
|
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
@if(!isOpen()){
|
||||||
<button
|
<button
|
||||||
*ngIf="!isOpen()"
|
|
||||||
(click)="toggleSidebar()"
|
(click)="toggleSidebar()"
|
||||||
class="fixed top-4 right-4 z-50 p-2.5 rounded-xl bg-[#1a2744] border border-[#2a3a5c] text-[#7b9cc4] hover:text-white hover:bg-[#243058] hover:border-[#3d5a8a] transition-all duration-200 shadow-lg"
|
class="fixed top-4 right-4 z-50 p-2.5 rounded-xl bg-[#1a2744] border border-[#2a3a5c] text-[#7b9cc4] hover:text-white hover:bg-[#243058] hover:border-[#3d5a8a] transition-all duration-200 shadow-lg"
|
||||||
title="Open sidebar"
|
title="Open sidebar"
|
||||||
@ -19,29 +19,22 @@
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
|
|
||||||
<!-- Backdrop (mobile) -->
|
<aside [class]="sidebarClasses()">
|
||||||
<div
|
|
||||||
*ngIf="isOpen()"
|
|
||||||
class="fixed inset-0 bg-black/40 backdrop-blur-sm z-30 lg:hidden"
|
|
||||||
(click)="toggleSidebar()"
|
|
||||||
></div>
|
|
||||||
|
|
||||||
<aside [class]="sidebarClasses()" style="font-family: 'DM Sans', 'Segoe UI', sans-serif;">
|
|
||||||
<div
|
|
||||||
class="absolute top-0 left-0 right-0 h-px bg-linear-to-r from-transparent via-[#3d6cb5] to-transparent"
|
|
||||||
></div>
|
|
||||||
|
|
||||||
<div class="flex items-center justify-between px-4 pt-5 pb-4 border-b border-[#1e2f4d]">
|
<div class="flex items-center justify-between px-4 pt-5 pb-4 border-b border-[#1e2f4d]">
|
||||||
<div class="flex items-center gap-2.5">
|
<div class="flex items-center gap-2.5">
|
||||||
<div
|
<div
|
||||||
class="w-8 h-8 rounded-full bg-linear-to-br from-[#00f2fe] to-[#4facfe] flex items-center justify-center font-semibold text-xl shadow-[0_0_20px_rgba(79,172,254,0.4)] animate-[pulse_2s_infinite]">
|
class="w-8 h-8 rounded-full bg-linear-to-br from-[#00f2fe] to-[#4facfe] flex items-center justify-center font-semibold text-xl shadow-[0_0_20px_rgba(79,172,254,0.4)] animate-[pulse_2s_infinite]"
|
||||||
|
>
|
||||||
AI
|
AI
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h1
|
<h1
|
||||||
class="m-0 font-semibold tracking-wide bg-linear-to-r from-white to-indigo-300 bg-clip-text text-transparent">
|
class="m-0 font-semibold tracking-wide bg-linear-to-r from-white to-indigo-300 bg-clip-text text-transparent"
|
||||||
Post Assistant</h1>
|
>
|
||||||
|
Post Assistant
|
||||||
|
</h1>
|
||||||
<p class="m-0 text-xs text-slate-400">Always online, ready to write.</p>
|
<p class="m-0 text-xs text-slate-400">Always online, ready to write.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -79,12 +72,7 @@
|
|||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
>
|
>
|
||||||
<path
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M12 4v16m8-8H4"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
New Chat
|
New Chat
|
||||||
</button>
|
</button>
|
||||||
@ -115,14 +103,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if (chatStore.chats().length !== 0) {
|
||||||
<div class="flex-1 overflow-y-auto px-2 pb-4 scrollbar-thin">
|
<div class="flex-1 overflow-y-auto px-2 pb-4 scrollbar-thin">
|
||||||
<!-- Chat Items -->
|
<!-- Chat Items -->
|
||||||
<div class="space-y-0.5">
|
<div class="space-y-0.5">
|
||||||
@for (chat of chatStore.chats(); track chat.id) {
|
@for (chat of chatStore.chats(); track chat.id) {
|
||||||
<button
|
<button (click)="selectChat(chat)" [class]="chatItemClasses(chat)">
|
||||||
(click)="selectChat(chat)"
|
|
||||||
[class]="chatItemClasses(chat)"
|
|
||||||
>
|
|
||||||
<!-- Active indicator -->
|
<!-- Active indicator -->
|
||||||
<div
|
<div
|
||||||
class="absolute left-0 top-1/2 -translate-y-1/2 w-0.5 h-6 bg-[#2d5be3] rounded-r-full"
|
class="absolute left-0 top-1/2 -translate-y-1/2 w-0.5 h-6 bg-[#2d5be3] rounded-r-full"
|
||||||
@ -149,28 +135,22 @@
|
|||||||
|
|
||||||
<!-- Text -->
|
<!-- Text -->
|
||||||
<div class="flex-1 min-w-0 text-left">
|
<div class="flex-1 min-w-0 text-left">
|
||||||
<p
|
<p class="text-xs font-medium truncate text-white">{{ chat.attributes.title }}</p>
|
||||||
class="text-xs font-medium truncate text-white"
|
|
||||||
>
|
|
||||||
{{ chat.attributes.title }}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Time -->
|
<!-- Time -->
|
||||||
<span class="text-[9px] text-[#3a5272] shrink-0 mt-0.5">{{
|
<span class="text-[9px] text-[#3a5272] shrink-0 mt-0.5"
|
||||||
formatTime(chat.attributes.createdAt)
|
>{{ formatTime(chat.attributes.createdAt) }}</span
|
||||||
}}</span>
|
>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
<!-- Empty state -->
|
<!-- Empty state -->
|
||||||
@if (chatStore.chats().length === 0) {
|
@if (chatStore.chats().length === 0) {
|
||||||
<div
|
<div class="flex flex-1 flex-col items-center justify-center py-10 px-4 text-center">
|
||||||
class="flex flex-col items-center justify-center py-10 px-4 text-center"
|
|
||||||
>
|
|
||||||
<div class="w-10 h-10 rounded-full bg-[#111a2e] flex items-center justify-center mb-3">
|
<div class="w-10 h-10 rounded-full bg-[#111a2e] flex items-center justify-center mb-3">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|||||||
@ -17,13 +17,13 @@ export class Sidebar implements OnInit {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.chatStore.fetchChats();
|
this.chatStore.fetchChats();
|
||||||
console.log(this.chatStore.chats());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected sidebarClasses = computed(() => {
|
protected sidebarClasses = computed(() => {
|
||||||
const base =
|
const base =
|
||||||
'fixed top-0 right-0 h-full w-64 border-l border-[#1e2f4d] flex flex-col z-40 transition-transform duration-300 ease-in-out shadow-2xl shadow-black/40 relative overflow-hidden';
|
'rounded-l-xl top-0 right-0 h-full border-l border-[#1e2f4d] flex flex-col transition-all duration-300 ease-in-out shadow-2xl shadow-black/40 overflow-hidden';
|
||||||
return this.isOpen() ? base : base + ' translate-x-full';
|
|
||||||
|
return this.isOpen() ? base + ' w-64' : base + ' w-0 border-none opacity-0';
|
||||||
});
|
});
|
||||||
|
|
||||||
protected chatItemClasses(chat: any): string {
|
protected chatItemClasses(chat: any): string {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user