mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-23 23:29:31 +01:00
feat: Add adjustable text size setting to interface (#19186)
* Add adjustable text size setting to interface Introduces a user-configurable text size (scale) setting, accessible via a slider in the interface settings. Updates CSS and Sidebar chat item components to respect the new --app-text-scale variable, and persists the setting in the store. Adds related i18n strings and ensures the text scale is applied globally and clamped to allowed values. * Refactor text scale logic into utility module Moved all text scale related constants and functions from components and stores into a new utility module (src/lib/utils/text-scale.ts). Updated imports and usage in Interface.svelte and index.ts to use the new module, improving code organization and reusability. * Adjust sidebar chat scaling without extra classes keep sidebar markup using existing Tailwind utility classes so chat items render identically pre-feature move all text-scale sizing into app.css under the #sidebar-chat-item selectors change the root font-size multiplier to use 1rem instead of an explicit 16px so browser/user preferences propagate * Update Switch.svelte Adjust toggles from fixed pixel to rem to scale with the text size * Update Interface.svelte Updated label from 'Text Scale' to 'UI Scale'. Added padding around slider * Update app.css Added comments
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { config, models, settings, user } from '$lib/stores';
|
||||
import { createEventDispatcher, onMount, getContext } from 'svelte';
|
||||
import { createEventDispatcher, onMount, onDestroy, getContext } from 'svelte';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import { updateUserInfo } from '$lib/apis/users';
|
||||
@@ -10,6 +10,14 @@
|
||||
import Switch from '$lib/components/common/Switch.svelte';
|
||||
import ManageFloatingActionButtonsModal from './Interface/ManageFloatingActionButtonsModal.svelte';
|
||||
import ManageImageCompressionModal from './Interface/ManageImageCompressionModal.svelte';
|
||||
import {
|
||||
DEFAULT_TEXT_SCALE_INDEX,
|
||||
TEXT_SCALE_MAX,
|
||||
TEXT_SCALE_MIN,
|
||||
TEXT_SCALE_VALUES,
|
||||
findClosestTextScaleIndex,
|
||||
getScaleFromIndex
|
||||
} from '$lib/utils/text-scale';
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
@@ -97,6 +105,46 @@
|
||||
let showManageFloatingActionButtonsModal = false;
|
||||
let showManageImageCompressionModal = false;
|
||||
|
||||
let textScaleIndex = DEFAULT_TEXT_SCALE_INDEX;
|
||||
let unsubscribeTextScale: (() => void) | undefined;
|
||||
|
||||
const persistTextScale = () => {
|
||||
const scale = getScaleFromIndex(textScaleIndex);
|
||||
|
||||
if ($settings?.textScale === scale) {
|
||||
return;
|
||||
}
|
||||
|
||||
saveSettings({ textScale: scale });
|
||||
};
|
||||
|
||||
const decreaseTextScale = () => {
|
||||
const previous = textScaleIndex;
|
||||
textScaleIndex = Math.max(0, textScaleIndex - 1);
|
||||
|
||||
if (textScaleIndex === previous) {
|
||||
return;
|
||||
}
|
||||
|
||||
persistTextScale();
|
||||
};
|
||||
|
||||
const increaseTextScale = () => {
|
||||
const previous = textScaleIndex;
|
||||
textScaleIndex = Math.min(TEXT_SCALE_VALUES.length - 1, textScaleIndex + 1);
|
||||
|
||||
if (textScaleIndex === previous) {
|
||||
return;
|
||||
}
|
||||
|
||||
persistTextScale();
|
||||
};
|
||||
|
||||
$: currentTextScale = getScaleFromIndex(textScaleIndex);
|
||||
$: textScaleDisplay = Number.isInteger(currentTextScale)
|
||||
? `${currentTextScale.toFixed(0)}`
|
||||
: `${currentTextScale.toFixed(1)}`;
|
||||
|
||||
const toggleLandingPageMode = async () => {
|
||||
landingPageMode = landingPageMode === '' ? 'chat' : '';
|
||||
saveSettings({ landingPageMode: landingPageMode });
|
||||
@@ -252,6 +300,20 @@
|
||||
|
||||
backgroundImageUrl = $settings?.backgroundImageUrl ?? null;
|
||||
webSearch = $settings?.webSearch ?? null;
|
||||
|
||||
textScaleIndex = findClosestTextScaleIndex($settings?.textScale ?? 1);
|
||||
|
||||
unsubscribeTextScale = settings.subscribe((uiSettings) => {
|
||||
const nextScaleIndex = findClosestTextScaleIndex(uiSettings?.textScale ?? 1);
|
||||
|
||||
if (nextScaleIndex !== textScaleIndex) {
|
||||
textScaleIndex = nextScaleIndex;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
unsubscribeTextScale?.();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -331,6 +393,64 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="py-0.5">
|
||||
<div class="flex w-full justify-between">
|
||||
<label
|
||||
id="ui-scale-label"
|
||||
class=" self-center text-xs"
|
||||
for="ui-scale-slider"
|
||||
>
|
||||
{$i18n.t('UI Scale')}
|
||||
</label>
|
||||
|
||||
<div class="flex items-center gap-1 text-xs" aria-live="polite">
|
||||
<span>{textScaleDisplay}x</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-2 flex items-center gap-2 pl-1 pr-1">
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-sm p-1 transition outline outline-1 outline-gray-200 hover:bg-gray-100 dark:outline-gray-700 dark:hover:bg-gray-800"
|
||||
on:click={decreaseTextScale}
|
||||
aria-labelledby="ui-scale-label"
|
||||
aria-label={$i18n.t('Decrease UI Scale')}
|
||||
>
|
||||
<Minus className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
|
||||
<div class="flex-1">
|
||||
<input
|
||||
id="ui-scale-slider"
|
||||
class="w-full accent-black dark:accent-white"
|
||||
type="range"
|
||||
min={0}
|
||||
max={TEXT_SCALE_VALUES.length - 1}
|
||||
step={1}
|
||||
bind:value={textScaleIndex}
|
||||
on:change={persistTextScale}
|
||||
aria-labelledby="ui-scale-label"
|
||||
aria-valuemin={TEXT_SCALE_MIN}
|
||||
aria-valuemax={TEXT_SCALE_MAX}
|
||||
aria-valuenow={currentTextScale}
|
||||
aria-valuetext={`${textScaleDisplay}x`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-sm p-1 transition outline outline-1 outline-gray-200 hover:bg-gray-100 dark:outline-gray-700 dark:hover:bg-gray-800"
|
||||
on:click={increaseTextScale}
|
||||
aria-labelledby="ui-scale-label"
|
||||
aria-label={$i18n.t('Increase UI Scale')}
|
||||
>
|
||||
<Plus className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class=" py-0.5 flex w-full justify-between">
|
||||
<div id="use-chat-title-as-tab-title-label" class=" self-center text-xs">
|
||||
|
||||
Reference in New Issue
Block a user