mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-06 02:48:04 +00:00
feat(ui): add expand/collapse to user settings modal
Add a toggle button to the settings modal header that switches between the default size (2xl) and a near-fullscreen 'max' size. The expand button uses existing ArrowsPointingOut/Collapse icon components with an aria-label. Hidden on mobile (md: breakpoint). The expanded state resets when the modal is closed. Also adds 'max' as a new Modal size option that renders at calc(100vw-4rem) x calc(100vh-4rem).
This commit is contained in:
parent
f85cb27ef8
commit
8676390881
2 changed files with 61 additions and 29 deletions
|
|
@ -28,6 +28,8 @@
|
|||
import Face from '../icons/Face.svelte';
|
||||
import AppNotification from '../icons/AppNotification.svelte';
|
||||
import UserBadgeCheck from '../icons/UserBadgeCheck.svelte';
|
||||
import ArrowsPointingOut from '../icons/ArrowsPointingOut.svelte';
|
||||
import Collapse from '../icons/Collapse.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
|
|
@ -41,6 +43,7 @@
|
|||
addScrollListener();
|
||||
} else {
|
||||
selectedTab = 'general';
|
||||
isExpanded = false;
|
||||
removeScrollListener();
|
||||
}
|
||||
|
||||
|
|
@ -552,6 +555,7 @@
|
|||
};
|
||||
|
||||
let selectedTab = 'general';
|
||||
let isExpanded = false;
|
||||
|
||||
// Function to handle sideways scrolling
|
||||
const scrollHandler = (event) => {
|
||||
|
|
@ -589,26 +593,47 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<Modal size="2xl" bind:show>
|
||||
<div class="text-gray-700 dark:text-gray-100 mx-1">
|
||||
<div class=" flex justify-between dark:text-gray-300 px-4 md:px-4.5 pt-4.5 pb-0.5 md:pb-2.5">
|
||||
<div class=" text-lg font-medium self-center">{$i18n.t('Settings')}</div>
|
||||
<button
|
||||
aria-label={$i18n.t('Close settings modal')}
|
||||
class="self-center"
|
||||
on:click={() => {
|
||||
show = false;
|
||||
}}
|
||||
>
|
||||
<XMark className="w-5 h-5"></XMark>
|
||||
</button>
|
||||
<Modal size={isExpanded ? 'max' : '2xl'} bind:show>
|
||||
<div class="text-gray-700 dark:text-gray-100 mx-1 flex flex-col h-full">
|
||||
<div
|
||||
class="flex items-center justify-between dark:text-gray-300 px-4 md:px-4.5 pt-4.5 pb-0.5 md:pb-2.5 flex-shrink-0"
|
||||
>
|
||||
<div class="text-lg font-medium self-center">{$i18n.t('Settings')}</div>
|
||||
|
||||
<div class="flex items-center gap-1">
|
||||
<button
|
||||
aria-label={$i18n.t(isExpanded ? 'Collapse' : 'Expand')}
|
||||
class="hidden md:flex p-1 rounded-lg transition hover:bg-gray-100 dark:hover:bg-gray-800"
|
||||
on:click={() => {
|
||||
isExpanded = !isExpanded;
|
||||
}}
|
||||
>
|
||||
{#if isExpanded}
|
||||
<Collapse className="size-4 text-gray-500" />
|
||||
{:else}
|
||||
<ArrowsPointingOut className="size-4 text-gray-500" />
|
||||
{/if}
|
||||
</button>
|
||||
<button
|
||||
aria-label={$i18n.t('Close settings modal')}
|
||||
class="self-center"
|
||||
on:click={() => {
|
||||
show = false;
|
||||
}}
|
||||
>
|
||||
<XMark className="w-5 h-5"></XMark>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col md:flex-row w-full pt-1 pb-4">
|
||||
<div class="flex flex-col md:flex-row w-full pt-1 pb-4 flex-grow overflow-hidden">
|
||||
<div
|
||||
role="tablist"
|
||||
id="settings-tabs-container"
|
||||
class="tabs flex flex-row overflow-x-auto gap-2.5 mx-3 md:pr-4 md:gap-1 md:flex-col flex-1 md:flex-none md:w-50 md:min-h-[min(42rem,calc(100dvh-10rem))] md:max-h-[min(42rem,calc(100dvh-10rem))] dark:text-gray-200 text-sm text-left mb-1 md:mb-0 -translate-y-1"
|
||||
class="tabs flex flex-row overflow-x-auto gap-2.5 mx-3 md:pr-4 md:gap-1 md:flex-col flex-1 md:flex-none md:w-50 dark:text-gray-200 text-sm text-left mb-1 md:mb-0 -translate-y-1
|
||||
{isExpanded
|
||||
? 'md:h-full md:overflow-y-auto'
|
||||
: 'md:min-h-[min(42rem,calc(100dvh-10rem))] md:max-h-[min(42rem,calc(100dvh-10rem))]'}"
|
||||
>
|
||||
<div
|
||||
class="hidden md:flex w-full rounded-full px-2.5 gap-2 bg-gray-100/80 dark:bg-gray-850/80 backdrop-blur-2xl my-1 mb-1.5"
|
||||
|
|
@ -880,7 +905,10 @@
|
|||
{/if}
|
||||
</div>
|
||||
<div
|
||||
class="flex-1 px-3.5 md:pl-0 md:pr-4.5 md:min-h-[min(42rem,calc(100dvh-10rem))] max-h-[min(42rem,calc(100dvh-10rem))] overflow-y-auto"
|
||||
class="flex-1 px-3.5 md:pl-0 md:pr-4.5 overflow-y-auto
|
||||
{isExpanded
|
||||
? 'md:h-full'
|
||||
: 'md:min-h-[min(42rem,calc(100dvh-10rem))] max-h-[min(42rem,calc(100dvh-10rem))]'}"
|
||||
>
|
||||
{#if selectedTab === 'general'}
|
||||
<General
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
import { flyAndScale } from '$lib/utils/transitions';
|
||||
import * as FocusTrap from 'focus-trap';
|
||||
export let show = true;
|
||||
export let size = 'md';
|
||||
export let size: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full' | 'max' = 'md';
|
||||
export let containerClassName = 'p-3';
|
||||
export let className = 'bg-white/95 dark:bg-gray-900/95 backdrop-blur-sm rounded-4xl';
|
||||
|
||||
|
|
@ -16,23 +16,26 @@
|
|||
// https://www.w3.org/WAI/WCAG21/Understanding/keyboard.html
|
||||
let focusTrap: FocusTrap.FocusTrap | null = null;
|
||||
|
||||
const sizeToWidth = (size) => {
|
||||
if (size === 'full') {
|
||||
const sizeToWidth = (modalSize: typeof size) => {
|
||||
if (modalSize === 'full') {
|
||||
return 'w-full';
|
||||
}
|
||||
if (size === 'xs') {
|
||||
if (modalSize === 'max') {
|
||||
return '';
|
||||
}
|
||||
if (modalSize === 'xs') {
|
||||
return 'w-[16rem]';
|
||||
} else if (size === 'sm') {
|
||||
} else if (modalSize === 'sm') {
|
||||
return 'w-[30rem]';
|
||||
} else if (size === 'md') {
|
||||
} else if (modalSize === 'md') {
|
||||
return 'w-[42rem]';
|
||||
} else if (size === 'lg') {
|
||||
} else if (modalSize === 'lg') {
|
||||
return 'w-[56rem]';
|
||||
} else if (size === 'xl') {
|
||||
} else if (modalSize === 'xl') {
|
||||
return 'w-[70rem]';
|
||||
} else if (size === '2xl') {
|
||||
} else if (modalSize === '2xl') {
|
||||
return 'w-[84rem]';
|
||||
} else if (size === '3xl') {
|
||||
} else if (modalSize === '3xl') {
|
||||
return 'w-[100rem]';
|
||||
} else {
|
||||
return 'w-[56rem]';
|
||||
|
|
@ -129,9 +132,10 @@
|
|||
}}
|
||||
>
|
||||
<div
|
||||
class="m-auto max-w-full {sizeToWidth(size)} {size !== 'full'
|
||||
? 'mx-2'
|
||||
: ''} shadow-3xl min-h-fit scrollbar-hidden {className} border border-white dark:border-gray-850"
|
||||
class="m-auto shadow-3xl min-h-fit scrollbar-hidden {className} border border-white dark:border-gray-850
|
||||
{size === 'max'
|
||||
? 'w-[calc(100vw-4rem)] h-[calc(100vh-4rem)] max-w-none max-h-none'
|
||||
: `max-w-full ${sizeToWidth(size)} ${size !== 'full' ? 'mx-2' : ''}`}"
|
||||
in:flyAndScale
|
||||
on:mousedown={(e) => {
|
||||
e.stopPropagation();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue