Redesign main app: slim top bar, dynamic sky hero, nowcast, scrub chart, unified palette
- One slate/blue palette across the app, dashboard, account/login pages (data colours stay orange = warm, blue = cool on the dashboard) - Slim sticky top bar with location chip, gear (settings) and ? (learn); 4-tab nav (Now, Station, Map, Alerts) with a thumb-reach bottom bar on phones - Hero sky gradient by condition/time with rain, storm, snow and star effects (respects reduced motion); keeps the searched city and badges when temps come from your station - One-line summary, 'Next 2 hours' bars and rain countdown from 15-minute precipitation, rain/cold-aware 'Bring' chips; yesterday + 'vs usual' context from the station - Scrubbable hourly chart (temp, rain chance, wind), 7-day range bars, AQI gauge, details tiles instead of drawers, taller radar with location marker + alert polygons - Skeleton loading instead of a full-screen spinner, sticky section headers, safe areas - Server: minutely_15 precipitation, public /api/station/summary Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1830fb2e2b
commit
fd61e35b56
16 files changed
+846
-221
No files matched your search
+115
-143
@@ -6,8 +6,8 @@
|
||||
<title>NeCloud Weather</title>
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<link rel="apple-touch-icon" href="/icons/icon.svg">
|
||||
<meta name="theme-color" content="#f5f2ec" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#191510" media="(prefers-color-scheme: dark)">
|
||||
<meta name="theme-color" content="#edf2f7" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#070c14" media="(prefers-color-scheme: dark)">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="apple-mobile-web-app-title" content="NeCloud Weather">
|
||||
@@ -18,37 +18,36 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@700;800&family=Barlow:wght@400;500;600&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="station-live.css">
|
||||
<link rel="stylesheet" href="app-ui.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="offline-banner" class="offline-banner hidden">No internet connection — showing cached data</div>
|
||||
<div id="ptr-indicator" class="ptr-indicator hidden">↓ Refreshing…</div>
|
||||
<div class="app">
|
||||
|
||||
<header class="masthead">
|
||||
<h1>NeCloud Weather</h1>
|
||||
<nav class="tabs">
|
||||
<button class="tab active" data-tab="conditions">Conditions</button>
|
||||
<header class="topbar">
|
||||
<a class="brand" href="/" aria-label="NeCloud Weather home"><span class="brand-mark">☁︎</span><span class="brand-name">NeCloud</span></a>
|
||||
<nav class="tabs" aria-label="Sections">
|
||||
<button class="tab active" data-tab="conditions">Now</button>
|
||||
<button class="tab" data-tab="station">Station</button>
|
||||
<button class="tab" data-tab="unified-map">Map</button>
|
||||
<button class="tab" data-tab="alerts">Alerts<span class="alert-badge hidden" id="alert-badge-nav"></span></button>
|
||||
<button class="tab" data-tab="learn">Learn</button>
|
||||
<button class="tab" data-tab="settings">Settings</button>
|
||||
</nav>
|
||||
<span class="tagline">Open-Meteo · RainViewer</span>
|
||||
<nav class="station-links">
|
||||
<a href="/dashboard" class="station-link">Dashboard</a>
|
||||
</nav>
|
||||
<div class="topbar-actions">
|
||||
<button class="loc-chip" id="tb-search" type="button" aria-label="Change location"><span class="loc-chip-ico">⌕</span><span id="tb-loc">Location</span></button>
|
||||
<a class="icon-btn" href="/dashboard" title="Station dashboard" aria-label="Station dashboard">▤</a>
|
||||
<button class="icon-btn" data-tab="learn" type="button" title="Learn" aria-label="Learn">?</button>
|
||||
<button class="icon-btn" data-tab="settings" type="button" title="Settings" aria-label="Settings">⚙</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Loading -->
|
||||
<div id="loading" class="loading hidden">
|
||||
<div class="loading-container">
|
||||
<div class="loading-icon">🌤️</div>
|
||||
<div class="loading-text">Fetching weather data…</div>
|
||||
<div class="loading-dots">
|
||||
<span></span><span></span><span></span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Loading: skeleton of the Now tab -->
|
||||
<div id="loading" class="loading hidden" aria-busy="true" aria-label="Loading weather">
|
||||
<div class="sk sk-hero"></div>
|
||||
<div class="sk sk-line"></div>
|
||||
<div class="sk sk-card"></div>
|
||||
<div class="sk sk-card tall"></div>
|
||||
<div class="sk-rows"><div class="sk sk-row"></div><div class="sk sk-row"></div><div class="sk sk-row"></div></div>
|
||||
</div>
|
||||
|
||||
<!-- ── TAB: CONDITIONS ── -->
|
||||
@@ -66,8 +65,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── HERO ── -->
|
||||
<div class="hero">
|
||||
<!-- ── HERO (dynamic sky) ── -->
|
||||
<div class="hero" id="hero">
|
||||
<canvas id="sky-fx" class="sky-fx" aria-hidden="true"></canvas>
|
||||
<div class="hero-left">
|
||||
<div id="cur-icon" class="hero-icon"></div>
|
||||
<div id="cur-desc" class="hero-desc"></div>
|
||||
@@ -77,6 +77,7 @@
|
||||
<div class="hero-center">
|
||||
<div class="hero-temp"><span id="cur-temp">--</span><span class="deg">°F</span></div>
|
||||
<div class="feels" id="feels-line">Feels like <span id="cur-feels">--</span>°F</div>
|
||||
<div class="hero-context hidden" id="hero-context"></div>
|
||||
<button id="share-hero-btn" class="hero-share-btn" type="button">Share hero card</button>
|
||||
<p id="share-hero-status" class="hero-share-status hidden"></p>
|
||||
</div>
|
||||
@@ -97,107 +98,40 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── SUN & MOON TIMELINE ── -->
|
||||
<div class="sun-section">
|
||||
<div class="sun-timeline-wrap">
|
||||
<div class="sun-endpoint">
|
||||
<span class="sun-ep-icon">🌅</span>
|
||||
<span id="sunrise-val" class="sun-ep-time">--</span>
|
||||
</div>
|
||||
<div class="sun-track-wrap">
|
||||
<div class="sun-track">
|
||||
<div class="sun-progress" id="sun-progress"></div>
|
||||
<div class="sun-dot" id="sun-dot">☀️</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sun-endpoint">
|
||||
<span class="sun-ep-icon">🌇</span>
|
||||
<span id="sunset-val" class="sun-ep-time">--</span>
|
||||
</div>
|
||||
<!-- ── ONE-LINE SUMMARY ── -->
|
||||
<div class="summary-line" id="summary-line"></div>
|
||||
|
||||
<!-- ── NEXT 2 HOURS + WHAT TO BRING ── -->
|
||||
<section class="ui-card nowcast" id="nowcast">
|
||||
<div class="section-head">
|
||||
<span class="section-label">Next 2 hours</span>
|
||||
<span class="section-note" id="nowcast-note"></span>
|
||||
</div>
|
||||
<div class="moon-row">
|
||||
<span class="moon-emoji">🌙</span>
|
||||
<span id="moon-phase-val">--</span>
|
||||
<span class="daylight-info" id="daylight-info">--</span>
|
||||
<div class="nowcast-bars" id="nowcast-bars"></div>
|
||||
<div class="bring-row">
|
||||
<span class="bring-label">Bring</span>
|
||||
<div id="recommendations" class="recs-grid"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── HOURLY ── -->
|
||||
<div class="section-head sticky-head">
|
||||
<span class="section-label">Hourly Forecast</span>
|
||||
<span class="section-note">
|
||||
<button id="hourly-feels-toggle" class="link-btn">Feels-like</button>
|
||||
<button id="hourly-extend-btn" class="link-btn">48h</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="ui-card hourly-card">
|
||||
<div class="hc-readout" id="hc-readout"></div>
|
||||
<div id="hourly-chart" class="hourly-chart" aria-label="Hourly temperature, rain chance and wind chart"></div>
|
||||
</div>
|
||||
<div id="hourly-scroll" class="hourly-scroll">
|
||||
<div id="hourly-track" class="hourly-track"></div>
|
||||
</div>
|
||||
|
||||
<!-- ── WIND & ATMOSPHERE (collapsed by default on mobile) ── -->
|
||||
<details class="details-drawer wind-drawer" id="wind-drawer">
|
||||
<summary class="drawer-summary">
|
||||
Wind & Atmosphere
|
||||
<span class="wind-drawer-peek" id="wind-drawer-peek"></span>
|
||||
<span class="drawer-chevron">›</span>
|
||||
</summary>
|
||||
<div class="drawer-body">
|
||||
<div class="card-group drawer-card-group">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Wind</div>
|
||||
<div class="stat-val"><span id="cur-wind">--</span> <span class="stat-unit wind-unit">mph</span></div>
|
||||
<div class="stat-sub" id="cur-wind-dir">--</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Gusts</div>
|
||||
<div class="stat-val"><span id="cur-gust">--</span> <span class="stat-unit gust-unit">mph</span></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Humidity</div>
|
||||
<div class="stat-val"><span id="cur-hum">--</span><span class="stat-unit">%</span></div>
|
||||
<div class="stat-sub" id="hum-feel"></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Dewpoint</div>
|
||||
<div class="stat-val"><span id="cur-dew">--</span>°</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Pressure</div>
|
||||
<div class="stat-val"><span id="cur-pres">--</span> <span class="stat-unit">hPa</span></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Visibility</div>
|
||||
<div class="stat-val"><span id="cur-vis">--</span> <span class="stat-unit vis-unit">mi</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<!-- ── MORE DETAILS DRAWER ── -->
|
||||
<details class="details-drawer">
|
||||
<summary class="drawer-summary">More Details <span class="drawer-chevron">›</span></summary>
|
||||
<div class="drawer-body">
|
||||
<div class="card-group drawer-card-group">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">UV Index</div>
|
||||
<div class="stat-val"><span id="cur-uv">--</span></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Cloud Cover</div>
|
||||
<div class="stat-val"><span id="cur-cloud">--</span><span class="stat-unit">%</span></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">US AQI</div>
|
||||
<div class="stat-val"><span id="aqi-us">--</span></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">PM2.5</div>
|
||||
<div class="stat-val"><span id="pm25">--</span></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Pollen</div>
|
||||
<div class="stat-val"><span id="pollen">--</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<!-- ── WHAT TO BRING ── -->
|
||||
<div class="section-head" style="margin-top:1.5rem">
|
||||
<span class="section-label">What to Bring</span>
|
||||
</div>
|
||||
<div id="recommendations" class="recs-grid"></div>
|
||||
|
||||
<!-- Embedded radar panel -->
|
||||
<div class="section-head">
|
||||
<!-- ── RADAR ── -->
|
||||
<div class="section-head sticky-head">
|
||||
<span class="section-label">Radar</span>
|
||||
<span class="section-note">
|
||||
<button class="link-btn" id="open-map-tab">Open map →</button>
|
||||
@@ -214,26 +148,71 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hourly -->
|
||||
<div class="section-head" style="margin-top:1.5rem">
|
||||
<span class="section-label">Hourly Forecast</span>
|
||||
<span class="section-note">
|
||||
<button id="hourly-feels-toggle" class="link-btn">Feels-like</button>
|
||||
<button id="hourly-extend-btn" class="link-btn">48h</button>
|
||||
</span>
|
||||
</div>
|
||||
<div id="hourly-scroll" class="hourly-scroll">
|
||||
<div id="hourly-track" class="hourly-track"></div>
|
||||
</div>
|
||||
<div id="precip-chart-wrap" class="precip-chart-wrap"></div>
|
||||
|
||||
<!-- 7-day -->
|
||||
<div class="section-head">
|
||||
<!-- ── 7-DAY ── -->
|
||||
<div class="section-head sticky-head">
|
||||
<span id="daily-forecast-label" class="section-label">7-Day Forecast</span>
|
||||
<button id="daily-toggle-btn" class="link-btn" type="button">Show 16-day</button>
|
||||
</div>
|
||||
<div id="daily-list" class="daily-list"></div>
|
||||
|
||||
<!-- ── DETAILS TILES ── -->
|
||||
<div class="section-head sticky-head">
|
||||
<span class="section-label">Details</span>
|
||||
<span class="section-note" id="wind-drawer-peek"></span>
|
||||
</div>
|
||||
<div class="detail-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Wind</div>
|
||||
<div class="stat-val"><span id="cur-wind">--</span> <span class="stat-unit wind-unit">mph</span></div>
|
||||
<div class="stat-sub" id="cur-wind-dir">--</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Gusts</div>
|
||||
<div class="stat-val"><span id="cur-gust">--</span> <span class="stat-unit gust-unit">mph</span></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Humidity</div>
|
||||
<div class="stat-val"><span id="cur-hum">--</span><span class="stat-unit">%</span></div>
|
||||
<div class="stat-sub" id="hum-feel"></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Dewpoint</div>
|
||||
<div class="stat-val"><span id="cur-dew">--</span>°</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Pressure</div>
|
||||
<div class="stat-val"><span id="cur-pres">--</span> <span class="stat-unit">hPa</span></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Visibility</div>
|
||||
<div class="stat-val"><span id="cur-vis">--</span> <span class="stat-unit vis-unit">mi</span></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">UV Index</div>
|
||||
<div class="stat-val"><span id="cur-uv">--</span></div>
|
||||
<div class="stat-sub" id="uv-cat"></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Cloud Cover</div>
|
||||
<div class="stat-val"><span id="cur-cloud">--</span><span class="stat-unit">%</span></div>
|
||||
</div>
|
||||
<div class="stat-card aqi-card">
|
||||
<div class="stat-label">Air Quality (US AQI)</div>
|
||||
<div class="stat-val"><span id="aqi-us">--</span> <span class="aqi-cat" id="aqi-cat"></span></div>
|
||||
<div class="aqi-track"><span class="aqi-marker" id="aqi-marker"></span></div>
|
||||
<div class="stat-sub">PM2.5 <span id="pm25">--</span> · Pollen <span id="pollen">--</span></div>
|
||||
</div>
|
||||
<div class="stat-card sun-tile">
|
||||
<div class="stat-label">Sun & Moon</div>
|
||||
<div class="sun-timeline-wrap">
|
||||
<div class="sun-endpoint"><span class="sun-ep-icon">🌅</span><span id="sunrise-val" class="sun-ep-time">--</span></div>
|
||||
<div class="sun-track-wrap"><div class="sun-track"><div class="sun-progress" id="sun-progress"></div><div class="sun-dot" id="sun-dot">☀️</div></div></div>
|
||||
<div class="sun-endpoint"><span class="sun-ep-icon">🌇</span><span id="sunset-val" class="sun-ep-time">--</span></div>
|
||||
</div>
|
||||
<div class="moon-row"><span class="moon-emoji">🌙</span><span id="moon-phase-val">--</span><span class="daylight-info" id="daylight-info">--</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<details class="details-drawer discussion-drawer" id="discussion-drawer">
|
||||
<summary class="drawer-summary">
|
||||
Forecaster's Discussion
|
||||
@@ -1296,19 +1275,12 @@
|
||||
<span class="bottom-label">Alerts</span>
|
||||
<span class="alert-badge hidden" id="alert-badge-bottom"></span>
|
||||
</button>
|
||||
<button class="bottom-tab" data-tab="learn" type="button">
|
||||
<span class="bottom-icon">📘</span>
|
||||
<span class="bottom-label">Learn</span>
|
||||
</button>
|
||||
<button class="bottom-tab" data-tab="settings" type="button">
|
||||
<span class="bottom-icon">⚙️</span>
|
||||
<span class="bottom-label">Settings</span>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
|
||||
<script src="app.js"></script>
|
||||
<script src="station-live.js"></script>
|
||||
<script src="app-ui.js"></script>
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/sw.js');
|
||||
|
||||
Reference in new issue
Block a user