Added new width constants to implement the responsive chat width feature

This commit is contained in:
Imad Saddik 2025-12-14 21:59:19 +01:00
parent dc0ba44991
commit ce0a7e3acc
6 changed files with 36 additions and 9 deletions

View File

@ -7,6 +7,7 @@
ChatFormHelperText,
ChatFormTextarea
} from '$lib/components/app';
import { MAX_WIDTH_CLASSES, DEFAULT_MAX_WIDTH_CLASS } from '$lib/constants/width-classes';
import { INPUT_CLASSES } from '$lib/constants/input-classes';
import { config } from '$lib/stores/settings.svelte';
import { FileTypeCategory, MimeTypeApplication } from '$lib/enums/files';
@ -62,6 +63,9 @@
let previousIsLoading = $state(isLoading);
let recordingSupported = $state(false);
let textareaRef: ChatFormTextarea | undefined = $state(undefined);
let maxWidthClass = $derived(
currentConfig.responsiveChatWidth ? MAX_WIDTH_CLASSES : DEFAULT_MAX_WIDTH_CLASS
);
function getAcceptStringForFileType(fileType: FileTypeCategory): string {
switch (fileType) {
@ -230,7 +234,7 @@
<form
onsubmit={handleSubmit}
class="{INPUT_CLASSES} border-radius-bottom-none mx-auto max-w-[48rem] overflow-hidden rounded-3xl backdrop-blur-md {className}"
class="{INPUT_CLASSES} border-radius-bottom-none mx-auto {maxWidthClass} overflow-hidden rounded-3xl backdrop-blur-md {className}"
>
<ChatAttachmentsList
bind:uploadedFiles

View File

@ -23,6 +23,7 @@
import { modelName as serverModelName } from '$lib/stores/server.svelte';
import { copyToClipboard } from '$lib/utils/copy';
import type { ApiChatCompletionToolCall } from '$lib/types/api';
import { MAX_WIDTH_CLASSES, DEFAULT_MAX_WIDTH_CLASS } from '$lib/constants/width-classes';
interface Props {
class?: string;
@ -100,6 +101,10 @@
return serverModel;
});
let maxWidthClass = $derived(
config().responsiveChatWidth ? MAX_WIDTH_CLASSES : DEFAULT_MAX_WIDTH_CLASS
);
function handleCopyModel() {
const model = displayedModel();
@ -174,7 +179,7 @@
{/if}
{#if message?.role === 'assistant' && isLoading() && !message?.content?.trim()}
<div class="mt-6 w-full max-w-[48rem]" in:fade>
<div class="mt-6 w-full {maxWidthClass}" in:fade>
<div class="processing-container">
<span class="processing-text">
{processingState.getProcessingMessage()}
@ -220,7 +225,7 @@
</div>
{:else if message.role === 'assistant'}
{#if config().disableReasoningFormat}
<pre class="raw-output">{messageContent || ''}</pre>
<pre class="raw-output {maxWidthClass}">{messageContent || ''}</pre>
{:else}
<MarkdownContent content={messageContent || ''} />
{/if}
@ -375,7 +380,6 @@
.raw-output {
width: 100%;
max-width: 48rem;
margin-top: 1.5rem;
padding: 1rem 1.25rem;
border-radius: 1rem;

View File

@ -9,7 +9,9 @@
editAssistantMessage,
regenerateMessageWithBranching
} from '$lib/stores/chat.svelte';
import { config } from '$lib/stores/settings.svelte';
import { getMessageSiblings } from '$lib/utils/branching';
import { MAX_WIDTH_CLASSES, DEFAULT_MAX_WIDTH_CLASS } from '$lib/constants/width-classes';
interface Props {
class?: string;
@ -21,6 +23,10 @@
let allConversationMessages = $state<DatabaseMessage[]>([]);
let maxWidthClass = $derived(
config().responsiveChatWidth ? MAX_WIDTH_CLASSES : DEFAULT_MAX_WIDTH_CLASS
);
function refreshAllMessages() {
const conversation = activeConversation();
@ -103,7 +109,7 @@
<div class="flex h-full flex-col space-y-10 pt-16 md:pt-24 {className}" style="height: auto; ">
{#each displayMessages as { message, siblingInfo } (message.id)}
<ChatMessage
class="mx-auto w-full max-w-[48rem]"
class="mx-auto w-full {maxWidthClass}"
{message}
{siblingInfo}
onDelete={handleDeleteMessage}

View File

@ -4,12 +4,16 @@
import { slotsService } from '$lib/services/slots';
import { isLoading, activeMessages, activeConversation } from '$lib/stores/chat.svelte';
import { config } from '$lib/stores/settings.svelte';
import { MAX_WIDTH_CLASSES, DEFAULT_MAX_WIDTH_CLASS } from '$lib/constants/width-classes';
const processingState = useProcessingState();
let isCurrentConversationLoading = $derived(isLoading());
let processingDetails = $derived(processingState.getProcessingDetails());
let showSlotsInfo = $derived(isCurrentConversationLoading || config().keepStatsVisible);
let maxWidthClass = $derived(
config().responsiveChatWidth ? MAX_WIDTH_CLASSES : DEFAULT_MAX_WIDTH_CLASS
);
// Track loading state reactively by checking if conversation ID is in loading conversations array
$effect(() => {
@ -77,7 +81,7 @@
</script>
<div class="chat-processing-info-container pointer-events-none" class:visible={showSlotsInfo}>
<div class="chat-processing-info-content">
<div class="chat-processing-info-content {maxWidthClass}">
{#each processingDetails as detail (detail)}
<span class="chat-processing-info-detail pointer-events-auto">{detail}</span>
{/each}
@ -108,7 +112,6 @@
align-items: center;
gap: 1rem;
justify-content: center;
max-width: 48rem;
margin: 0 auto;
}

View File

@ -14,6 +14,8 @@
ConfirmationDialog
} from '$lib/components/app';
import * as AlertDialog from '$lib/components/ui/alert-dialog';
import { config } from '$lib/stores/settings.svelte';
import { MAX_WIDTH_CLASSES, DEFAULT_MAX_WIDTH_CLASS } from '$lib/constants/width-classes';
import {
AUTO_SCROLL_AT_BOTTOM_THRESHOLD,
AUTO_SCROLL_INTERVAL,
@ -85,6 +87,10 @@
let isCurrentConversationLoading = $derived(isLoading());
let maxWidthClass = $derived(
config().responsiveChatWidth ? MAX_WIDTH_CLASSES : DEFAULT_MAX_WIDTH_CLASS
);
async function handleDeleteConfirm() {
const conversation = activeConversation();
if (conversation) {
@ -302,7 +308,7 @@
<ChatProcessingInfo />
{#if serverWarning()}
<ChatScreenWarning class="pointer-events-auto mx-auto max-w-[48rem] px-4" />
<ChatScreenWarning class="pointer-events-auto mx-auto {maxWidthClass} px-4" />
{/if}
<div class="conversation-chat-form pointer-events-auto rounded-t-3xl pb-4">
@ -333,7 +339,7 @@
ondrop={handleDrop}
role="main"
>
<div class="w-full max-w-[48rem] px-4">
<div class="w-full {maxWidthClass} px-4">
<div class="mb-8 text-center" in:fade={{ duration: 300 }}>
<h1 class="mb-2 text-3xl font-semibold tracking-tight">llama.cpp</h1>

View File

@ -0,0 +1,4 @@
export const MAX_WIDTH_CLASSES =
'max-w-[48rem] md:max-w-[60rem] min-[1920px]:max-w-[80rem] min-[2560px]:max-w-[120rem]';
export const DEFAULT_MAX_WIDTH_CLASS = 'max-w-[48rem]';