소스 검색

refac: styling

Timothy J. Baek 6 달 전
부모
커밋
6f07afc79b

+ 22 - 15
src/lib/components/workspace/Functions.svelte

@@ -47,6 +47,14 @@
 
 	let showDeleteConfirm = false;
 
+	let filteredItems = [];
+	$: filteredItems = $functions.filter(
+		(f) =>
+			query === '' ||
+			f.name.toLowerCase().includes(query.toLowerCase()) ||
+			f.id.toLowerCase().includes(query.toLowerCase())
+	);
+
 	const shareHandler = async (func) => {
 		const item = await getFunctionById(localStorage.token, func.id).catch((error) => {
 			toast.error(error);
@@ -174,17 +182,7 @@
 	</title>
 </svelte:head>
 
-<div class="mb-3">
-	<div class="flex justify-between items-center">
-		<div class="flex md:self-center text-lg font-medium px-0.5">
-			{$i18n.t('Functions')}
-			<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" />
-			<span class="text-lg font-medium text-gray-500 dark:text-gray-300">{$functions.length}</span>
-		</div>
-	</div>
-</div>
-
-<div class=" flex w-full space-x-2">
+<div class=" flex w-full space-x-2 mb-2.5">
 	<div class="flex flex-1">
 		<div class=" self-center ml-1 mr-3">
 			<svg
@@ -225,12 +223,21 @@
 		</a>
 	</div>
 </div>
-<hr class=" border-gray-50 dark:border-gray-850 my-2.5" />
+
+<div class="mb-3.5">
+	<div class="flex justify-between items-center">
+		<div class="flex md:self-center text-base font-medium px-0.5">
+			{$i18n.t('Functions')}
+			<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" />
+			<span class="text-base font-medium text-gray-500 dark:text-gray-300"
+				>{filteredItems.length}</span
+			>
+		</div>
+	</div>
+</div>
 
 <div class="my-3 mb-5">
-	{#each $functions.filter((f) => query === '' || f.name
-				.toLowerCase()
-				.includes(query.toLowerCase()) || f.id.toLowerCase().includes(query.toLowerCase())) as func}
+	{#each filteredItems as func}
 		<div
 			class=" flex space-x-4 cursor-pointer w-full px-3 py-2 dark:hover:bg-white/5 hover:bg-black/5 rounded-xl"
 		>

+ 14 - 14
src/lib/components/workspace/Knowledge.svelte

@@ -72,17 +72,7 @@
 	}}
 />
 
-<div class="mb-3">
-	<div class="flex justify-between items-center">
-		<div class="flex md:self-center text-lg font-medium px-0.5">
-			{$i18n.t('Knowledge')}
-			<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" />
-			<span class="text-lg font-medium text-gray-500 dark:text-gray-300">{$knowledge.length}</span>
-		</div>
-	</div>
-</div>
-
-<div class=" flex w-full space-x-2">
+<div class=" flex w-full space-x-2 mb-2.5">
 	<div class="flex flex-1">
 		<div class=" self-center ml-1 mr-3">
 			<svg
@@ -127,12 +117,22 @@
 	</div>
 </div>
 
-<hr class=" border-gray-50 dark:border-gray-850 my-2.5" />
+<div class="mb-3.5">
+	<div class="flex justify-between items-center">
+		<div class="flex md:self-center text-base font-medium px-0.5">
+			{$i18n.t('Knowledge')}
+			<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" />
+			<span class="text-base font-medium text-gray-500 dark:text-gray-300"
+				>{filteredItems.length}</span
+			>
+		</div>
+	</div>
+</div>
 
-<div class="my-3 mb-5 grid lg:grid-cols-2 xl:grid-cols-3 gap-2">
+<div class="my-3 mb-5 grid md:grid-cols-2 lg:grid-cols-3 gap-2">
 	{#each filteredItems as item}
 		<button
-			class=" flex space-x-4 cursor-pointer text-left w-full px-4 py-3 border border-gray-50 dark:border-gray-850 hover:bg-gray-50 dark:hover:bg-gray-850 transition rounded-xl"
+			class=" flex space-x-4 cursor-pointer text-left w-full px-4 py-3 border border-gray-50 dark:border-gray-850 dark:hover:border-gray-800 hover:bg-gray-50 dark:hover:bg-gray-850 transition rounded-xl"
 			on:click={() => {
 				if (item?.meta?.document) {
 					toast.error(

+ 27 - 21
src/lib/components/workspace/Models.svelte

@@ -35,8 +35,16 @@
 	let modelsImportInputElement: HTMLInputElement;
 
 	let _models = [];
+
+	let filteredModels = [];
 	let selectedModel = null;
 
+	$: if (_models) {
+		filteredModels = _models.filter(
+			(m) => searchValue === '' || m.name.toLowerCase().includes(searchValue.toLowerCase())
+		);
+	}
+
 	let sortable = null;
 	let searchValue = '';
 
@@ -294,17 +302,7 @@
 	}}
 />
 
-<div class="mb-3">
-	<div class="flex justify-between items-center">
-		<div class="flex md:self-center text-lg font-medium px-0.5">
-			{$i18n.t('Models')}
-			<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" />
-			<span class="text-lg font-medium text-gray-500 dark:text-gray-300">{$models.length}</span>
-		</div>
-	</div>
-</div>
-
-<div class=" flex w-full space-x-2">
+<div class=" flex w-full space-x-2 mb-2.5">
 	<div class="flex flex-1">
 		<div class=" self-center ml-1 mr-3">
 			<svg
@@ -329,7 +327,7 @@
 
 	<div>
 		<a
-			class=" px-2 py-2 rounded-xl border border-gray-200 dark:border-gray-600 dark:border-0 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 transition font-medium text-sm flex items-center space-x-1"
+			class=" px-2 py-2 rounded-xl border border-gray-200 dark:border-gray-600 dark:border-0 hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800 transition font-medium text-sm flex items-center space-x-1"
 			href="/workspace/models/create"
 		>
 			<svg
@@ -346,12 +344,22 @@
 	</div>
 </div>
 
-<hr class=" border-gray-50 dark:border-gray-850 my-2.5" />
+<div class="mb-3.5">
+	<div class="flex justify-between items-center">
+		<div class="flex md:self-center text-base font-medium px-0.5">
+			{$i18n.t('Models')}
+			<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-850" />
+			<span class="text-base font-medium text-gray-500 dark:text-gray-300"
+				>{filteredModels.length}</span
+			>
+		</div>
+	</div>
+</div>
 
 <a class=" flex space-x-4 cursor-pointer w-full mb-2 px-3 py-1" href="/workspace/models/create">
-	<div class=" self-center w-10 flex-shrink-0">
+	<div class=" self-center w-8 flex-shrink-0">
 		<div
-			class="w-full h-10 flex justify-center rounded-full bg-transparent dark:bg-gray-700 border border-dashed border-gray-200"
+			class="w-full h-8 flex justify-center rounded-full bg-transparent dark:bg-gray-700 border border-dashed border-gray-200"
 		>
 			<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6">
 				<path
@@ -365,16 +373,14 @@
 
 	<div class=" self-center">
 		<div class=" font-semibold line-clamp-1">{$i18n.t('Create a model')}</div>
-		<div class=" text-sm line-clamp-1">{$i18n.t('Customize models for a specific purpose')}</div>
+		<div class=" text-sm line-clamp-1 text-gray-500">
+			{$i18n.t('Customize models for a specific purpose')}
+		</div>
 	</div>
 </a>
 
-<hr class=" border-gray-50 dark:border-gray-850 my-2.5" />
-
 <div class=" my-2 mb-5" id="model-list">
-	{#each _models.filter((m) => searchValue === '' || m.name
-				.toLowerCase()
-				.includes(searchValue.toLowerCase())) as model}
+	{#each filteredModels as model}
 		<div
 			class=" flex space-x-4 cursor-pointer w-full px-3 py-2 dark:hover:bg-white/5 hover:bg-black/5 rounded-xl"
 			id="model-item-{model.id}"

+ 16 - 13
src/lib/components/workspace/Prompts.svelte

@@ -21,6 +21,9 @@
 	let showDeleteConfirm = false;
 	let deletePrompt = null;
 
+	let filteredItems = [];
+	$: filteredItems = $prompts.filter((p) => query === '' || p.command.includes(query));
+
 	const shareHandler = async (prompt) => {
 		toast.success($i18n.t('Redirecting you to OpenWebUI Community'));
 
@@ -64,17 +67,7 @@
 	</title>
 </svelte:head>
 
-<div class="mb-3">
-	<div class="flex justify-between items-center">
-		<div class="flex md:self-center text-lg font-medium px-0.5">
-			{$i18n.t('Prompts')}
-			<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" />
-			<span class="text-lg font-medium text-gray-500 dark:text-gray-300">{$prompts.length}</span>
-		</div>
-	</div>
-</div>
-
-<div class=" flex w-full space-x-2">
+<div class=" flex w-full space-x-2 mb-2.5">
 	<div class="flex flex-1">
 		<div class=" self-center ml-1 mr-3">
 			<svg
@@ -116,10 +109,20 @@
 	</div>
 </div>
 
-<hr class=" border-gray-50 dark:border-gray-850 my-2.5" />
+<div class="mb-3.5">
+	<div class="flex justify-between items-center">
+		<div class="flex md:self-center text-base font-medium px-0.5">
+			{$i18n.t('Prompts')}
+			<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" />
+			<span class="text-base font-medium text-gray-500 dark:text-gray-300"
+				>{filteredItems.length}</span
+			>
+		</div>
+	</div>
+</div>
 
 <div class="my-3 mb-5">
-	{#each $prompts.filter((p) => query === '' || p.command.includes(query)) as prompt}
+	{#each filteredItems as prompt}
 		<div
 			class=" flex space-x-4 cursor-pointer w-full px-3 py-2 dark:hover:bg-white/5 hover:bg-black/5 rounded-xl"
 		>

+ 21 - 15
src/lib/components/workspace/Tools.svelte

@@ -42,6 +42,14 @@
 
 	let showDeleteConfirm = false;
 
+	let filteredItems = [];
+	$: filteredItems = $tools.filter(
+		(t) =>
+			query === '' ||
+			t.name.toLowerCase().includes(query.toLowerCase()) ||
+			t.id.toLowerCase().includes(query.toLowerCase())
+	);
+
 	const shareHandler = async (tool) => {
 		const item = await getToolById(localStorage.token, tool.id).catch((error) => {
 			toast.error(error);
@@ -146,17 +154,7 @@
 	</title>
 </svelte:head>
 
-<div class="mb-3">
-	<div class="flex justify-between items-center">
-		<div class="flex md:self-center text-lg font-medium px-0.5">
-			{$i18n.t('Tools')}
-			<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" />
-			<span class="text-lg font-medium text-gray-500 dark:text-gray-300">{$tools.length}</span>
-		</div>
-	</div>
-</div>
-
-<div class=" flex w-full space-x-2">
+<div class=" flex w-full space-x-2 mb-2.5">
 	<div class="flex flex-1">
 		<div class=" self-center ml-1 mr-3">
 			<svg
@@ -198,12 +196,20 @@
 	</div>
 </div>
 
-<hr class=" border-gray-50 dark:border-gray-850 my-2.5" />
+<div class="mb-3.5">
+	<div class="flex justify-between items-center">
+		<div class="flex md:self-center text-base font-medium px-0.5">
+			{$i18n.t('Tools')}
+			<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" />
+			<span class="text-base font-medium text-gray-500 dark:text-gray-300"
+				>{filteredItems.length}</span
+			>
+		</div>
+	</div>
+</div>
 
 <div class="my-3 mb-5">
-	{#each $tools.filter((t) => query === '' || t.name
-				.toLowerCase()
-				.includes(query.toLowerCase()) || t.id.toLowerCase().includes(query.toLowerCase())) as tool}
+	{#each filteredItems as tool}
 		<div
 			class=" flex space-x-4 cursor-pointer w-full px-3 py-2 dark:hover:bg-white/5 hover:bg-black/5 rounded-xl"
 		>

+ 27 - 25
src/routes/(app)/admin/+layout.svelte

@@ -30,12 +30,12 @@
 			? 'md:max-w-[calc(100%-260px)]'
 			: ''}"
 	>
-		<div class=" px-4 pt-3 mt-0.5 mb-1">
+		<div class=" px-3.5 py-2">
 			<div class=" flex items-center gap-1">
-				<div class="{$showSidebar ? 'md:hidden' : ''} mr-1 self-start flex flex-none items-center">
+				<div class="{$showSidebar ? 'md:hidden' : ''} mr-1 flex flex-none items-center">
 					<button
 						id="sidebar-toggle-button"
-						class="cursor-pointer p-1 flex rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
+						class="cursor-pointer p-1.5 flex rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
 						on:click={() => {
 							showSidebar.set(!$showSidebar);
 						}}
@@ -46,33 +46,35 @@
 						</div>
 					</button>
 				</div>
-				<div class="flex items-center text-xl font-semibold">{$i18n.t('Admin Panel')}</div>
-			</div>
-		</div>
+				<!-- <div class="flex items-center text-xl font-semibold">{$i18n.t('Admin Panel')}</div> -->
 
-		<div class="px-4 my-1">
-			<div
-				class="flex scrollbar-none overflow-x-auto w-fit text-center text-sm font-medium rounded-xl bg-transparent/10 p-1"
-			>
-				<a
-					class="min-w-fit rounded-lg p-1.5 px-3 {['/admin', '/admin/'].includes($page.url.pathname)
-						? 'bg-gray-50 dark:bg-gray-850'
-						: ''} transition"
-					href="/admin">{$i18n.t('Dashboard')}</a
-				>
+				<div class=" flex w-full">
+					<div
+						class="flex scrollbar-none overflow-x-auto w-fit text-center text-sm font-medium rounded-full bg-transparent/10 p-1"
+					>
+						<a
+							class="min-w-fit rounded-full p-1.5 px-3 {['/admin', '/admin/'].includes(
+								$page.url.pathname
+							)
+								? 'bg-gray-50 dark:bg-gray-850'
+								: ''} transition"
+							href="/admin">{$i18n.t('Dashboard')}</a
+						>
 
-				<a
-					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/admin/settings')
-						? 'bg-gray-50 dark:bg-gray-850'
-						: ''} transition"
-					href="/admin/settings">{$i18n.t('Settings')}</a
-				>
+						<a
+							class="min-w-fit rounded-full p-1.5 px-3 {$page.url.pathname.includes(
+								'/admin/settings'
+							)
+								? 'bg-gray-50 dark:bg-gray-850'
+								: ''} transition"
+							href="/admin/settings">{$i18n.t('Settings')}</a
+						>
+					</div>
+				</div>
 			</div>
 		</div>
 
-		<hr class=" my-2 dark:border-gray-850" />
-
-		<div class=" py-1 px-5 flex-1 max-h-full overflow-y-auto">
+		<div class=" pb-1 px-5 flex-1 max-h-full overflow-y-auto">
 			<slot />
 		</div>
 	</div>

+ 62 - 55
src/routes/(app)/workspace/+layout.svelte

@@ -1,6 +1,6 @@
 <script lang="ts">
 	import { onMount, getContext } from 'svelte';
-	import { WEBUI_NAME, showSidebar, functions, user } from '$lib/stores';
+	import { WEBUI_NAME, showSidebar, functions, user, mobile } from '$lib/stores';
 	import { page } from '$app/stores';
 	import { goto } from '$app/navigation';
 
@@ -26,16 +26,16 @@
 
 {#if loaded}
 	<div
-		class=" flex flex-col w-full min-h-screen max-h-screen {$showSidebar
+		class=" relative flex flex-col w-full min-h-screen max-h-screen {$showSidebar
 			? 'md:max-w-[calc(100%-260px)]'
 			: ''}"
 	>
-		<div class=" px-4 pt-3 mt-0.5 mb-1">
+		<div class="   px-3.5 my-2 bg-transparent backdrop-blur-xl">
 			<div class=" flex items-center gap-1">
-				<div class="{$showSidebar ? 'md:hidden' : ''} mr-1 self-start flex flex-none items-center">
+				<div class="{$showSidebar ? 'md:hidden' : ''} mr-1 self-center flex flex-none items-center">
 					<button
 						id="sidebar-toggle-button"
-						class="cursor-pointer p-1 flex rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
+						class="cursor-pointer p-1.5 flex rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
 						on:click={() => {
 							showSidebar.set(!$showSidebar);
 						}}
@@ -46,64 +46,71 @@
 						</div>
 					</button>
 				</div>
-				<div class="flex items-center text-xl font-semibold">{$i18n.t('Workspace')}</div>
-			</div>
-		</div>
 
-		<div class="px-4 my-1">
-			<div
-				class="flex scrollbar-none overflow-x-auto w-fit text-center text-sm font-medium rounded-xl bg-transparent/10 p-1"
-			>
-				<a
-					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/models')
-						? 'bg-gray-50 dark:bg-gray-850'
-						: ''} transition"
-					href="/workspace/models">{$i18n.t('Models')}</a
-				>
+				<!-- <div class="flex items-center text-xl font-semibold mr-3">{$i18n.t('Workspace')}</div> -->
+
+				<div class="">
+					<div
+						class="flex scrollbar-none overflow-x-auto w-fit text-center text-sm font-medium rounded-full bg-transparent/10 backdrop-blur-2xl p-1 shadow-2xl touch-auto pointer-events-auto"
+					>
+						<a
+							class="min-w-fit rounded-full p-1.5 px-3 {$page.url.pathname.includes(
+								'/workspace/models'
+							)
+								? 'bg-gray-50 dark:bg-gray-850'
+								: ''} transition"
+							href="/workspace/models">{$i18n.t('Models')}</a
+						>
 
