Переглянути джерело

refac: user message styling

Timothy J. Baek 11 місяців тому
батько
коміт
0722e4b690

+ 1 - 1
src/lib/components/chat/Messages/Name.svelte

@@ -1,3 +1,3 @@
-<div class=" self-center font-bold mb-0.5 capitalize line-clamp-1">
+<div class=" self-center font-bold mb-0.5 line-clamp-1">
 	<slot />
 </div>

+ 2 - 2
src/lib/components/chat/Messages/ProfileImage.svelte

@@ -2,6 +2,6 @@
 	export let src = '/user.png';
 </script>
 
-<div class=" mr-4">
-	<img {src} class=" max-w-[28px] object-cover rounded-full" alt="profile" draggable="false" />
+<div class=" mr-3">
+	<img {src} class=" w-8 object-cover rounded-full" alt="profile" draggable="false" />
 </div>

+ 15 - 11
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -338,7 +338,7 @@
 				($i18n.language === 'dg-DG' ? `/doge.png` : `${WEBUI_BASE_URL}/static/favicon.png`)}
 		/>
 
-		<div class="w-full overflow-hidden">
+		<div class="w-full overflow-hidden pl-1">
 			<Name>
 				{#if message.model in modelfiles}
 					{modelfiles[message.model]?.title}
@@ -347,8 +347,10 @@
 				{/if}
 
 				{#if message.timestamp}
-					<span class=" invisible group-hover:visible text-gray-400 text-xs font-medium">
-						{dayjs(message.timestamp * 1000).format($i18n.t('DD/MM/YYYY HH:mm'))}
+					<span
+						class=" self-center invisible group-hover:visible text-gray-400 text-xs font-medium uppercase"
+					>
+						{dayjs(message.timestamp * 1000).format($i18n.t('h:mm a'))}
 					</span>
 				{/if}
 			</Name>
@@ -370,7 +372,7 @@
 			>
 				<div>
 					{#if edit === true}
-						<div class=" w-full">
+						<div class="w-full bg-gray-800 rounded-3xl px-5 py-3 my-2">
 							<textarea
 								id="message-edit-{message.id}"
 								bind:this={editTextAreaElement}
@@ -382,23 +384,25 @@
 								}}
 							/>
 
-							<div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium">
+							<div class=" mt-2 mb-1 flex justify-end space-x-1.5 text-sm font-medium">
 								<button
-									class="px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
+									id="close-edit-message-button"
+									class=" px-4 py-2 bg-gray-900 hover:bg-gray-850 text-gray-100 transition rounded-3xl"
 									on:click={() => {
-										editMessageConfirmHandler();
+										cancelEditMessage();
 									}}
 								>
-									{$i18n.t('Save')}
+									{$i18n.t('Cancel')}
 								</button>
 
 								<button
-									class=" px-4 py-2 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-100 transition outline outline-1 outline-gray-200 dark:outline-gray-600 rounded-lg"
+									id="save-edit-message-button"
+									class="px-4 py-2 bg-white hover:bg-gray-100 text-gray-800 transition rounded-3xl"
 									on:click={() => {
-										cancelEditMessage();
+										editMessageConfirmHandler();
 									}}
 								>
-									{$i18n.t('Cancel')}
+									{$i18n.t('Save')}
 								</button>
 							</div>
 						</div>

+ 71 - 93
src/lib/components/chat/Messages/UserMessage.svelte

@@ -55,48 +55,19 @@
 </script>
 
 <div class=" flex w-full">
-	<ProfileImage
-		src={message.user
-			? $modelfiles.find((modelfile) => modelfile.tagName === message.user)?.imageUrl ?? '/user.png'
-			: user?.profile_image_url ?? '/user.png'}
-	/>
-
 	<div class="w-full overflow-hidden">
-		<div class="user-message">
-			<Name>
-				{#if message.user}
-					{#if $modelfiles.map((modelfile) => modelfile.tagName).includes(message.user)}
-						{$modelfiles.find((modelfile) => modelfile.tagName === message.user)?.title}
-					{:else}
-						{$i18n.t('You')}
-						<span class=" text-gray-500 text-sm font-medium">{message?.user ?? ''}</span>
-					{/if}
-				{:else if $settings.showUsername}
-					{user.name}
-				{:else}
-					{$i18n.t('You')}
-				{/if}
-
-				{#if message.timestamp}
-					<span class=" invisible group-hover:visible text-gray-400 text-xs font-medium">
-						{dayjs(message.timestamp * 1000).format($i18n.t('DD/MM/YYYY HH:mm'))}
-					</span>
-				{/if}
-			</Name>
-		</div>
-
 		<div
-			class="prose chat-{message.role} w-full max-w-full dark:prose-invert prose-headings:my-0 prose-p:my-0 prose-p:-mb-4 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-img:my-0 prose-ul:-my-4 prose-ol:-my-4 prose-li:-my-3 prose-ul:-mb-6 prose-ol:-mb-6 prose-li:-mb-4 whitespace-pre-line"
+			class="prose chat-{message.role} w-full max-w-full flex flex-col justify-end dark:prose-invert prose-headings:my-0 prose-p:my-0 prose-p:-mb-4 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-img:my-0 prose-ul:-my-4 prose-ol:-my-4 prose-li:-my-3 prose-ul:-mb-6 prose-ol:-mb-6 prose-li:-mb-4 whitespace-pre-line"
 		>
 			{#if message.files}
-				<div class="my-2.5 w-full flex overflow-x-auto gap-2 flex-wrap">
+				<div class="mt-2.5 mb-1 w-full flex justify-end overflow-x-auto gap-2 flex-wrap">
 					{#each message.files as file}
 						<div>
 							{#if file.type === 'image'}
 								<img src={file.url} alt="input" class=" max-h-96 rounded-lg" draggable="false" />
 							{:else if file.type === 'doc'}
 								<button
-									class="h-16 w-[15rem] flex items-center space-x-3 px-2.5 dark:bg-gray-600 rounded-xl border border-gray-200 dark:border-none text-left"
+									class="h-16 w-72 flex items-center space-x-3 px-2.5 dark:bg-gray-850 rounded-xl border border-gray-200 dark:border-none text-left"
 									type="button"
 									on:click={() => {
 										if (file?.url) {
@@ -132,7 +103,7 @@
 								</button>
 							{:else if file.type === 'collection'}
 								<button
-									class="h-16 w-[15rem] flex items-center space-x-3 px-2.5 dark:bg-gray-600 rounded-xl border border-gray-200 dark:border-none text-left"
+									class="h-16 w-72 flex items-center space-x-3 px-2.5 dark:bg-gray-600 rounded-xl border border-gray-200 dark:border-none text-left"
 									type="button"
 								>
 									<div class="p-2.5 bg-red-400 text-white rounded-lg">
@@ -166,7 +137,7 @@
 			{/if}
 
 			{#if edit === true}
-				<div class=" w-full">
+				<div class=" w-full bg-gray-800 rounded-3xl px-5 py-3 mb-2">
 					<textarea
 						id="message-edit-{message.id}"
 						bind:this={messageEditTextAreaElement}
@@ -190,81 +161,41 @@
 						}}
 					/>
 
-					<div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium">
+					<div class=" mt-2 mb-1 flex justify-end space-x-1.5 text-sm font-medium">
 						<button
-							id="save-edit-message-button"
-							class="px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
+							id="close-edit-message-button"
+							class=" px-4 py-2 bg-gray-900 hover:bg-gray-850 text-gray-100 transition rounded-3xl"
 							on:click={() => {
-								editMessageConfirmHandler();
+								cancelEditMessage();
 							}}
 						>
-							{$i18n.t('Save & Submit')}
+							{$i18n.t('Cancel')}
 						</button>
 
 						<button
-							id="close-edit-message-button"
-							class=" px-4 py-2 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-100 transition outline outline-1 outline-gray-200 dark:outline-gray-600 rounded-lg"
+							id="save-edit-message-button"
+							class="px-4 py-2 bg-white hover:bg-gray-100 text-gray-800 transition rounded-3xl"
 							on:click={() => {
-								cancelEditMessage();
+								editMessageConfirmHandler();
 							}}
 						>
-							{$i18n.t('Cancel')}
+							{$i18n.t('Send')}
 						</button>
 					</div>
 				</div>
 			{:else}
 				<div class="w-full">
-					<pre id="user-message">{message.content}</pre>
-
-					<div class=" flex justify-start space-x-1 text-gray-700 dark:text-gray-500">
-						{#if siblings.length > 1}
-							<div class="flex self-center">
-								<button
-									class="self-center dark:hover:text-white hover:text-black transition"
-									on:click={() => {
-										showPreviousMessage(message);
-									}}
-								>
-									<svg
-										xmlns="http://www.w3.org/2000/svg"
-										viewBox="0 0 20 20"
-										fill="currentColor"
-										class="w-4 h-4"
-									>
-										<path
-											fill-rule="evenodd"
-											d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
-											clip-rule="evenodd"
-										/>
-									</svg>
-								</button>
-
-								<div class="text-xs font-bold self-center dark:text-gray-100">
-									{siblings.indexOf(message.id) + 1} / {siblings.length}
-								</div>
-
-								<button
-									class="self-center dark:hover:text-white hover:text-black transition"
-									on:click={() => {
-										showNextMessage(message);
-									}}
-								>
-									<svg
-										xmlns="http://www.w3.org/2000/svg"
-										viewBox="0 0 20 20"
-										fill="currentColor"
-										class="w-4 h-4"
-									>
-										<path
-											fill-rule="evenodd"
-											d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
-											clip-rule="evenodd"
-										/>
-									</svg>
-								</button>
-							</div>
-						{/if}
+					<div class="flex justify-end mb-2">
+						<div
+							class="rounded-3xl px-5 py-2 max-w-[90%] bg-gray-850 {message.files
+								? 'rounded-tr-lg'
+								: ''}"
+						>
+							<pre id="user-message">{message.content}</pre>
+						</div>
+					</div>
 
+					<div class=" flex justify-end space-x-1 text-gray-700 dark:text-gray-500">
 						{#if !readOnly}
 							<Tooltip content={$i18n.t('Edit')} placement="bottom">
 								<button
@@ -340,6 +271,53 @@
 								</button>
 							</Tooltip>
 						{/if}
+						{#if siblings.length > 1}
+							<div class="flex self-center">
+								<button
+									class="self-center dark:hover:text-white hover:text-black transition"
+									on:click={() => {
+										showPreviousMessage(message);
+									}}
+								>
+									<svg
+										xmlns="http://www.w3.org/2000/svg"
+										viewBox="0 0 20 20"
+										fill="currentColor"
+										class="w-4 h-4"
+									>
+										<path
+											fill-rule="evenodd"
+											d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
+											clip-rule="evenodd"
+										/>
+									</svg>
+								</button>
+
+								<div class="text-xs font-bold self-center dark:text-gray-100">
+									{siblings.indexOf(message.id) + 1} / {siblings.length}
+								</div>
+
+								<button
+									class="self-center dark:hover:text-white hover:text-black transition"
+									on:click={() => {
+										showNextMessage(message);
+									}}
+								>
+									<svg
+										xmlns="http://www.w3.org/2000/svg"
+										viewBox="0 0 20 20"
+										fill="currentColor"
+										class="w-4 h-4"
+									>
+										<path
+											fill-rule="evenodd"
+											d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
+											clip-rule="evenodd"
+										/>
+									</svg>
+								</button>
+							</div>
+						{/if}
 					</div>
 				</div>
 			{/if}

+ 3 - 32
src/lib/components/layout/Navbar.svelte

@@ -68,37 +68,7 @@
 			<div class="self-start flex flex-none items-center text-gray-600 dark:text-gray-400">
 				<!-- <div class="md:hidden flex self-center w-[1px] h-5 mx-2 bg-gray-300 dark:bg-stone-700" /> -->
 
-				{#if !shareEnabled}
-					<Tooltip content={$i18n.t('Settings')}>
-						<button
-							class="hidden md:flex cursor-pointer px-2 py-2 rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
-							id="open-settings-button"
-							on:click={async () => {
-								await showSettings.set(!$showSettings);
-							}}
-						>
-							<svg
-								xmlns="http://www.w3.org/2000/svg"
-								fill="none"
-								viewBox="0 0 24 24"
-								stroke-width="1.5"
-								stroke="currentColor"
-								class="w-5 h-5"
-							>
-								<path
-									stroke-linecap="round"
-									stroke-linejoin="round"
-									d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z"
-								/>
-								<path
-									stroke-linecap="round"
-									stroke-linejoin="round"
-									d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
-								/>
-							</svg>
-						</button>
-					</Tooltip>
-				{:else}
+				{#if shareEnabled}
 					<Menu
 						{chat}
 						{shareEnabled}
@@ -159,8 +129,9 @@
 					</button>
 				</Tooltip>
 
-				{#if !$mobile && $user !== undefined}
+				{#if $user !== undefined}
 					<UserMenu
+						className="max-w-[200px]"
 						role={$user.role}
 						on:show={(e) => {
 							if (e.detail === 'archived-chat') {

+ 66 - 68
src/lib/components/layout/Navbar/Menu.svelte

@@ -82,7 +82,7 @@
 			align="end"
 			transition={flyAndScale}
 		>
-			<DropdownMenu.Item
+			<!-- <DropdownMenu.Item
 				class="flex gap-2 items-center px-3 py-2 text-sm  cursor-pointer dark:hover:bg-gray-800 rounded-md"
 				on:click={async () => {
 					await showSettings.set(!$showSettings);
@@ -108,89 +108,88 @@
 					/>
 				</svg>
 				<div class="flex items-center">{$i18n.t('Settings')}</div>
+			</DropdownMenu.Item> -->
+
+			<DropdownMenu.Item
+				class="flex gap-2 items-center px-3 py-2 text-sm  cursor-pointer dark:hover:bg-gray-800 rounded-md"
+				on:click={() => {
+					shareHandler();
+				}}
+			>
+				<svg
+					xmlns="http://www.w3.org/2000/svg"
+					viewBox="0 0 24 24"
+					fill="currentColor"
+					class="size-4"
+				>
+					<path
+						fill-rule="evenodd"
+						d="M15.75 4.5a3 3 0 1 1 .825 2.066l-8.421 4.679a3.002 3.002 0 0 1 0 1.51l8.421 4.679a3 3 0 1 1-.729 1.31l-8.421-4.678a3 3 0 1 1 0-4.132l8.421-4.679a3 3 0 0 1-.096-.755Z"
+						clip-rule="evenodd"
+					/>
+				</svg>
+				<div class="flex items-center">{$i18n.t('Share')}</div>
 			</DropdownMenu.Item>
 
-			{#if shareEnabled}
-				<DropdownMenu.Item
-					class="flex gap-2 items-center px-3 py-2 text-sm  cursor-pointer dark:hover:bg-gray-800 rounded-md"
+			<!-- <DropdownMenu.Item
+					class="flex gap-2 items-center px-3 py-2 text-sm  font-medium cursor-pointer"
 					on:click={() => {
-						shareHandler();
+						downloadHandler();
 					}}
+				/> -->
+			<DropdownMenu.Sub>
+				<DropdownMenu.SubTrigger
+					class="flex gap-2 items-center px-3 py-2 text-sm  cursor-pointer dark:hover:bg-gray-800 rounded-md"
 				>
 					<svg
 						xmlns="http://www.w3.org/2000/svg"
+						fill="none"
 						viewBox="0 0 24 24"
-						fill="currentColor"
+						stroke-width="1.5"
+						stroke="currentColor"
 						class="size-4"
 					>
 						<path
-							fill-rule="evenodd"
-							d="M15.75 4.5a3 3 0 1 1 .825 2.066l-8.421 4.679a3.002 3.002 0 0 1 0 1.51l8.421 4.679a3 3 0 1 1-.729 1.31l-8.421-4.678a3 3 0 1 1 0-4.132l8.421-4.679a3 3 0 0 1-.096-.755Z"
-							clip-rule="evenodd"
+							stroke-linecap="round"
+							stroke-linejoin="round"
+							d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3"
 						/>
 					</svg>
-					<div class="flex items-center">{$i18n.t('Share')}</div>
-				</DropdownMenu.Item>
 
-				<!-- <DropdownMenu.Item
-					class="flex gap-2 items-center px-3 py-2 text-sm  font-medium cursor-pointer"
-					on:click={() => {
-						downloadHandler();
-					}}
-				/> -->
-				<DropdownMenu.Sub>
-					<DropdownMenu.SubTrigger
+					<div class="flex items-center">{$i18n.t('Download')}</div>
+				</DropdownMenu.SubTrigger>
+				<DropdownMenu.SubContent
+					class="w-full rounded-lg px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg"
+					transition={flyAndScale}
+					sideOffset={8}
+				>
+					<DropdownMenu.Item
 						class="flex gap-2 items-center px-3 py-2 text-sm  cursor-pointer dark:hover:bg-gray-800 rounded-md"
+						on:click={() => {
+							downloadTxt();
+						}}
 					>
-						<svg
-							xmlns="http://www.w3.org/2000/svg"
-							fill="none"
-							viewBox="0 0 24 24"
-							stroke-width="1.5"
-							stroke="currentColor"
-							class="size-4"
-						>
-							<path
-								stroke-linecap="round"
-								stroke-linejoin="round"
-								d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3"
-							/>
-						</svg>
-
-						<div class="flex items-center">{$i18n.t('Download')}</div>
-					</DropdownMenu.SubTrigger>
-					<DropdownMenu.SubContent
-						class="w-full rounded-lg px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg"
-						transition={flyAndScale}
-						sideOffset={8}
+						<div class="flex items-center line-clamp-1">{$i18n.t('Plain text (.txt)')}</div>
+					</DropdownMenu.Item>
+
+					<DropdownMenu.Item
+						class="flex gap-2 items-center px-3 py-2 text-sm  cursor-pointer dark:hover:bg-gray-800 rounded-md"
+						on:click={() => {
+							downloadPdf();
+						}}
 					>
-						<DropdownMenu.Item
-							class="flex gap-2 items-center px-3 py-2 text-sm  cursor-pointer dark:hover:bg-gray-800 rounded-md"
-							on:click={() => {
-								downloadTxt();
-							}}
-						>
-							<div class="flex items-center line-clamp-1">{$i18n.t('Plain text (.txt)')}</div>
-						</DropdownMenu.Item>
-
-						<DropdownMenu.Item
-							class="flex gap-2 items-center px-3 py-2 text-sm  cursor-pointer dark:hover:bg-gray-800 rounded-md"
-							on:click={() => {
-								downloadPdf();
-							}}
-						>
-							<div class="flex items-center line-clamp-1">{$i18n.t('PDF document (.pdf)')}</div>
-						</DropdownMenu.Item>
-					</DropdownMenu.SubContent>
-				</DropdownMenu.Sub>
-
-				<hr class="border-gray-100 dark:border-gray-800 mt-2.5 mb-1.5" />
-
-				<div class="flex p-1">
-					<Tags chatId={chat.id} />
-				</div>
-
-				<!-- <DropdownMenu.Item
+						<div class="flex items-center line-clamp-1">{$i18n.t('PDF document (.pdf)')}</div>
+					</DropdownMenu.Item>
+				</DropdownMenu.SubContent>
+			</DropdownMenu.Sub>
+
+			<hr class="border-gray-100 dark:border-gray-800 mt-2.5 mb-1.5" />
+
+			<div class="flex p-1">
+				<Tags chatId={chat.id} />
+			</div>
+
+			<!-- <DropdownMenu.Item
 					class="flex  gap-2  items-center px-3 py-2 text-sm  font-medium cursor-pointer"
 					on:click={() => {
 						tagHandler();
@@ -214,7 +213,6 @@
 
 					<div class="flex items-center">Tag</div>
 				</DropdownMenu.Item> -->
-			{/if}
 		</DropdownMenu.Content>
 	</div>
 </Dropdown>

+ 34 - 25
src/lib/components/layout/Sidebar.svelte

@@ -218,32 +218,9 @@
 			: 'invisible'}"
 	>
 		<div class="px-2.5 flex justify-between space-x-1 text-gray-600 dark:text-gray-400">
-			<button
-				class=" cursor-pointer px-2 py-2 flex rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
-				on:click={() => {
-					showSidebar.set(!$showSidebar);
-				}}
-			>
-				<div class=" m-auto self-center">
-					<svg
-						xmlns="http://www.w3.org/2000/svg"
-						fill="none"
-						viewBox="0 0 24 24"
-						stroke-width="2"
-						stroke="currentColor"
-						class="size-5"
-					>
-						<path
-							stroke-linecap="round"
-							stroke-linejoin="round"
-							d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25H12"
-						/>
-					</svg>
-				</div>
-			</button>
 			<a
 				id="sidebar-new-chat-button"
-				class="flex justify-between rounded-xl px-2 py-2 hover:bg-gray-100 dark:hover:bg-gray-850 transition"
+				class="flex flex-1 justify-between rounded-xl px-2 py-2 hover:bg-gray-100 dark:hover:bg-gray-850 transition"
 				href="/"
 				on:click={async () => {
 					selectedChatId = null;
@@ -259,7 +236,15 @@
 					}, 0);
 				}}
 			>
-				<div class="self-center">
+				<div class="self-center mx-1.5">
+					<img
+						src="{WEBUI_BASE_URL}/static/favicon.png"
+						class=" size-6 -translate-x-1.5 rounded-full"
+						alt="logo"
+					/>
+				</div>
+				<div class=" self-center font-medium text-sm dark:text-white">{$i18n.t('New Chat')}</div>
+				<div class="self-center ml-auto">
 					<svg
 						xmlns="http://www.w3.org/2000/svg"
 						viewBox="0 0 20 20"
@@ -275,6 +260,30 @@
 					</svg>
 				</div>
 			</a>
+
+			<button
+				class=" cursor-pointer px-2 py-2 flex rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
+				on:click={() => {
+					showSidebar.set(!$showSidebar);
+				}}
+			>
+				<div class=" m-auto self-center">
+					<svg
+						xmlns="http://www.w3.org/2000/svg"
+						fill="none"
+						viewBox="0 0 24 24"
+						stroke-width="2"
+						stroke="currentColor"
+						class="size-5"
+					>
+						<path
+							stroke-linecap="round"
+							stroke-linejoin="round"
+							d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25H12"
+						/>
+					</svg>
+				</div>
+			</button>
 		</div>
 
 		{#if $user?.role === 'admin'}

+ 45 - 44
src/lib/components/layout/Sidebar/UserMenu.svelte

@@ -12,6 +12,7 @@
 
 	export let show = false;
 	export let role = '';
+	export let className = 'max-w-[240px]';
 
 	const dispatch = createEventDispatcher();
 </script>
@@ -28,55 +29,14 @@
 
 	<slot name="content">
 		<DropdownMenu.Content
-			class="w-full max-w-[240px] text-sm rounded-xl px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-850 dark:text-white shadow"
+			class="w-full {className} text-sm rounded-xl px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-850 dark:text-white shadow"
 			sideOffset={8}
 			side="bottom"
 			align="start"
 			transition={(e) => fade(e, { duration: 100 })}
 		>
-			{#if role === 'admin'}
-				<button
-					class="flex rounded-md py-2.5 px-3.5 w-full hover:bg-gray-100 dark:hover:bg-gray-800 transition"
-					on:click={() => {
-						goto('/admin');
-						show = false;
-					}}
-				>
-					<div class=" self-center mr-3">
-						<svg
-							xmlns="http://www.w3.org/2000/svg"
-							fill="none"
-							viewBox="0 0 24 24"
-							stroke-width="1.5"
-							stroke="currentColor"
-							class="w-5 h-5"
-						>
-							<path
-								stroke-linecap="round"
-								stroke-linejoin="round"
-								d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z"
-							/>
-						</svg>
-					</div>
-					<div class=" self-center font-medium">{$i18n.t('Admin Panel')}</div>
-				</button>
-			{/if}
-
-			<button
-				class="flex rounded-md py-2.5 px-3.5 w-full hover:bg-gray-100 dark:hover:bg-gray-800 transition"
-				on:click={() => {
-					dispatch('show', 'archived-chat');
-					show = false;
-				}}
-			>
-				<div class=" self-center mr-3">
-					<ArchiveBox className="size-5" strokeWidth="1.5" />
-				</div>
-				<div class=" self-center font-medium">{$i18n.t('Archived Chats')}</div>
-			</button>
-
 			<button
-				class="flex rounded-md py-2.5 px-3.5 w-full hover:bg-gray-100 dark:hover:bg-gray-800 transition"
+				class="flex rounded-md py-2 px-3 w-full hover:bg-gray-100 dark:hover:bg-gray-800 transition"
 				on:click={async () => {
 					await showSettings.set(true);
 					show = false;
@@ -106,10 +66,51 @@
 				<div class=" self-center font-medium">{$i18n.t('Settings')}</div>
 			</button>
 
+			<button
+				class="flex rounded-md py-2 px-3 w-full hover:bg-gray-100 dark:hover:bg-gray-800 transition"
+				on:click={() => {
+					dispatch('show', 'archived-chat');
+					show = false;
+				}}
+			>
+				<div class=" self-center mr-3">
+					<ArchiveBox className="size-5" strokeWidth="1.5" />
+				</div>
+				<div class=" self-center font-medium">{$i18n.t('Archived Chats')}</div>
+			</button>
+
+			{#if role === 'admin'}
+				<button
+					class="flex rounded-md py-2 px-3 w-full hover:bg-gray-100 dark:hover:bg-gray-800 transition"
+					on:click={() => {
+						goto('/admin');
+						show = false;
+					}}
+				>
+					<div class=" self-center mr-3">
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							fill="none"
+							viewBox="0 0 24 24"
+							stroke-width="1.5"
+							stroke="currentColor"
+							class="w-5 h-5"
+						>
+							<path
+								stroke-linecap="round"
+								stroke-linejoin="round"
+								d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z"
+							/>
+						</svg>
+					</div>
+					<div class=" self-center font-medium">{$i18n.t('Admin Panel')}</div>
+				</button>
+			{/if}
+
 			<hr class=" dark:border-gray-800 my-2 p-0" />
 
 			<button
-				class="flex rounded-md py-2.5 px-3.5 w-full hover:bg-gray-100 dark:hover:bg-gray-800 transition"
+				class="flex rounded-md py-2 px-3 w-full hover:bg-gray-100 dark:hover:bg-gray-800 transition"
 				on:click={() => {
 					localStorage.removeItem('token');
 					location.href = '/auth';