Compare commits

...

3 Commits

Author SHA1 Message Date
Roberto
ca669a1c5c chore(contextual): use sm trigger + scroll context fixes
- AdiuvaTriggerButton uses sm variant (40px, icon 24px)
- AppShell main scroll container: overflow-hidden + flex column so
  routes own their own scroll. Sticky ProjectTabBar still anchors
  to header boundary
- tasks.tsx wrapper gets h-full + overflow-y-auto under the new
  scroll regime
2026-05-15 07:54:26 +02:00
Roberto
ffd0e97508 fix(contextual): better contrast trigger button + use logo-mark.svg asset
- AdiuvaIcon now uses /logo/logo-mark.svg directly (served via vite
  publicDir from adiuvAI/assets/); animation is built into the asset
- Light mode: pure white surface + dusty lavender border so the
  button reads on the pinkish-white canvas; centered ambient shadow
  (was bottom-heavy)
- Dark mode: lifted surface (#1f1f22) with subtle inner highlight
- sm variant bumped to 40px (icon 18px) for sidebar new-chat/close
2026-05-15 07:53:40 +02:00
Roberto
2bc9617b14 fix(layout): restore scroll on tasks and timeline pages
AppShell's post-header wrap div used overflow-hidden to scope a
sticky context for ProjectTabBar. Pages without their own internal
scroll container (tasks, timeline) had their overflow clipped.

overflow-y-auto on the same div keeps the sticky context AND lets
tasks/timeline scroll naturally. Projects' nested scroll container
still works (sticky inside still anchors to this boundary).
2026-05-15 07:37:43 +02:00
6 changed files with 56 additions and 29 deletions

View File

@@ -1,17 +1,17 @@
export interface AdiuvaIconProps {
size?: number;
/** South-half color. Defaults to off-white for dark backgrounds. */
southColor?: string;
}
export function AdiuvaIcon({ size = 22, southColor = '#e5e5e7' }: AdiuvaIconProps) {
export function AdiuvaIcon({ size = 24 }: AdiuvaIconProps) {
return (
<svg width={size} height={size} viewBox="0 0 64 64" fill="none" aria-hidden="true">
<g className="adiuva-needle-g">
<path d="M32,4 L48,32 L16,32 Z" fill="#fbc881" />
<path d="M16,32 L48,32 L32,60 Z" fill={southColor} />
<circle cx="32" cy="32" r="2.5" fill="#fff" opacity="0.3" />
</g>
</svg>
<img
src="/logo/logo-mark.svg"
width={size}
height={size}
alt=""
aria-hidden="true"
draggable={false}
className="adiuva-mark-img select-none pointer-events-none"
/>
);
}

View File

@@ -11,7 +11,7 @@ export function AdiuvaTriggerButton() {
aria-pressed={open}
className="adiuva-btn sm"
>
<AdiuvaIcon size={14} />
<AdiuvaIcon size={24} />
</button>
);
}

View File

@@ -15,10 +15,10 @@ export function ContextualSidebar() {
void newChat();
}}
>
<Plus size={14} />
<Plus size={18} />
</button>
<button type="button" className="adiuva-btn sm" title="Close sidebar" onClick={close}>
<X size={14} />
<X size={18} />
</button>
</div>
<ChatSurface

View File

@@ -233,8 +233,10 @@ function AppShellInner({ children }: AppShellProps) {
)}
{/* This div creates a new overflow/sticky context scoped BELOW the header,
so sticky elements inside (e.g. ProjectTabBar) anchor to this boundary
and never slide behind the AppShell header. */}
<div className="flex-1 min-h-0 overflow-hidden">
and never slide behind the AppShell header. Routes own their own
scroll behavior: tasks/notes scroll the whole route content; timeline
fills the area and scrolls only the inner Gantt table. */}
<div className="flex-1 min-h-0 flex flex-col overflow-hidden">
<MainArea>
{children}
</MainArea>

View File

@@ -377,30 +377,54 @@ body {
display: inline-flex;
align-items: center;
justify-content: center;
background: var(--card);
border: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
/* Light mode: pure white pops on pinkish canvas (#f4edf3). */
background: #ffffff;
border: 1px solid #c8c3cd;
border-radius: 14px;
cursor: pointer;
transition: box-shadow .3s ease, background .2s ease;
transition: box-shadow .25s ease, background .2s ease, border-color .2s ease;
/* Centered ambient shadow, not bottom-weighted. */
box-shadow:
inset 0 1px 0 color-mix(in srgb, white 6%, transparent),
0 2px 4px -1px rgba(0, 0, 0, .5),
0 8px 16px -4px rgba(0, 0, 0, .55),
0 20px 36px -10px rgba(0, 0, 0, .6);
0 0 0 1px rgba(0, 0, 0, .02),
0 2px 8px -2px rgba(0, 0, 0, .08),
0 6px 16px -4px rgba(0, 0, 0, .06);
color: inherit;
padding: 0;
}
.adiuva-btn:hover {
background: color-mix(in srgb, var(--card) 92%, white 8%);
background: #ffffff;
border-color: color-mix(in srgb, #c8c3cd 50%, #fbc881 50%);
box-shadow:
inset 0 1px 0 color-mix(in srgb, white 6%, transparent),
0 4px 8px -2px rgba(0, 0, 0, .6),
0 18px 28px -8px rgba(0, 0, 0, .65),
0 30px 60px -14px rgba(251, 200, 129, .22);
0 0 0 1px rgba(251, 200, 129, .25),
0 2px 10px -2px rgba(0, 0, 0, .10),
0 8px 22px -4px rgba(251, 200, 129, .22);
}
.adiuva-btn:active { transform: scale(.97); }
.adiuva-btn.sm { width: 32px; height: 32px; border-radius: 10px; }
.adiuva-btn.sm { width: 40px; height: 40px; border-radius: 12px; }
/* Dark mode: surface needs to lift off near-black canvas (#0c0c0c). */
.dark .adiuva-btn {
background: #1f1f22;
border-color: rgba(255, 255, 255, .08);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .05),
0 0 0 1px rgba(0, 0, 0, .35),
0 4px 14px -2px rgba(0, 0, 0, .55),
0 10px 24px -6px rgba(0, 0, 0, .45);
}
.dark .adiuva-btn:hover {
background: #26262a;
border-color: rgba(251, 200, 129, .18);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .06),
0 0 0 1px rgba(251, 200, 129, .12),
0 4px 18px -2px rgba(0, 0, 0, .6),
0 12px 28px -8px rgba(251, 200, 129, .25);
}
/* The asset SVG already animates internally — img tag uses its own keyframes.
These external keyframes remain only for the older inline-SVG path (kept
for back-compat if any consumer still uses <AdiuvaIcon> inline). */
.adiuva-needle-g {
transform-origin: 32px 32px;
animation: adiuva-compass-settle 6s ease-in-out infinite;
@@ -414,4 +438,5 @@ body {
}
@media (prefers-reduced-motion: reduce) {
.adiuva-needle-g { animation: none; }
.adiuva-mark-img { animation: none; }
}

View File

@@ -38,7 +38,7 @@ function TasksPage() {
}, [allTasks]);
return (
<div className="flex flex-col gap-6 p-6 pt-0 w-full">
<div className="flex flex-col gap-6 p-6 pt-0 w-full h-full overflow-y-auto">
<div ref={overviewRef} data-ai-section="tasks-overview" className="grid grid-cols-4 gap-4">
<Item variant="muted">
<ItemMedia variant="icon"><ClipboardCheck /></ItemMedia>