feat(briefing): tabbed weather locations, sticky weather, wider sidebar
Add location tabs when multiple weather sources configured. Weather section stays pinned at top of sidebar while news scrolls independently. Bump sidebar width from 420px to 620px max for better readability. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -56,8 +56,9 @@ const todayConvId = ref<number | null>(null)
|
|||||||
|
|
||||||
const isToday = computed(() => selectedConvId.value === todayConvId.value)
|
const isToday = computed(() => selectedConvId.value === todayConvId.value)
|
||||||
|
|
||||||
// Weather panel (left column)
|
// Weather panel
|
||||||
const weatherData = ref<WeatherData[]>([])
|
const weatherData = ref<WeatherData[]>([])
|
||||||
|
const selectedWeatherIdx = ref(0)
|
||||||
const tempUnit = ref<string>('C')
|
const tempUnit = ref<string>('C')
|
||||||
|
|
||||||
interface CurrentConditions {
|
interface CurrentConditions {
|
||||||
@@ -274,17 +275,25 @@ onMounted(async () => {
|
|||||||
|
|
||||||
<!-- Right column: Weather + News -->
|
<!-- Right column: Weather + News -->
|
||||||
<div class="briefing-right">
|
<div class="briefing-right">
|
||||||
<!-- Weather section -->
|
<!-- Weather section (sticky) -->
|
||||||
<template v-if="weatherData.length">
|
<div class="weather-section" v-if="weatherData.length">
|
||||||
|
<div class="weather-tabs" v-if="weatherData.length > 1">
|
||||||
|
<button
|
||||||
|
v-for="(loc, i) in weatherData"
|
||||||
|
:key="(loc as WeatherData).location"
|
||||||
|
class="weather-tab"
|
||||||
|
:class="{ active: selectedWeatherIdx === i }"
|
||||||
|
@click="selectedWeatherIdx = i"
|
||||||
|
>{{ (loc as WeatherData).location }}</button>
|
||||||
|
</div>
|
||||||
<WeatherCard
|
<WeatherCard
|
||||||
v-for="loc in weatherData"
|
:weather="weatherData[selectedWeatherIdx]"
|
||||||
:key="(loc as WeatherData).location"
|
|
||||||
:weather="loc"
|
|
||||||
:temp-unit="tempUnit"
|
:temp-unit="tempUnit"
|
||||||
/>
|
/>
|
||||||
</template>
|
</div>
|
||||||
|
|
||||||
<!-- News section -->
|
<!-- News section (scrollable) -->
|
||||||
|
<div class="news-section">
|
||||||
<div class="panel-label-row">
|
<div class="panel-label-row">
|
||||||
<div class="panel-label">Today's News</div>
|
<div class="panel-label">Today's News</div>
|
||||||
<span v-if="newsItems.length" class="news-count">{{ newsItems.length }} items</span>
|
<span v-if="newsItems.length" class="news-count">{{ newsItems.length }} items</span>
|
||||||
@@ -329,6 +338,7 @@ onMounted(async () => {
|
|||||||
>💬</button>
|
>💬</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -344,7 +354,7 @@ onMounted(async () => {
|
|||||||
|
|
||||||
.briefing-shell {
|
.briefing-shell {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr minmax(320px, 420px);
|
grid-template-columns: 1fr minmax(420px, 620px);
|
||||||
grid-template-rows: auto 1fr;
|
grid-template-rows: auto 1fr;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
@@ -438,17 +448,60 @@ onMounted(async () => {
|
|||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
grid-row: 2;
|
grid-row: 2;
|
||||||
border-left: 1px solid var(--color-border);
|
border-left: 1px solid var(--color-border);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-section {
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 1rem 1rem 0.5rem;
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-section :deep(.weather-card) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-tabs {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-tab {
|
||||||
|
padding: 0.3rem 0.7rem;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: 6px;
|
||||||
|
background: none;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-family: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-tab:hover {
|
||||||
|
border-color: var(--color-primary);
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-tab.active {
|
||||||
|
background: color-mix(in srgb, var(--color-primary) 12%, transparent);
|
||||||
|
border-color: var(--color-primary);
|
||||||
|
color: var(--color-primary);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.news-section {
|
||||||
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 1rem;
|
padding: 0.75rem 1rem 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.briefing-right :deep(.weather-card) {
|
|
||||||
margin-bottom: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-label {
|
.panel-label {
|
||||||
font-size: 0.72rem;
|
font-size: 0.72rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -561,7 +614,7 @@ a.news-title:hover { text-decoration: underline; color: var(--color-primary); }
|
|||||||
|
|
||||||
/* ─── Responsive ─────────────────────────────────────────────────────────── */
|
/* ─── Responsive ─────────────────────────────────────────────────────────── */
|
||||||
|
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 900px) {
|
||||||
.briefing-shell {
|
.briefing-shell {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
grid-template-rows: auto 1fr auto;
|
grid-template-rows: auto 1fr auto;
|
||||||
|
|||||||
Reference in New Issue
Block a user