forked from open-webui/open-webui
		
	refac: styling
This commit is contained in:
		
							parent
							
								
									db08ad964c
								
							
						
					
					
						commit
						e99d69bfe2
					
				
					 8 changed files with 163 additions and 132 deletions
				
			
		|  | @ -55,6 +55,11 @@ | |||
| 	let isRecording = false; | ||||
| 	const MIN_DECIBELS = -45; | ||||
| 
 | ||||
| 	const scrollToBottom = () => { | ||||
| 		const element = document.getElementById('messages-container'); | ||||
| 		element.scrollTop = element.scrollHeight; | ||||
| 	}; | ||||
| 
 | ||||
| 	const startRecording = async () => { | ||||
| 		const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); | ||||
| 		mediaRecorder = new MediaRecorder(stream); | ||||
|  | @ -371,17 +376,17 @@ | |||
| 	</div> | ||||
| {/if} | ||||
| 
 | ||||
| <div class="w-full pt-2 md:pt-0"> | ||||
| 	<div class="px-2.5 pt-2.5 -mb-0.5 mx-auto inset-x-0 bg-transparent flex justify-center"> | ||||
| <div class="w-full"> | ||||
| 	<div class="px-2.5 -mb-0.5 mx-auto inset-x-0 bg-transparent flex justify-center"> | ||||
| 		<div class="flex flex-col max-w-3xl w-full"> | ||||
| 			<div> | ||||
| 			<div class="relative"> | ||||
| 				{#if autoScroll === false && messages.length > 0} | ||||
| 					<div class=" flex justify-center mb-4"> | ||||
| 					<div class=" absolute -top-12 left-0 right-0 flex justify-center"> | ||||
| 						<button | ||||
| 							class=" bg-white border border-gray-100 dark:border-none dark:bg-white/20 p-1.5 rounded-full" | ||||
| 							on:click={() => { | ||||
| 								autoScroll = true; | ||||
| 								window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); | ||||
| 								scrollToBottom(); | ||||
| 							}} | ||||
| 						> | ||||
| 							<svg | ||||
|  | @ -401,7 +406,7 @@ | |||
| 				{/if} | ||||
| 			</div> | ||||
| 
 | ||||
