This commit is contained in:
Timothy Jaeryang Baek
2026-03-15 23:37:45 -05:00
parent b99f8dabdd
commit a361df840e
13 changed files with 192 additions and 212 deletions
+20 -21
View File
@@ -43,8 +43,7 @@
import Minus from '$lib/components/icons/Minus.svelte';
import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
import { goto } from '$app/navigation';
import { DropdownMenu } from 'bits-ui';
import { flyAndScale } from '$lib/utils/transitions';
import Dropdown from '$lib/components/common/Dropdown.svelte';
import AdminViewSelector from './Models/AdminViewSelector.svelte';
import Pagination from '$lib/components/common/Pagination.svelte';
@@ -495,55 +494,55 @@
</Tooltip>
<div slot="content">
<DropdownMenu.Content
class="w-full max-w-[170px] rounded-xl p-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-sm"
sideOffset={-2}
side="bottom"
align="end"
transition={flyAndScale}
<div
class="w-[170px] rounded-xl p-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-sm"
>
<DropdownMenu.Item
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
enableAllHandler();
}}
>
<CheckCircle className="size-4" />
<div class="flex items-center">{$i18n.t('Enable All')}</div>
</DropdownMenu.Item>
</button>
<DropdownMenu.Item
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
disableAllHandler();
}}
>
<Minus className="size-4" />
<div class="flex items-center">{$i18n.t('Disable All')}</div>
</DropdownMenu.Item>
</button>
<hr class="border-gray-100 dark:border-gray-800 my-1" />
<DropdownMenu.Item
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
showAllHandler();
}}
>
<Eye className="size-4" />
<div class="flex items-center">{$i18n.t('Show All')}</div>
</DropdownMenu.Item>
</button>
<DropdownMenu.Item
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
hideAllHandler();
}}
>
<EyeSlash className="size-4" />
<div class="flex items-center">{$i18n.t('Hide All')}</div>
</DropdownMenu.Item>
</DropdownMenu.Content>
</button>
</div>
</div>
</Dropdown>
</div>
@@ -1,6 +1,4 @@
<script lang="ts">
import { DropdownMenu } from 'bits-ui';
import { flyAndScale } from '$lib/utils/transitions';
import { getContext, onMount, tick } from 'svelte';
import { config, user, tools as _tools, mobile } from '$lib/stores';
@@ -45,33 +43,31 @@
</Tooltip>
<div slot="content">
<DropdownMenu.Content
class="w-full max-w-[200px] rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-999 bg-white dark:bg-gray-850 dark:text-white shadow-lg transition"
sideOffset={4}
alignOffset={-6}
side="bottom"
align="start"
transition={flyAndScale}
<div
class="w-[200px] rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-999 bg-white dark:bg-gray-850 dark:text-white shadow-lg transition"
>
<DropdownMenu.Item
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl"
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl"
type="button"
on:click={() => {
uploadFilesHandler();
}}
>
<Clip />
<div class="line-clamp-1">{$i18n.t('Upload Files')}</div>
</DropdownMenu.Item>
</button>
<DropdownMenu.Item
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl"
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl"
type="button"
on:click={() => {
screenCaptureHandler();
}}
>
<Camera />
<div class=" line-clamp-1">{$i18n.t('Capture')}</div>
</DropdownMenu.Item>
</DropdownMenu.Content>
</button>
</div>
</div>
</Dropdown>
+1 -1
View File
@@ -194,7 +194,7 @@
{#if $user !== undefined}
<UserMenu
className="max-w-[240px]"
className="w-[240px]"
role={$user?.role}
help={true}
on:show={(e) => {
+1 -2
View File
@@ -89,8 +89,7 @@
import PlusAlt from '../icons/PlusAlt.svelte';
import Dropdown from '../common/Dropdown.svelte';
import { DropdownMenu } from 'bits-ui';
import { flyAndScale } from '$lib/utils/transitions';
import CommandSuggestionList from './MessageInput/CommandSuggestionList.svelte';
import Knobs from '../icons/Knobs.svelte';
@@ -1,8 +1,8 @@
<script lang="ts">
import { DropdownMenu } from 'bits-ui';
import { getContext, onMount, tick } from 'svelte';
import { fly } from 'svelte/transition';
import { flyAndScale } from '$lib/utils/transitions';
import { config, user, tools as _tools, mobile, knowledge } from '$lib/stores';
import { getKnowledgeBases } from '$lib/apis/knowledge';
@@ -122,13 +122,8 @@
</Tooltip>
<div slot="content">
<DropdownMenu.Content
class="w-full max-w-70 rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg max-h-72 overflow-y-auto overflow-x-hidden scrollbar-thin transition"
sideOffset={4}
alignOffset={-6}
side="bottom"
align="start"
transition={flyAndScale}
<div
class="w-70 rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg max-h-72 overflow-y-auto overflow-x-hidden scrollbar-thin transition"
>
{#if tab === ''}
<div in:fly={{ x: -20, duration: 150 }}>
@@ -140,10 +135,11 @@
: ''}
className="w-full"
>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl {!fileUploadEnabled
<button
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl {!fileUploadEnabled
? 'opacity-50'
: ''}"
type="button"
on:click={() => {
if (fileUploadEnabled) {
uploadFilesHandler();
@@ -153,7 +149,7 @@
<Clip />
<div class="line-clamp-1">{$i18n.t('Upload Files')}</div>
</DropdownMenu.Item>
</button>
</Tooltip>
<Tooltip
@@ -164,10 +160,11 @@
: ''}
className="w-full"
>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl {!fileUploadEnabled
<button
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl {!fileUploadEnabled
? 'opacity-50'
: ''}"
type="button"
on:click={() => {
if (fileUploadEnabled) {
if (!detectMobile()) {
@@ -184,7 +181,7 @@
>
<Camera />
<div class=" line-clamp-1">{$i18n.t('Capture')}</div>
</DropdownMenu.Item>
</button>
</Tooltip>
<Tooltip
@@ -193,10 +190,11 @@
: ''}
className="w-full"
>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl {!webUploadEnabled
<button
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl {!webUploadEnabled
? 'opacity-50'
: ''}"
type="button"
on:click={() => {
if (webUploadEnabled) {
showAttachWebpageModal = true;
@@ -205,7 +203,7 @@
>
<GlobeAlt />
<div class="line-clamp-1">{$i18n.t('Attach Webpage')}</div>
</DropdownMenu.Item>
</button>
</Tooltip>
{#if $config?.features?.enable_notes ?? false}
@@ -302,8 +300,9 @@
{#if fileUploadEnabled}
{#if $config?.features?.enable_google_drive_integration}
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl"
<button
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl"
type="button"
on:click={() => {
uploadGoogleDriveHandler();
}}
@@ -335,7 +334,7 @@
/>
</svg>
<div class="line-clamp-1">{$i18n.t('Google Drive')}</div>
</DropdownMenu.Item>
</button>
{/if}
{#if $config?.features?.enable_onedrive_integration && ($config?.features?.enable_onedrive_personal || $config?.features?.enable_onedrive_business)}
@@ -521,8 +520,9 @@
</button>
{#if $config?.features?.enable_onedrive_personal}
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl text-left"
<button
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl text-left"
type="button"
on:click={() => {
uploadOneDriveHandler('personal');
}}
@@ -530,12 +530,13 @@
<div class="flex flex-col">
<div class="line-clamp-1">{$i18n.t('Microsoft OneDrive (personal)')}</div>
</div>
</DropdownMenu.Item>
</button>
{/if}
{#if $config?.features?.enable_onedrive_business}
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl text-left"
<button
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl text-left"
type="button"
on:click={() => {
uploadOneDriveHandler('organizations');
}}
@@ -546,10 +547,10 @@
</div>
<div class="text-xs text-gray-500">{$i18n.t('Includes SharePoint')}</div>
</div>
</DropdownMenu.Item>
</button>
{/if}
</div>
{/if}
</DropdownMenu.Content>
</div>
</div>
</Dropdown>
+1 -1
View File
@@ -230,7 +230,7 @@
{#if $user !== undefined && $user !== null}
<UserMenu
className="max-w-[240px]"
className="w-[240px]"
role={$user?.role}
help={true}
on:show={(e) => {
+7 -1
View File
@@ -1,6 +1,8 @@
<script lang="ts">
import { flyAndScale } from '$lib/utils/transitions';
import { tick } from 'svelte';
import { createEventDispatcher, tick } from 'svelte';
const dispatch = createEventDispatcher();
/** Whether the dropdown is open */
export let show = false;
@@ -104,6 +106,7 @@
async function toggleOpen() {
show = !show;
onOpenChange(show);
dispatch('change', show);
if (show) {
await tick();
positionContent();
@@ -126,12 +129,14 @@
if (contentEl?.contains(event.target)) return;
show = false;
onOpenChange(false);
dispatch('change', false);
}
function handleKeydown(event) {
if (event.key === 'Escape' && show) {
show = false;
onOpenChange(false);
dispatch('change', false);
}
}
@@ -139,6 +144,7 @@
export function close() {
show = false;
onOpenChange(false);
dispatch('change', false);
}
</script>
+63 -69
View File
@@ -1,12 +1,11 @@
<script lang="ts">
import { DropdownMenu } from 'bits-ui';
import VirtualList from '@sveltejs/svelte-virtual-list';
import { getContext } from 'svelte';
import { flyAndScale } from '$lib/utils/transitions';
import { WEBUI_BASE_URL } from '$lib/constants';
import Dropdown from '$lib/components/common/Dropdown.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import emojiGroups from '$lib/emoji-groups.json';
@@ -107,79 +106,74 @@
}
</script>
<DropdownMenu.Root
bind:open={show}
closeFocus={false}
onOpenChange={(state) => {
if (!state) {
<Dropdown
bind:show
{align}
on:change={(e) => {
if (e.detail === false) {
search = '';
onClose();
}
}}
typeahead={false}
>
<DropdownMenu.Trigger>
<slot />
</DropdownMenu.Trigger>
<DropdownMenu.Content
class="max-w-full w-80 border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-850 rounded-3xl z-9999 shadow-lg dark:text-white"
sideOffset={8}
{side}
{align}
transition={flyAndScale}
>
<div class="mb-1 px-4 pt-2.5 pb-2">
<input
type="text"
class="w-full text-sm bg-transparent outline-hidden"
placeholder={$i18n.t('Search all emojis')}
bind:value={search}
/>
</div>
<slot />
<div slot="content">
<div
class="max-w-full w-80 border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-850 rounded-3xl z-9999 shadow-lg dark:text-white"
>
<div class="mb-1 px-4 pt-2.5 pb-2">
<input
type="text"
class="w-full text-sm bg-transparent outline-hidden"
placeholder={$i18n.t('Search all emojis')}
bind:value={search}
/>
</div>
<!-- Virtualized Emoji List -->
<div class="w-full flex justify-start h-96 overflow-y-auto px-3 pb-3 text-sm">
{#if emojiRows.length === 0}
<div class="text-center text-xs text-gray-500 dark:text-gray-400">
{$i18n.t('No results')}
</div>
{:else}
<div class="w-full flex ml-0.5">
<VirtualList rowHeight={ROW_HEIGHT} items={emojiRows} height={384} let:item>
<div class="w-full">
{#if item.length === 1 && item[0].type === 'group'}
<!-- Render group header -->
<div class="text-xs font-medium mb-2 text-gray-500 dark:text-gray-400">
{item[0].label}
</div>
{:else}
<!-- Render emojis in a row -->
<div class="flex items-center gap-1.5 w-full">
{#each item as emojiItem}
<Tooltip
content={emojiItem.shortCodes.map((code) => `:${code}:`).join(', ')}
placement="top"
>
<button
class="p-1.5 rounded-lg cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-700 transition {selected === emojiItem.shortCodes[0] ? 'bg-gray-200 dark:bg-gray-700' : ''}"
on:click={() => selectEmoji(emojiItem)}
<!-- Virtualized Emoji List -->
<div class="w-full flex justify-start h-96 overflow-y-auto px-3 pb-3 text-sm">
{#if emojiRows.length === 0}
<div class="text-center text-xs text-gray-500 dark:text-gray-400">
{$i18n.t('No results')}
</div>
{:else}
<div class="w-full flex ml-0.5">
<VirtualList rowHeight={ROW_HEIGHT} items={emojiRows} height={384} let:item>
<div class="w-full">
{#if item.length === 1 && item[0].type === 'group'}
<!-- Render group header -->
<div class="text-xs font-medium mb-2 text-gray-500 dark:text-gray-400">
{item[0].label}
</div>
{:else}
<!-- Render emojis in a row -->
<div class="flex items-center gap-1.5 w-full">
{#each item as emojiItem}
<Tooltip
content={emojiItem.shortCodes.map((code) => `:${code}:`).join(', ')}
placement="top"
>
<img
src="{WEBUI_BASE_URL}/assets/emojis/{emojiItem.name.toLowerCase()}.svg"
alt={emojiItem.name}
class="size-5"
loading="lazy"
/>
</button>
</Tooltip>
{/each}
</div>
{/if}
</div>
</VirtualList>
</div>
{/if}
<button
class="p-1.5 rounded-lg cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-700 transition {selected === emojiItem.shortCodes[0] ? 'bg-gray-200 dark:bg-gray-700' : ''}"
on:click={() => selectEmoji(emojiItem)}
>
<img
src="{WEBUI_BASE_URL}/assets/emojis/{emojiItem.name.toLowerCase()}.svg"
alt={emojiItem.name}
class="size-5"
loading="lazy"
/>
</button>
</Tooltip>
{/each}
</div>
{/if}
</div>
</VirtualList>
</div>
{/if}
</div>
</div>
</DropdownMenu.Content>
</DropdownMenu.Root>
</div>
</Dropdown>
+1 -1
View File
@@ -1398,7 +1398,7 @@
role={$user?.role}
profile={$config?.features?.enable_user_status ?? true}
showActiveUsers={false}
className="max-w-[calc(var(--sidebar-width)-1rem)]"
className="w-[calc(var(--sidebar-width)-1rem)]"
on:show={(e) => {
if (e.detail === 'archived-chat') {
showArchivedChats.set(true);
@@ -1,8 +1,6 @@
<script lang="ts">
import { DropdownMenu } from 'bits-ui';
import { createEventDispatcher, getContext, onMount, tick } from 'svelte';
import { flyAndScale } from '$lib/utils/transitions';
import { goto } from '$app/navigation';
import { fade, slide } from 'svelte/transition';
@@ -13,6 +11,7 @@
import { WEBUI_API_BASE_URL } from '$lib/constants';
import Dropdown from '$lib/components/common/Dropdown.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import ArchiveBox from '$lib/components/icons/ArchiveBox.svelte';
import QuestionMarkCircle from '$lib/components/icons/QuestionMarkCircle.svelte';
@@ -38,7 +37,7 @@
export let profile = false;
export let help = false;
export let className = 'max-w-[240px]';
export let className = 'w-[240px]';
export let align = 'end';
export let showActiveUsers = true;
@@ -60,7 +59,8 @@
}
};
const handleDropdownChange = (state: boolean) => {
const handleDropdownChange = (e) => {
const state = e.detail;
dispatch('change', state);
// Fetch usage info when dropdown opens, if user has permission
@@ -79,18 +79,12 @@
/>
<!-- svelte-ignore a11y-no-static-element-interactions -->
<DropdownMenu.Root bind:open={show} onOpenChange={handleDropdownChange}>
<DropdownMenu.Trigger>
<slot />
</DropdownMenu.Trigger>
<Dropdown bind:show on:change={handleDropdownChange} {align}>
<slot />
<slot name="content">
<DropdownMenu.Content
class="w-full {className} rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg text-sm"
sideOffset={4}
side="top"
{align}
transition={(e) => fade(e, { duration: 100 })}
<div slot="content">
<div
class="{className} rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg text-sm"
>
{#if profile}
<div class=" flex gap-3.5 w-full p-2.5 items-center">
@@ -201,8 +195,9 @@
<hr class=" border-gray-50/30 dark:border-gray-800/30 my-1.5 p-0" />
{/if}
<DropdownMenu.Item
<button
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
type="button"
on:click={async () => {
show = false;
@@ -218,10 +213,11 @@
<Settings className="w-5 h-5" strokeWidth="1.5" />
</div>
<div class=" self-center truncate">{$i18n.t('Settings')}</div>
</DropdownMenu.Item>
</button>
<DropdownMenu.Item
<button
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
type="button"
on:click={async () => {
show = false;
@@ -238,11 +234,10 @@
<ArchiveBox className="size-5" strokeWidth="1.5" />
</div>
<div class=" self-center truncate">{$i18n.t('Archived Chats')}</div>
</DropdownMenu.Item>
</button>
{#if role === 'admin'}
<DropdownMenu.Item
as="a"
<a
href="/playground"
draggable="false"
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
@@ -258,9 +253,8 @@
<Code className="size-5" strokeWidth="1.5" />
</div>
<div class=" self-center truncate">{$i18n.t('Playground')}</div>
</DropdownMenu.Item>
<DropdownMenu.Item
as="a"
</a>
<a
href="/admin"
draggable="false"
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
@@ -276,7 +270,7 @@
<UserGroup className="w-5 h-5" strokeWidth="1.5" />
</div>
<div class=" self-center truncate">{$i18n.t('Admin Panel')}</div>
</DropdownMenu.Item>
</a>
{/if}
{#if help}
@@ -285,8 +279,7 @@
<!-- {$i18n.t('Help')} -->
{#if $user?.role === 'admin'}
<DropdownMenu.Item
as="a"
<a
href="https://docs.openwebui.com"
target="_blank"
draggable="false"
@@ -300,11 +293,10 @@
<QuestionMarkCircle className="size-5" />
</div>
<div class=" self-center truncate">{$i18n.t('Documentation')}</div>
</DropdownMenu.Item>
</a>
<!-- Releases -->
<DropdownMenu.Item
as="a"
<a
href="https://github.com/open-webui/open-webui/releases"
target="_blank"
draggable="false"
@@ -318,11 +310,12 @@
<Map className="size-5" />
</div>
<div class=" self-center truncate">{$i18n.t('Releases')}</div>
</DropdownMenu.Item>
</a>
{/if}
<DropdownMenu.Item
<button
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
type="button"
id="chat-share-button"
on:click={async () => {
show = false;
@@ -338,13 +331,14 @@
<Keyboard className="size-5" />
</div>
<div class=" self-center truncate">{$i18n.t('Keyboard shortcuts')}</div>
</DropdownMenu.Item>
</button>
{/if}
<hr class=" border-gray-50/30 dark:border-gray-800/30 my-1 p-0" />
<DropdownMenu.Item
<button
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
type="button"
on:click={async () => {
const res = await userSignOut();
user.set(null);
@@ -358,7 +352,7 @@
<SignOut className="w-5 h-5" strokeWidth="1.5" />
</div>
<div class=" self-center truncate">{$i18n.t('Sign Out')}</div>
</DropdownMenu.Item>
</button>
{#if showActiveUsers && ($config?.features?.enable_public_active_users_count || role === 'admin') && usage}
{#if usage?.user_count}
@@ -395,10 +389,6 @@
</Tooltip>
{/if}
{/if}
<!-- <DropdownMenu.Item class="flex items-center py-1.5 px-3 text-sm ">
<div class="flex items-center">Profile</div>
</DropdownMenu.Item> -->
</DropdownMenu.Content>
</slot>
</DropdownMenu.Root>
</div>
</div>
</Dropdown>
+20 -21
View File
@@ -43,8 +43,7 @@
import XMark from '../icons/XMark.svelte';
import EyeSlash from '../icons/EyeSlash.svelte';
import Eye from '../icons/Eye.svelte';
import { DropdownMenu } from 'bits-ui';
import { flyAndScale } from '$lib/utils/transitions';
import Dropdown from '$lib/components/common/Dropdown.svelte';
import ViewSelector from './common/ViewSelector.svelte';
import TagSelector from './common/TagSelector.svelte';
@@ -517,55 +516,55 @@
</Tooltip>
<div slot="content">
<DropdownMenu.Content
class="w-full max-w-[170px] rounded-xl p-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-sm"
sideOffset={-2}
side="bottom"
align="end"
transition={flyAndScale}
<div
class="w-[170px] rounded-xl p-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-sm"
>
<DropdownMenu.Item
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
enableAllHandler();
}}
>
<CheckCircle className="size-4" />
<div class="flex items-center">{$i18n.t('Enable All')}</div>
</DropdownMenu.Item>
</button>
<DropdownMenu.Item
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
disableAllHandler();
}}
>
<Minus className="size-4" />
<div class="flex items-center">{$i18n.t('Disable All')}</div>
</DropdownMenu.Item>
</button>
<hr class="border-gray-100 dark:border-gray-800 my-1" />
<DropdownMenu.Item
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
showAllHandler();
}}
>
<Eye className="size-4" />
<div class="flex items-center">{$i18n.t('Show All')}</div>
</DropdownMenu.Item>
</button>
<DropdownMenu.Item
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
<button
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
type="button"
on:click={() => {
hideAllHandler();
}}
>
<EyeSlash className="size-4" />
<div class="flex items-center">{$i18n.t('Hide All')}</div>
</DropdownMenu.Item>
</DropdownMenu.Content>
</button>
</div>
</div>
</Dropdown>
</div>
@@ -1,11 +1,11 @@
<script lang="ts">
import dayjs from 'dayjs';
import { DropdownMenu } from 'bits-ui';
import { onMount, onDestroy, getContext, createEventDispatcher } from 'svelte';
import { searchNotes } from '$lib/apis/notes';
import { searchKnowledgeBases, searchKnowledgeFiles } from '$lib/apis/knowledge';
import { flyAndScale } from '$lib/utils/transitions';
import { decodeString } from '$lib/utils';
import Dropdown from '$lib/components/common/Dropdown.svelte';
@@ -118,12 +118,8 @@
<slot />
<div slot="content">
<DropdownMenu.Content
<div
class="z-[10000] text-black dark:text-white rounded-2xl shadow-lg border border-gray-200 dark:border-gray-800 flex flex-col bg-white dark:bg-gray-850 w-70 p-1.5"
sideOffset={8}
side="bottom"
align="start"
transition={flyAndScale}
>
<div class=" flex w-full space-x-2 px-2 pb-0.5">
<div class="flex flex-1">
@@ -210,6 +206,6 @@
{/each}
{/if}
</div>
</DropdownMenu.Content>
</div>
</div>
</Dropdown>
+1 -1
View File
@@ -81,7 +81,7 @@
<div class=" self-center flex items-center gap-1">
{#if $user !== undefined && $user !== null}
<UserMenu
className="max-w-[240px]"
className="w-[240px]"
role={$user?.role}
help={true}
on:show={(e) => {