-				<a
-					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes(
-						'/workspace/knowledge'
-					)
-						? 'bg-gray-50 dark:bg-gray-850'
-						: ''} transition"
-					href="/workspace/knowledge"
-				>
-					{$i18n.t('Knowledge')}
-				</a>
+						<a
+							class="min-w-fit rounded-full p-1.5 px-3 {$page.url.pathname.includes(
+								'/workspace/knowledge'
+							)
+								? 'bg-gray-50 dark:bg-gray-850'
+								: ''} transition"
+							href="/workspace/knowledge"
+						>
+							{$i18n.t('Knowledge')}
+						</a>
 
-				<a
-					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/prompts')
-						? 'bg-gray-50 dark:bg-gray-850'
-						: ''} transition"
-					href="/workspace/prompts">{$i18n.t('Prompts')}</a
-				>
+						<a
+							class="min-w-fit rounded-full p-1.5 px-3 {$page.url.pathname.includes(
+								'/workspace/prompts'
+							)
+								? 'bg-gray-50 dark:bg-gray-850'
+								: ''} transition"
+							href="/workspace/prompts">{$i18n.t('Prompts')}</a
+						>
 
-				<a
-					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/tools')
-						? 'bg-gray-50 dark:bg-gray-850'
-						: ''} transition"
-					href="/workspace/tools"
-				>
-					{$i18n.t('Tools')}
-				</a>
+						<a
+							class="min-w-fit rounded-full p-1.5 px-3 {$page.url.pathname.includes(
+								'/workspace/tools'
+							)
+								? 'bg-gray-50 dark:bg-gray-850'
+								: ''} transition"
+							href="/workspace/tools"
+						>
+							{$i18n.t('Tools')}
+						</a>
 
-				<a
-					class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes(
-						'/workspace/functions'
-					)
-						? 'bg-gray-50 dark:bg-gray-850'
-						: ''} transition"
-					href="/workspace/functions"
-				>
-					{$i18n.t('Functions')}
-				</a>
+						<a
+							class="min-w-fit rounded-full p-1.5 px-3 {$page.url.pathname.includes(
+								'/workspace/functions'
+							)
+								? 'bg-gray-50 dark:bg-gray-850'
+								: ''} transition"
+							href="/workspace/functions"
+						>
+							{$i18n.t('Functions')}
+						</a>
+					</div>
+				</div>
+
+				<!-- <div class="flex items-center text-xl font-semibold">{$i18n.t('Workspace')}</div> -->
 			</div>
 		</div>
 
-		<hr class=" my-2 border-gray-100 dark:border-gray-850" />
-
-		<div class=" py-1 px-5 flex-1 max-h-full overflow-y-auto">
+		<div class=" pb-1 px-5 flex-1 max-h-full overflow-y-auto">
 			<slot />
 		</div>
 	</div>