| 			<div class="w-full"> | ||||
| 			<div class="w-full relative"> | ||||
| 				{#if prompt.charAt(0) === '/'} | ||||
| 					<Prompts bind:this={promptsElement} bind:prompt /> | ||||
| 				{:else if prompt.charAt(0) === '#'} | ||||
|  | @ -432,14 +437,16 @@ | |||
| 						bind:chatInputPlaceholder | ||||
| 						{messages} | ||||
| 					/> | ||||
| 				{:else if messages.length == 0 && suggestionPrompts.length !== 0} | ||||
| 				{/if} | ||||
| 
 | ||||
| 				{#if messages.length == 0 && suggestionPrompts.length !== 0} | ||||
| 					<Suggestions {suggestionPrompts} {submitPrompt} /> | ||||
| 				{/if} | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<div class="bg-white dark:bg-gray-900"> | ||||
| 		<div class="max-w-3xl px-2.5 -mb-0.5 mx-auto inset-x-0"> | ||||
| 		<div class="max-w-3xl px-2.5 mx-auto inset-x-0"> | ||||
| 			<div class=" pb-2"> | ||||
| 				<input | ||||
| 					bind:this={filesInputElement} | ||||
|  |  | |||
|  | @ -88,7 +88,7 @@ | |||
| </script> | ||||
| 
 | ||||
| {#if filteredItems.length > 0 || prompt.split(' ')?.at(0)?.substring(1).startsWith('http')} | ||||
| 	<div class="md:px-2 mb-3 text-left w-full"> | ||||
| 	<div class="md:px-2 mb-3 text-left w-full absolute bottom-0 left-0 right-0"> | ||||
| 		<div class="flex w-full rounded-lg border border-gray-100 dark:border-gray-700"> | ||||
| 			<div class=" bg-gray-100 dark:bg-gray-700 w-10 rounded-l-lg text-center"> | ||||
| 				<div class=" text-lg font-semibold mt-2">#</div> | ||||
|  |  | |||
|  | @ -120,7 +120,7 @@ | |||
| </script> | ||||
| 
 | ||||
| {#if filteredModels.length > 0} | ||||
| 	<div class="md:px-2 mb-3 text-left w-full"> | ||||
| 	<div class="md:px-2 mb-3 text-left w-full absolute bottom-0 left-0 right-0"> | ||||
| 		<div class="flex w-full rounded-lg border border-gray-100 dark:border-gray-700"> | ||||
| 			<div class=" bg-gray-100 dark:bg-gray-700 w-10 rounded-l-lg text-center"> | ||||
| 				<div class=" text-lg font-semibold mt-2">@</div> | ||||
|  |  | |||
|  | @ -47,7 +47,7 @@ | |||
| </script> | ||||
| 
 | ||||
| {#if filteredPromptCommands.length > 0} | ||||
| 	<div class="md:px-2 mb-3 text-left w-full"> | ||||
| 	<div class="md:px-2 mb-3 text-left w-full absolute bottom-0 left-0 right-0"> | ||||
| 		<div class="flex w-full rounded-lg border border-gray-100 dark:border-gray-700"> | ||||
| 			<div class=" bg-gray-100 dark:bg-gray-700 w-10 rounded-l-lg text-center"> | ||||
| 				<div class=" text-lg font-semibold mt-2">/</div> | ||||
|  |  | |||
|  | @ -29,10 +29,16 @@ | |||
| 	$: if (autoScroll && bottomPadding) { | ||||
| 		(async () => { | ||||
| 			await tick(); | ||||
| 			window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); | ||||
| 
 | ||||
| 			scrollToBottom(); | ||||
| 		})(); | ||||
| 	} | ||||
| 
 | ||||
| 	const scrollToBottom = () => { | ||||
| 		const element = document.getElementById('messages-container'); | ||||
| 		element.scrollTop = element.scrollHeight; | ||||
| 	}; | ||||
| 
 | ||||
| 	const copyToClipboard = (text) => { | ||||
| 		if (!navigator.clipboard) { | ||||
| 			var textArea = document.createElement('textarea'); | ||||
|  | @ -160,10 +166,11 @@ | |||
| 
 | ||||
| 		await tick(); | ||||
| 
 | ||||
| 		autoScroll = window.innerHeight + window.scrollY >= document.body.offsetHeight - 40; | ||||
| 		const element = document.getElementById('messages-container'); | ||||
| 		autoScroll = element.scrollHeight - element.scrollTop === element.clientHeight - 40; | ||||
| 
 | ||||
| 		setTimeout(() => { | ||||
| 			window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); | ||||
| 			scrollToBottom(); | ||||
| 		}, 100); | ||||
| 	}; | ||||
| 
 | ||||
|  | @ -208,9 +215,11 @@ | |||
| 
 | ||||
| 		await tick(); | ||||
| 
 | ||||
| 		autoScroll = window.innerHeight + window.scrollY >= document.body.offsetHeight - 40; | ||||
| 		const element = document.getElementById('messages-container'); | ||||
| 		autoScroll = element.scrollHeight - element.scrollTop === element.clientHeight - 40; | ||||
| 
 | ||||
| 		setTimeout(() => { | ||||
| 			window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); | ||||
| 			scrollToBottom(); | ||||
| 		}, 100); | ||||
| 	}; | ||||
| </script> | ||||
|  | @ -218,95 +227,97 @@ | |||
| {#if messages.length == 0} | ||||
| 	<Placeholder models={selectedModels} modelfiles={selectedModelfiles} /> | ||||
| {:else} | ||||
| 	{#key chatId} | ||||
| 		{#each messages as message, messageIdx} | ||||
| 			<div class=" w-full"> | ||||
| 				<div | ||||
| 					class="flex flex-col justify-between px-5 mb-3 {$settings?.fullScreenMode ?? null | ||||
| 						? 'max-w-full' | ||||
| 						: 'max-w-3xl'} mx-auto rounded-lg group" | ||||
| 				> | ||||
| 					{#if message.role === 'user'} | ||||
| 						<UserMessage | ||||
| 							user={$user} | ||||
| 							{message} | ||||
| 							siblings={message.parentId !== null | ||||
| 								? history.messages[message.parentId]?.childrenIds ?? [] | ||||
| 								: Object.values(history.messages) | ||||
| 										.filter((message) => message.parentId === null) | ||||
| 										.map((message) => message.id) ?? []} | ||||
| 							{confirmEditMessage} | ||||
| 							{showPreviousMessage} | ||||
| 							{showNextMessage} | ||||
| 							{copyToClipboard} | ||||
| 						/> | ||||
| 	<div class=" pb-10"> | ||||
| 		{#key chatId} | ||||
| 			{#each messages as message, messageIdx} | ||||
| 				<div class=" w-full"> | ||||
| 					<div | ||||
| 						class="flex flex-col justify-between px-5 mb-3 {$settings?.fullScreenMode ?? null | ||||
| 							? 'max-w-full' | ||||
| 							: 'max-w-3xl'} mx-auto rounded-lg group" | ||||
| 					> | ||||
| 						{#if message.role === 'user'} | ||||
| 							<UserMessage | ||||
| 								user={$user} | ||||
| 								{message} | ||||
| 								siblings={message.parentId !== null | ||||
| 									? history.messages[message.parentId]?.childrenIds ?? [] | ||||
| 									: Object.values(history.messages) | ||||
| 											.filter((message) => message.parentId === null) | ||||
| 											.map((message) => message.id) ?? []} | ||||
| 								{confirmEditMessage} | ||||
| 								{showPreviousMessage} | ||||
| 								{showNextMessage} | ||||
| 								{copyToClipboard} | ||||
| 							/> | ||||
| 
 | ||||
| 						{#if messages.length - 1 === messageIdx && processing !== ''} | ||||
| 							<div class="flex my-2.5 ml-12 items-center w-fit space-x-2.5"> | ||||
| 								<div class=" dark:text-blue-100"> | ||||
| 									<svg | ||||
| 										class=" w-4 h-4 translate-y-[0.5px]" | ||||
| 										fill="currentColor" | ||||
| 										viewBox="0 0 24 24" | ||||
| 										xmlns="http://www.w3.org/2000/svg" | ||||
| 										><style> | ||||
| 											.spinner_qM83 { | ||||
| 												animation: spinner_8HQG 1.05s infinite; | ||||
| 											} | ||||
| 											.spinner_oXPr { | ||||
| 												animation-delay: 0.1s; | ||||
| 											} | ||||
| 											.spinner_ZTLf { | ||||
| 												animation-delay: 0.2s; | ||||
| 											} | ||||
| 											@keyframes spinner_8HQG { | ||||
| 												0%, | ||||
| 												57.14% { | ||||
| 													animation-timing-function: cubic-bezier(0.33, 0.66, 0.66, 1); | ||||
| 													transform: translate(0); | ||||
| 							{#if messages.length - 1 === messageIdx && processing !== ''} | ||||
| 								<div class="flex my-2.5 ml-12 items-center w-fit space-x-2.5"> | ||||
| 									<div class=" dark:text-blue-100"> | ||||
| 										<svg | ||||
| 											class=" w-4 h-4 translate-y-[0.5px]" | ||||
| 											fill="currentColor" | ||||
| 											viewBox="0 0 24 24" | ||||
| 											xmlns="http://www.w3.org/2000/svg" | ||||
| 											><style> | ||||
| 												.spinner_qM83 { | ||||
| 													animation: spinner_8HQG 1.05s infinite; | ||||
| 												} | ||||
| 												28.57% { | ||||
| 													animation-timing-function: cubic-bezier(0.33, 0, 0.66, 0.33); | ||||
| 													transform: translateY(-6px); | ||||
| 												.spinner_oXPr { | ||||
| 													animation-delay: 0.1s; | ||||
| 												} | ||||
| 												100% { | ||||
| 													transform: translate(0); | ||||
| 												.spinner_ZTLf { | ||||
| 													animation-delay: 0.2s; | ||||
| 												} | ||||
| 											} | ||||
| 										</style><circle class="spinner_qM83" cx="4" cy="12" r="2.5" /><circle | ||||
| 											class="spinner_qM83 spinner_oXPr" | ||||
| 											cx="12" | ||||
| 											cy="12" | ||||
| 											r="2.5" | ||||
| 										/><circle class="spinner_qM83 spinner_ZTLf" cx="20" cy="12" r="2.5" /></svg | ||||
| 									> | ||||
| 												@keyframes spinner_8HQG { | ||||
| 													0%, | ||||
| 													57.14% { | ||||
| 														animation-timing-function: cubic-bezier(0.33, 0.66, 0.66, 1); | ||||
| 														transform: translate(0); | ||||
| 													} | ||||
| 													28.57% { | ||||
| 														animation-timing-function: cubic-bezier(0.33, 0, 0.66, 0.33); | ||||
| 														transform: translateY(-6px); | ||||
| 													} | ||||
| 													100% { | ||||
| 														transform: translate(0); | ||||
| 													} | ||||
| 												} | ||||
| 											</style><circle class="spinner_qM83" cx="4" cy="12" r="2.5" /><circle | ||||
| 												class="spinner_qM83 spinner_oXPr" | ||||
| 												cx="12" | ||||
| 												cy="12" | ||||
| 												r="2.5" | ||||
| 											/><circle class="spinner_qM83 spinner_ZTLf" cx="20" cy="12" r="2.5" /></svg | ||||
| 										> | ||||
| 									</div> | ||||
| 									<div class=" text-sm font-medium"> | ||||
| 										{processing} | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class=" text-sm font-medium"> | ||||
| 									{processing} | ||||
| 								</div> | ||||
| 							</div> | ||||
| 							{/if} | ||||
| 						{:else} | ||||
| 							<ResponseMessage | ||||
| 								{message} | ||||
| 								modelfiles={selectedModelfiles} | ||||
| 								siblings={history.messages[message.parentId]?.childrenIds ?? []} | ||||
| 								isLastMessage={messageIdx + 1 === messages.length} | ||||
| 								{confirmEditResponseMessage} | ||||
| 								{showPreviousMessage} | ||||
| 								{showNextMessage} | ||||
| 								{rateMessage} | ||||
| 								{copyToClipboard} | ||||
| 								{continueGeneration} | ||||
| 								{regenerateResponse} | ||||
| 							/> | ||||
| 						{/if} | ||||
| 					{:else} | ||||
| 						<ResponseMessage | ||||
| 							{message} | ||||
| 							modelfiles={selectedModelfiles} | ||||
| 							siblings={history.messages[message.parentId]?.childrenIds ?? []} | ||||
| 							isLastMessage={messageIdx + 1 === messages.length} | ||||
| 							{confirmEditResponseMessage} | ||||
| 							{showPreviousMessage} | ||||
| 							{showNextMessage} | ||||
| 							{rateMessage} | ||||
| 							{copyToClipboard} | ||||
| 							{continueGeneration} | ||||
| 							{regenerateResponse} | ||||
| 						/> | ||||
| 					{/if} | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		{/each} | ||||
| 			{/each} | ||||
| 
 | ||||
| 		{#if bottomPadding} | ||||
| 			<div class=" mb-10" /> | ||||
| 		{/if} | ||||
| 	{/key} | ||||
| 			{#if bottomPadding} | ||||
| 				<div class=" mb-10" /> | ||||
| 			{/if} | ||||
| 		{/key} | ||||
| 	</div> | ||||
| {/if} | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ | |||
| </script> | ||||
| 
 | ||||
| {#if models.length > 0} | ||||
| 	<div class="m-auto text-center max-w-md pb-56 px-2"> | ||||
| 	<div class="m-auto text-center max-w-md px-2"> | ||||
| 		<div class="flex justify-center mt-8"> | ||||
| 			<div class="flex -space-x-4 mb-1"> | ||||
| 				{#each models as model, modelIdx} | ||||
|  |  | |||
|  | @ -137,6 +137,11 @@ | |||
| 		}); | ||||
| 	}; | ||||
| 
 | ||||
| 	const scrollToBottom = () => { | ||||
| 		const element = document.getElementById('messages-container'); | ||||
| 		element.scrollTop = element.scrollHeight; | ||||
| 	}; | ||||
| 
 | ||||
| 	////////////////////////// | ||||
| 	// Ollama functions | ||||
| 	////////////////////////// | ||||
|  | @ -316,7 +321,7 @@ | |||
| 		await tick(); | ||||
| 
 | ||||
| 		// Scroll down | ||||
| 		window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 		scrollToBottom(); | ||||
| 
 | ||||
| 		const messagesBody = [ | ||||
| 			$settings.system | ||||
|  | @ -469,7 +474,7 @@ | |||
| 				} | ||||
| 
 | ||||
| 				if (autoScroll) { | ||||
| 					window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 					scrollToBottom(); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
|  | @ -508,7 +513,7 @@ | |||
| 		await tick(); | ||||
| 
 | ||||
| 		if (autoScroll) { | ||||
| 			window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 			scrollToBottom(); | ||||
| 		} | ||||
| 
 | ||||
| 		if (messages.length == 2 && messages.at(1).content !== '') { | ||||
|  | @ -519,8 +524,7 @@ | |||
| 
 | ||||
| 	const sendPromptOpenAI = async (model, userPrompt, responseMessageId, _chatId) => { | ||||
| 		const responseMessage = history.messages[responseMessageId]; | ||||
| 
 | ||||
| 		window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 		scrollToBottom(); | ||||
| 
 | ||||
| 		const res = await generateOpenAIChatCompletion(localStorage.token, { | ||||
| 			model: model, | ||||
|  | @ -628,7 +632,7 @@ | |||
| 				} | ||||
| 
 | ||||
| 				if (autoScroll) { | ||||
| 					window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 					scrollToBottom(); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
|  | @ -672,7 +676,7 @@ | |||
| 		await tick(); | ||||
| 
 | ||||
| 		if (autoScroll) { | ||||
| 			window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 			scrollToBottom(); | ||||
| 		} | ||||
| 
 | ||||
| 		if (messages.length == 2) { | ||||
|  | @ -783,16 +787,18 @@ | |||
| 	}; | ||||
| </script> | ||||
| 
 | ||||
| <svelte:window | ||||
| 	on:scroll={(e) => { | ||||
| 		autoScroll = window.innerHeight + window.scrollY >= document.body.offsetHeight - 40; | ||||
| 	}} | ||||
| /> | ||||
| 
 | ||||
| <div class="min-h-screen w-full flex flex-col"> | ||||
| <div class="min-h-screen max-h-screen w-full flex flex-col"> | ||||
| 	<Navbar {title} shareEnabled={messages.length > 0} {initNewChat} {tags} {addTag} {deleteTag} /> | ||||
| 	<div class="flex flex-col justify-center h-full"> | ||||
| 		<div class=" pb-2.5 flex flex-1 flex-col justify-between w-full overflow-hidden"> | ||||
| 	<div class="flex flex-col flex-auto"> | ||||
| 		<div | ||||
| 			class=" pb-2.5 flex flex-col justify-between w-full flex-auto overflow-auto h-80" | ||||
| 			id="messages-container" | ||||
| 			on:scroll={(e) => { | ||||
| 				console.log(e.target.scrollHeight, e.target.scrollTop, e.target.clientHeight); | ||||
| 				console.log(e.target.scrollHeight - e.target.scrollTop, e.target.clientHeight); | ||||
| 				autoScroll = e.target.scrollHeight - e.target.scrollTop <= e.target.clientHeight + 50; | ||||
| 			}} | ||||
| 		> | ||||
| 			<div | ||||
| 				class="{$settings?.fullScreenMode ?? null | ||||
| 					? 'max-w-full' | ||||
|  | @ -801,7 +807,7 @@ | |||
| 				<ModelSelector bind:selectedModels disabled={messages.length > 0} /> | ||||
| 			</div> | ||||
| 
 | ||||
| 			<div class=" h-full mt-14 w-full flex flex-col"> | ||||
| 			<div class=" h-full w-full flex flex-col py-8"> | ||||
| 				<Messages | ||||
| 					chatId={$chatId} | ||||
| 					{selectedModels} | ||||
|  |  | |||
|  | @ -153,6 +153,11 @@ | |||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| 	const scrollToBottom = () => { | ||||
| 		const element = document.getElementById('messages-container'); | ||||
| 		element.scrollTop = element.scrollHeight; | ||||
| 	}; | ||||
| 
 | ||||
| 	////////////////////////// | ||||
| 	// Ollama functions | ||||
| 	////////////////////////// | ||||
|  | @ -330,7 +335,7 @@ | |||
| 		await tick(); | ||||
| 
 | ||||
| 		// Scroll down | ||||
| 		window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 		scrollToBottom(); | ||||
| 
 | ||||
| 		const messagesBody = [ | ||||
| 			$settings.system | ||||
|  | @ -483,7 +488,7 @@ | |||
| 				} | ||||
| 
 | ||||
| 				if (autoScroll) { | ||||
| 					window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 					scrollToBottom(); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
|  | @ -522,7 +527,7 @@ | |||
| 		await tick(); | ||||
| 
 | ||||
| 		if (autoScroll) { | ||||
| 			window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 			scrollToBottom(); | ||||
| 		} | ||||
| 
 | ||||
| 		if (messages.length == 2 && messages.at(1).content !== '') { | ||||
|  | @ -534,7 +539,7 @@ | |||
| 	const sendPromptOpenAI = async (model, userPrompt, responseMessageId, _chatId) => { | ||||
| 		const responseMessage = history.messages[responseMessageId]; | ||||
| 
 | ||||
| 		window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 		scrollToBottom(); | ||||
| 
 | ||||
| 		const res = await generateOpenAIChatCompletion(localStorage.token, { | ||||
| 			model: model, | ||||
|  | @ -642,7 +647,7 @@ | |||
| 				} | ||||
| 
 | ||||
| 				if (autoScroll) { | ||||
| 					window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 					scrollToBottom(); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
|  | @ -686,7 +691,7 @@ | |||
| 		await tick(); | ||||
| 
 | ||||
| 		if (autoScroll) { | ||||
| 			window.scrollTo({ top: document.body.scrollHeight }); | ||||
| 			scrollToBottom(); | ||||
| 		} | ||||
| 
 | ||||
| 		if (messages.length == 2) { | ||||
|  | @ -797,14 +802,8 @@ | |||
| 	}); | ||||
| </script> | ||||
| 
 | ||||
| <svelte:window | ||||
| 	on:scroll={(e) => { | ||||
| 		autoScroll = window.innerHeight + window.scrollY >= document.body.offsetHeight - 40; | ||||
| 	}} | ||||
| /> | ||||
| 
 | ||||
| {#if loaded} | ||||
| 	<div class="min-h-screen w-full flex flex-col"> | ||||
| 	<div class="min-h-screen max-h-screen w-full flex flex-col"> | ||||
| 		<Navbar | ||||
| 			{title} | ||||
| 			shareEnabled={messages.length > 0} | ||||
|  | @ -820,8 +819,16 @@ | |||
| 			{addTag} | ||||
| 			{deleteTag} | ||||
| 		/> | ||||
| 		<div class="justify-center"> | ||||
| 			<div class=" pb-2.5 flex flex-col justify-between w-full"> | ||||
| 		<div class="flex flex-col flex-auto"> | ||||
| 			<div | ||||
| 				class=" pb-2.5 flex flex-col justify-between w-full flex-auto overflow-auto h-0" | ||||
| 				id="messages-container" | ||||
| 				on:scroll={(e) => { | ||||
| 					console.log(e.target.scrollHeight, e.target.scrollTop, e.target.clientHeight); | ||||
| 					console.log(e.target.scrollHeight - e.target.scrollTop, e.target.clientHeight); | ||||
| 					autoScroll = e.target.scrollHeight - e.target.scrollTop <= e.target.clientHeight + 50; | ||||
| 				}} | ||||
| 			> | ||||
| 				<div | ||||
| 					class="{$settings?.fullScreenMode ?? null | ||||
| 						? 'max-w-full' | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy J. Baek
						Timothy J. Baek