Frameless transparent window with custom title bar
Remove native window decorations and add transparent background with rounded corners, border, and drop shadow. Add custom close button (Linux) and minimize/maximize/close (Windows) in the header. Add programmatic window dragging via mousedown and double-click to maximize. Install tauri-plugin-os for platform detection. Move sync spinner to bottom-right corner. Convert drawer layout from vw to cqi units to support the padding-based shadow approach.
This commit is contained in:
parent
e5c78ddfde
commit
ea76f65579
12
apps/tauri/package-lock.json
generated
12
apps/tauri/package-lock.json
generated
|
|
@ -9,7 +9,8 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tauri-apps/api": "^2.0.0",
|
"@tauri-apps/api": "^2.0.0",
|
||||||
"@tauri-apps/plugin-dialog": "^2.0.0"
|
"@tauri-apps/plugin-dialog": "^2.0.0",
|
||||||
|
"@tauri-apps/plugin-os": "^2.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||||
|
|
@ -1421,6 +1422,15 @@
|
||||||
"@tauri-apps/api": "^2.8.0"
|
"@tauri-apps/api": "^2.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tauri-apps/plugin-os": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-os/-/plugin-os-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-n+nXWeuSeF9wcEsSPmRnBEGrRgOy6jjkSU+UVCOV8YUGKb2erhDOxis7IqRXiRVHhY8XMKks00BJ0OAdkpf6+A==",
|
||||||
|
"license": "MIT OR Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@tauri-apps/api": "^2.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tauri-apps/api": "^2.0.0",
|
"@tauri-apps/api": "^2.0.0",
|
||||||
"@tauri-apps/plugin-dialog": "^2.0.0"
|
"@tauri-apps/plugin-dialog": "^2.0.0",
|
||||||
|
"@tauri-apps/plugin-os": "^2.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ tauri-build = { version = "2", features = [] }
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tauri = { version = "2", features = [] }
|
tauri = { version = "2", features = [] }
|
||||||
tauri-plugin-dialog = "2"
|
tauri-plugin-dialog = "2"
|
||||||
|
tauri-plugin-os = "2"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
bevy-tasks-core = { path = "../../../crates/bevy-tasks-core" }
|
bevy-tasks-core = { path = "../../../crates/bevy-tasks-core" }
|
||||||
|
|
|
||||||
15
apps/tauri/src-tauri/capabilities/default.json
Normal file
15
apps/tauri/src-tauri/capabilities/default.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"identifier": "default",
|
||||||
|
"description": "Default capabilities for Bevy Tasks",
|
||||||
|
"windows": ["main"],
|
||||||
|
"permissions": [
|
||||||
|
"core:default",
|
||||||
|
"dialog:default",
|
||||||
|
"os:default",
|
||||||
|
"core:window:allow-close",
|
||||||
|
"core:window:allow-minimize",
|
||||||
|
"core:window:allow-toggle-maximize",
|
||||||
|
"core:window:allow-start-dragging",
|
||||||
|
"core:window:allow-is-maximized"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -353,6 +353,7 @@ pub fn run() {
|
||||||
|
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
|
.plugin(tauri_plugin_os::init())
|
||||||
.manage(Mutex::new(AppState { config, repo: None }))
|
.manage(Mutex::new(AppState { config, repo: None }))
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
get_config,
|
get_config,
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@
|
||||||
"height": 700,
|
"height": 700,
|
||||||
"minWidth": 320,
|
"minWidth": 320,
|
||||||
"minHeight": 500,
|
"minHeight": 500,
|
||||||
"resizable": true
|
"resizable": true,
|
||||||
|
"decorations": false,
|
||||||
|
"transparent": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"security": {
|
"security": {
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,14 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={app.darkMode ? "dark" : ""}>
|
<div class={app.darkMode ? "dark" : ""}>
|
||||||
|
<div class="h-screen w-screen p-2">
|
||||||
<div
|
<div
|
||||||
class="h-screen w-screen overflow-hidden bg-surface-light text-text-light dark:bg-surface-dark dark:text-text-dark"
|
class="relative h-full w-full overflow-hidden rounded-xl border border-black/15 bg-surface-light text-text-light dark:border-white/15 dark:bg-surface-dark dark:text-text-dark"
|
||||||
|
style="container-type: inline-size; box-shadow: 0 2px 8px rgba(0,0,0,0.25), 0 0 2px rgba(0,0,0,0.1)"
|
||||||
>
|
>
|
||||||
{#if app.error}
|
{#if app.error}
|
||||||
<div
|
<div
|
||||||
class="fixed top-0 left-0 right-0 z-50 flex items-center justify-between bg-danger px-4 py-2 text-sm text-white"
|
class="absolute top-0 left-0 right-0 z-50 flex items-center justify-between bg-danger px-4 py-2 text-sm text-white"
|
||||||
>
|
>
|
||||||
<span>{app.error}</span>
|
<span>{app.error}</span>
|
||||||
<button onclick={() => app.clearError()} class="ml-2 font-bold">✕</button>
|
<button onclick={() => app.clearError()} class="ml-2 font-bold">✕</button>
|
||||||
|
|
@ -29,4 +31,5 @@
|
||||||
<TasksScreen />
|
<TasksScreen />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,16 @@
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scrollbar styling */
|
/* Scrollbar styling */
|
||||||
|
|
@ -42,3 +47,9 @@ body {
|
||||||
.dark ::-webkit-scrollbar-thumb {
|
.dark ::-webkit-scrollbar-thumb {
|
||||||
background: #4b5563;
|
background: #4b5563;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Select dropdown theming */
|
||||||
|
.dark select option {
|
||||||
|
background-color: #242424;
|
||||||
|
color: #e5e7eb;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,28 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { app } from "../stores/app.svelte";
|
import { app } from "../stores/app.svelte";
|
||||||
import TaskItem from "../components/TaskItem.svelte";
|
import TaskItem from "../components/TaskItem.svelte";
|
||||||
|
import TaskDetailView from "../components/TaskDetailView.svelte";
|
||||||
import NewTaskInput, { newTaskState } from "../components/NewTaskInput.svelte";
|
import NewTaskInput, { newTaskState } from "../components/NewTaskInput.svelte";
|
||||||
import SettingsScreen from "./SettingsScreen.svelte";
|
import SettingsScreen from "./SettingsScreen.svelte";
|
||||||
|
import { getCurrentWindow } from "@tauri-apps/api/window";
|
||||||
|
import { platform } from "@tauri-apps/plugin-os";
|
||||||
|
import type { Task } from "../types";
|
||||||
|
|
||||||
|
const appWindow = getCurrentWindow();
|
||||||
|
const currentPlatform = platform();
|
||||||
|
const isDesktop = currentPlatform === "linux" || currentPlatform === "windows";
|
||||||
|
const isWindows = currentPlatform === "windows";
|
||||||
|
|
||||||
|
let selectedTaskId = $state<string | null>(null);
|
||||||
|
let selectedTask = $derived(selectedTaskId ? app.tasks.find(t => t.id === selectedTaskId) ?? null : null);
|
||||||
|
|
||||||
|
function openTask(task: Task) {
|
||||||
|
selectedTaskId = task.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeDetail() {
|
||||||
|
selectedTaskId = null;
|
||||||
|
}
|
||||||
|
|
||||||
let showDrawer = $state(false);
|
let showDrawer = $state(false);
|
||||||
let showSettings = $state(false);
|
let showSettings = $state(false);
|
||||||
|
|
@ -23,8 +43,8 @@
|
||||||
window.addEventListener("mousedown", handleWindowClick);
|
window.addEventListener("mousedown", handleWindowClick);
|
||||||
}
|
}
|
||||||
let newListName = $state("");
|
let newListName = $state("");
|
||||||
let showCompleted = $state(true);
|
let showCompleted = $state(false);
|
||||||
let completedVisible = $state(true);
|
let completedVisible = $state(false);
|
||||||
let listMenuId = $state<string | null>(null);
|
let listMenuId = $state<string | null>(null);
|
||||||
let wsMenuName = $state<string | null>(null);
|
let wsMenuName = $state<string | null>(null);
|
||||||
let dragId = $state<string | null>(null);
|
let dragId = $state<string | null>(null);
|
||||||
|
|
@ -113,19 +133,25 @@
|
||||||
showSettings = false;
|
showSettings = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleHeaderMouseDown(e: MouseEvent) {
|
||||||
|
if (e.button !== 0) return;
|
||||||
|
if ((e.target as HTMLElement).closest("button")) return;
|
||||||
|
if (isDesktop) appWindow.startDragging();
|
||||||
|
}
|
||||||
|
|
||||||
let workspaceNames = $derived(app.config ? Object.keys(app.config.workspaces) : []);
|
let workspaceNames = $derived(app.config ? Object.keys(app.config.workspaces) : []);
|
||||||
let translateX = $derived(showDrawer ? '0' : '-80vw');
|
let translateX = $derived(showDrawer ? '0' : '-80cqi');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Viewport clip -->
|
<!-- Viewport clip -->
|
||||||
<div class="h-screen w-screen overflow-hidden">
|
<div class="h-full w-full overflow-hidden">
|
||||||
<!-- Sliding container: left drawer + main content -->
|
<!-- Sliding container: left drawer + main content -->
|
||||||
<div
|
<div
|
||||||
class="flex h-full ease-out {resizing ? '' : 'transition-transform duration-250'}"
|
class="flex h-full ease-out {resizing ? '' : 'transition-transform duration-250'}"
|
||||||
style="width: calc(100vw + 80vw); transform: translateX({translateX})"
|
style="width: calc(100cqi + 80cqi); transform: translateX({translateX})"
|
||||||
>
|
>
|
||||||
<!-- Drawer panel -->
|
<!-- Drawer panel -->
|
||||||
<div class="flex h-full w-[80vw] shrink-0 flex-col bg-surface-light dark:bg-surface-dark">
|
<div class="flex h-full shrink-0 flex-col bg-surface-light dark:bg-surface-dark" style="width: 80cqi">
|
||||||
<!-- List items + new list button -->
|
<!-- List items + new list button -->
|
||||||
<div class="flex-1 overflow-y-auto py-2">
|
<div class="flex-1 overflow-y-auto py-2">
|
||||||
{#each app.lists as list (list.id)}
|
{#each app.lists as list (list.id)}
|
||||||
|
|
@ -287,7 +313,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Main content panel -->
|
<!-- Main content panel -->
|
||||||
<div class="relative flex h-full w-screen shrink-0 flex-col bg-surface-light dark:bg-surface-dark">
|
<div class="relative h-full shrink-0 overflow-hidden bg-surface-light dark:bg-surface-dark" style="width: 100cqi">
|
||||||
<!-- Dim overlay when drawer is open -->
|
<!-- Dim overlay when drawer is open -->
|
||||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<div
|
<div
|
||||||
|
|
@ -296,17 +322,28 @@
|
||||||
onclick={closeDrawer}
|
onclick={closeDrawer}
|
||||||
onkeydown={(e) => { if (e.key === "Escape") closeDrawer(); }}
|
onkeydown={(e) => { if (e.key === "Escape") closeDrawer(); }}
|
||||||
></div>
|
></div>
|
||||||
<!-- Header -->
|
|
||||||
|
<!-- Sliding inner: task list + detail view -->
|
||||||
|
<div
|
||||||
|
class="flex h-full {resizing ? '' : 'transition-transform duration-250'} ease-out"
|
||||||
|
style="width: 200%; transform: translateX({selectedTask ? '-50%' : '0'})"
|
||||||
|
>
|
||||||
|
<!-- Sub-panel: Task list -->
|
||||||
|
<div class="relative flex h-full w-1/2 flex-col">
|
||||||
|
<!-- Header / drag region -->
|
||||||
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<header
|
<header
|
||||||
|
onmousedown={handleHeaderMouseDown}
|
||||||
|
ondblclick={() => { if (isDesktop) appWindow.toggleMaximize(); }}
|
||||||
class="relative flex items-center border-b border-border-light px-4 py-3 dark:border-border-dark"
|
class="relative flex items-center border-b border-border-light px-4 py-3 dark:border-border-dark"
|
||||||
>
|
>
|
||||||
<!-- Back arrow (left) -->
|
<!-- Drawer toggle (left) -->
|
||||||
<button
|
<button
|
||||||
onclick={() => (showDrawer = !showDrawer)}
|
onclick={() => (showDrawer = !showDrawer)}
|
||||||
class="absolute left-2 rounded-lg p-1.5 hover:bg-black/5 dark:hover:bg-white/10"
|
class="absolute left-2 rounded-lg p-1.5 hover:bg-black/5 dark:hover:bg-white/10"
|
||||||
>
|
>
|
||||||
<svg class="h-5 w-5 opacity-60" viewBox="0 0 20 20" fill="currentColor">
|
<svg class="h-5 w-5 opacity-60" viewBox="0 0 20 20" fill="currentColor">
|
||||||
<path fill-rule="evenodd" d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" />
|
<path d="M3 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h8a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
@ -318,9 +355,36 @@
|
||||||
<p class="text-lg font-bold">{app.activeList?.title ?? "Tasks"}</p>
|
<p class="text-lg font-bold">{app.activeList?.title ?? "Tasks"}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Sync spinner (right) -->
|
<!-- Window controls (right) -->
|
||||||
{#if app.syncing}
|
{#if isDesktop}
|
||||||
<div class="absolute right-4 h-5 w-5 animate-spin rounded-full border-2 border-primary border-t-transparent"></div>
|
<div class="absolute right-1.5 flex items-center gap-0.5">
|
||||||
|
{#if isWindows}
|
||||||
|
<button
|
||||||
|
onclick={() => appWindow.minimize()}
|
||||||
|
class="rounded p-1.5 opacity-50 hover:bg-black/10 hover:opacity-80 dark:hover:bg-white/10"
|
||||||
|
>
|
||||||
|
<svg class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path d="M4 10a1 1 0 011-1h10a1 1 0 110 2H5a1 1 0 01-1-1z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onclick={() => appWindow.toggleMaximize()}
|
||||||
|
class="rounded p-1.5 opacity-50 hover:bg-black/10 hover:opacity-80 dark:hover:bg-white/10"
|
||||||
|
>
|
||||||
|
<svg class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<rect x="3" y="3" width="14" height="14" rx="1" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
<button
|
||||||
|
onclick={() => appWindow.close()}
|
||||||
|
class="rounded p-1.5 opacity-50 hover:bg-danger/20 hover:opacity-100 hover:text-danger dark:hover:bg-danger/20"
|
||||||
|
>
|
||||||
|
<svg class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
@ -346,7 +410,7 @@
|
||||||
ondrop={(e) => handleDrop(e, task.id)}
|
ondrop={(e) => handleDrop(e, task.id)}
|
||||||
class="{dragId === task.id ? 'opacity-30' : ''} {dragOverId === task.id && dragId !== task.id ? 'border-t-2 border-t-primary' : ''}"
|
class="{dragId === task.id ? 'opacity-30' : ''} {dragOverId === task.id && dragId !== task.id ? 'border-t-2 border-t-primary' : ''}"
|
||||||
>
|
>
|
||||||
<TaskItem {task} />
|
<TaskItem {task} onopen={openTask} />
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
|
|
@ -383,7 +447,7 @@
|
||||||
{#if completedVisible}
|
{#if completedVisible}
|
||||||
<div class="transition-all duration-300 ease-out {showCompleted ? 'opacity-100 translate-y-0' : 'opacity-0 -translate-y-4'}">
|
<div class="transition-all duration-300 ease-out {showCompleted ? 'opacity-100 translate-y-0' : 'opacity-0 -translate-y-4'}">
|
||||||
{#each app.completedTasks as task (task.id)}
|
{#each app.completedTasks as task (task.id)}
|
||||||
<TaskItem {task} />
|
<TaskItem {task} onopen={openTask} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -393,7 +457,7 @@
|
||||||
|
|
||||||
<!-- FAB button -->
|
<!-- FAB button -->
|
||||||
<div
|
<div
|
||||||
class="pointer-events-none absolute bottom-6 left-0 right-0 z-30 flex justify-center transition-all duration-250 ease-out {newTaskState.open ? 'opacity-0 scale-75' : ''} {showDrawer ? 'translate-y-24 opacity-0' : 'translate-y-0 opacity-100'}"
|
class="pointer-events-none absolute bottom-6 left-0 right-0 z-20 flex justify-center transition-all duration-250 ease-out {newTaskState.open ? 'opacity-0 scale-75' : ''} {showDrawer || selectedTask ? 'translate-y-24 opacity-0' : 'translate-y-0 opacity-100'}"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
onclick={() => { if (app.activeListId) newTaskState.open = true; }}
|
onclick={() => { if (app.activeListId) newTaskState.open = true; }}
|
||||||
|
|
@ -406,13 +470,27 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Sub-panel: Task detail -->
|
||||||
|
<div class="relative flex h-full w-1/2 flex-col bg-surface-light dark:bg-surface-dark">
|
||||||
|
{#if selectedTask}
|
||||||
|
<TaskDetailView task={selectedTask} onback={closeDetail} />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Sync spinner -->
|
||||||
|
{#if app.syncing}
|
||||||
|
<div class="absolute bottom-4 right-4 z-20 h-5 w-5 animate-spin rounded-full border-2 border-primary border-t-transparent"></div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Settings popup overlay -->
|
<!-- Settings popup overlay -->
|
||||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<div
|
<div
|
||||||
class="fixed inset-0 z-50 flex transition-opacity duration-200 {showSettings ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}"
|
class="absolute inset-0 z-50 flex transition-opacity duration-200 {showSettings ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}"
|
||||||
style="padding: 4%"
|
style="padding: 4%"
|
||||||
>
|
>
|
||||||
<!-- Backdrop -->
|
<!-- Backdrop -->
|
||||||
|
|
@ -431,6 +509,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Toast overlay (outside sliding container so it stays centered) -->
|
<!-- Toast overlay (outside sliding container so it stays centered) -->
|
||||||
<div class="pointer-events-none fixed inset-0 z-50">
|
<div class="pointer-events-none absolute inset-0 z-50">
|
||||||
<NewTaskInput />
|
<NewTaskInput />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue