fix: floating mini-chat overlay style + weather precip fallback

- KnowledgeView mini-chat: replace harsh border-top with upward box-shadow
  and rounded top corners (16px); remove padding-bottom from content area
  so widget truly overlays cards without pushing layout; add collapse
  toggle (chevron) that hides messages without closing the conversation
- WeatherCard: show precip_mm as fallback when precipitation_probability_max
  is null but actual rainfall is expected (Open-Meteo omits probability for
  some forecast days even when rain is shown)
- Pass precip_mm through weather service → frontend type definitions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-01 09:04:47 -04:00
parent a0620c4949
commit 5924e565b1
4 changed files with 29 additions and 9 deletions
+7 -1
View File
@@ -7,6 +7,7 @@ interface ForecastDay {
high: number
low: number
precip_probability: number | null
precip_mm: number | null
windspeed_max: number
}
@@ -90,7 +91,12 @@ const fetchedAtLabel = computed(() => {
<span class="forecast-icon">{{ weatherIcon(day.condition) }}</span>
<span class="forecast-condition">{{ day.condition }}</span>
<span class="forecast-temps">{{ day.high }}° / {{ day.low }}°</span>
<span v-if="day.precip_probability != null && day.precip_probability > 0" class="forecast-precip">💧 {{ day.precip_probability }}%</span>
<span v-if="day.precip_probability != null && day.precip_probability > 0" class="forecast-precip">
💧 {{ day.precip_probability }}%
</span>
<span v-else-if="day.precip_mm != null && day.precip_mm > 0" class="forecast-precip">
💧 {{ day.precip_mm.toFixed(1) }}mm
</span>
<span v-else class="forecast-precip forecast-precip--dry">💧 </span>
<span class="forecast-wind">💨 {{ day.windspeed_max }} {{ weather.wind_unit ?? 'km/h' }}</span>
</div>
+1 -1
View File
@@ -36,7 +36,7 @@ interface WeatherData {
yesterday_high: number | null
yesterday_low: number | null
wind_unit?: string
forecast: { day: string; condition: string; high: number; low: number; precip_probability: number | null; windspeed_max: number }[]
forecast: { day: string; condition: string; high: number; low: number; precip_probability: number | null; precip_mm: number | null; windspeed_max: number }[]
}
const chatStore = useChatStore()
+20 -7
View File
@@ -136,6 +136,7 @@ function toggleGraph() {
const chatInput = ref("");
const chatOpen = ref(false);
const chatCollapsed = ref(false);
const chatConvId = ref<number | null>(null);
const chatSending = ref(false);
const chatMessages = computed(() => {
@@ -437,8 +438,8 @@ onUnmounted(() => {
<!-- Floating mini-chat -->
<div class="minichat" :class="{ 'minichat--open': chatOpen }">
<!-- Message history (shown when chatOpen) -->
<div v-if="chatOpen" class="minichat-messages" ref="chatScrollEl">
<!-- Message history (shown when chatOpen and not collapsed) -->
<div v-if="chatOpen && !chatCollapsed" class="minichat-messages" ref="chatScrollEl">
<template v-if="chatMessages.length === 0 && !chatStore.streaming">
<div class="minichat-welcome">Ask me anything about your notes, tasks, or ideas.</div>
</template>
@@ -495,6 +496,17 @@ onUnmounted(() => {
title="Send"
>&uarr;</button>
</div>
<button
v-if="chatOpen"
class="btn-close-chat"
@click="chatCollapsed = !chatCollapsed"
:title="chatCollapsed ? 'Expand chat' : 'Collapse chat'"
>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
<polyline v-if="chatCollapsed" points="18 15 12 9 6 15"/>
<polyline v-else points="6 9 12 15 18 9"/>
</svg>
</button>
<button
v-if="chatOpen"
class="btn-close-chat"
@@ -633,7 +645,6 @@ onUnmounted(() => {
flex-direction: column;
overflow: hidden;
min-width: 0;
padding-bottom: 64px; /* space for minichat input */
}
/* ── Toolbar ─────────────────────────────────────────────── */
@@ -904,9 +915,10 @@ onUnmounted(() => {
z-index: 20;
display: flex;
flex-direction: column;
border-top: 1px solid var(--color-border, rgba(255,255,255,0.06));
background: var(--color-bg-secondary);
transition: all 0.2s;
border-radius: 16px 16px 0 0;
box-shadow: 0 -8px 32px rgba(0,0,0,0.35), 0 -1px 0 rgba(255,255,255,0.05);
transition: box-shadow 0.2s;
}
.knowledge-root.graph-open .minichat {
right: 420px;
@@ -918,8 +930,9 @@ onUnmounted(() => {
display: flex;
flex-direction: column;
gap: 8px;
background: var(--color-bg);
border-bottom: 1px solid var(--color-border, rgba(255,255,255,0.06));
background: transparent;
border-bottom: 1px solid rgba(255,255,255,0.05);
border-radius: 16px 16px 0 0;
}
.minichat-welcome {
color: var(--color-muted);