Skip to content

Commit 32f8fea

Browse files
ringsaturnclaude
andcommitted
web: split the rail into fields, overlays and marks with one view state
The layer rail is three sections, one kind of press each. The field section is a radio: each dataset's core tiles (FORECAST_MODELS[].railCore; temperature, precipitation, wind and cloud on a forecast model, the solar radiation in cloud's place on SFLUX, the reflectivity on a radar mosaic), the tile of the field on screen when it is not a core one, and MORE, which opens a sheet listing every field the run publishes, grouped by quantity, with a chip per surface and variant under a family. The overlay section is switches drawn over the field: the pressure lines (the PRESSURE tile now toggles them rather than replacing the field), the particles (moved out of the capsule), the experiment's derived layers. The mark section is the storm sheet trigger and the two station switches. Switch tiles carry a ring, sheet triggers a chevron; an empty section hides with its rule; the dense variant is decided by the visible tile count against the rail's box. The level row's lines group gains ALONE, the way to the lines-alone view and back to the field last on screen. What is on screen is one object, ViewState (viewstate.ts), whose parseView and searchForView are inverses of each other over every parameter the shell reads; main.ts holds it as `view` and derives the rail's pressed states (syncRail) and the address bar (syncUrl) from it, replacing the composition, particle, derived-layer, storm and station variables. FamilyInfo.members splits into levels (the same quantity on other surfaces: the isobaric set, the cloud layers) and variants (related quantities behind one tile: sea ice cover and thickness, wave height and period). The level row draws levels only, under a fixed LEVEL caption; a family tile's gloss follows the member on screen; pressing a pressed variants family cycles through them. The web fixture gains a gust bundle, a field outside the core tiles, so the e2e suite can drive MORE. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016peFTwXxKVuwLqZYYDqr2W
1 parent a20c774 commit 32f8fea

25 files changed

Lines changed: 1821 additions & 493 deletions

CLAUDE.md

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -710,16 +710,45 @@ to RG8 (u codes in red, v in green, the packing `particles.ts` builds, which
710710
`main.ts` interleaves once per frame and memoizes) and looks the palette up
711711
by `magnitude / maxMagnitude`; every vector bundle takes this path with its
712712
own ceiling from `levels.ts::vectorMaxMagnitude`. `web/src/levels.ts` is the
713-
family registry: one rail tile per family, the level row on the capsule
714-
picks the member, and cloud cover lists its members outright in
715-
`FamilyInfo.members`. Past ten visible rail tiles `main.ts` marks the rail
716-
dense and the stylesheet drops the tiles to 36px. The rail is a scroll
717-
column in a fixed box (under the zoom tile down to the capsule on desktop;
718-
under the round controls on phones, where `main.ts` publishes the capsule's
719-
measured height as `--capsule-height`), and its tiles are grouped by
720-
quantity in `index.html`, so a new tile goes into its group. Over a field
721-
the lines group is on the row whenever the run publishes a pressure surface:
722-
a pressed member is the overlay, pressing it again takes the lines off.
713+
family registry: one rail tile per family, and a family's members are
714+
two kinds. `FamilyInfo.levels` are the same quantity on other surfaces
715+
(the isobaric set, or the cloud layers listed outright): the level row on
716+
the capsule picks among them. `FamilyInfo.variants` are related but
717+
different quantities behind one tile (sea ice cover and thickness, wave
718+
height and period), never on the level row: the field sheet lists them as
719+
chips under the family's row, and pressing the pressed tile again cycles
720+
through them. A family tile's gloss follows the member on screen
721+
(`syncFamilyGloss`: TEMP 2M, TEMP 850, ICE THICK).
722+
723+
The layer rail is three sections, one kind of press each (`index.html`,
724+
`.rail-section`): the fields (a radio: the dataset's core tiles,
725+
`FORECAST_MODELS[].railCore`, the tile of the field on screen when it is
726+
not a core one, and MORE, which opens `#field-sheet`, every field the run
727+
publishes grouped by quantity, written by `main.ts::renderFieldSheet` from
728+
the rail's own tiles and a stopgap group table), the overlays (switches
729+
drawn over the field and following the playhead: the pressure lines, the
730+
particles, the experiment's derived layers) and the marks (the storm sheet
731+
trigger, the soundings and the airports). A switch tile carries
732+
`data-toggle` and a ring in its corner, a sheet trigger `data-dialog` and a
733+
chevron. `syncFieldTiles` hides every field tile the run does not ship or
734+
the screen does not show, and writes a generic tile for a field this build
735+
has no tile for while it is on screen; the rail is marked dense
736+
(`syncRailDensity`, tiles at 36px) when its visible tiles would not fit its
737+
box at full size. The rail is a scroll column in a fixed box (under the
738+
zoom tile down to the capsule on desktop; under the round controls on
739+
phones, where `main.ts` publishes the capsule's measured height as
740+
`--capsule-height`). A new field with an icon is a tile in the field
741+
section plus a line in `FIELD_GROUP_TILES`; without one it is a row of the
742+
sheet's last group. What is on screen is one object, `view: ViewState`
743+
(`web/src/viewstate.ts`: the field and the lines, the particles, the
744+
experiment's derived layers, the storm and station marks); the rail's
745+
pressed states (`syncRail`), the level row and the address bar
746+
(`syncUrl` over `searchForView`, the inverse of `parseView`) are
747+
projections of it, and nothing else holds a copy. The lines group is on the level row whenever the run
748+
publishes a pressure surface: a pressed member is the overlay, pressing it
749+
again takes the lines off, as does the rail's pressure switch, and the
750+
group's ALONE member drops the field to leave the chart by itself (the
751+
field last on screen, `lastField`, comes back on the next press).
723752

724753
The pressure family is drawn as contour lines: `web/src/pressure.ts` holds
725754
the per-level intervals and emphasised lines, `layer.ts::setContours` turns
@@ -740,10 +769,11 @@ once a second; a stop, a step or a pan refreshes at once.
740769
emphasised lines identical across the three implementations.
741770

742771
`particles.ts` advects GPU particles through the wind field as an overlay in
743-
one ink, on by default, off from the capsule (`?particles=off`, remembered
744-
in `localStorage`, off by default under `prefers-reduced-motion`). Wind
745-
narrows to the viewport while the overlay is off; with it on the session
746-
takes the whole plane, since the particles respawn across the grid.
772+
one ink, on by default, off from the rail's overlay section
773+
(`?particles=off`, remembered in `localStorage`, off by default under
774+
`prefers-reduced-motion`). Wind narrows to the viewport while the overlay
775+
is off; with it on the session takes the whole plane, since the particles
776+
respawn across the grid.
747777
`playback.ts` holds the frame-rate ladder and the per-frame dwell that keeps
748778
a mixed-step axis at one apparent speed.
749779

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,13 @@ such as `tmp2m` / `prate` / `wind10m` / `solar` / `radar`, and each isobaric
283283
field names itself (`pressure`, `hgt500`, `tmp850` / `t850`, `rh700`,
284284
`wind850`, `qflux850` / `vapor850`; there is no separate `level`
285285
parameter). Both are case-insensitive, the address bar stays in sync, and
286-
unrecognized values fall back to defaults. In the page one rail tile stands
287-
for a whole family and the level row on the transport capsule picks the
288-
surface.
286+
unrecognized values fall back to defaults. In the page the rail carries a
287+
tile for each core field (temperature, precipitation, wind, cloud on a
288+
forecast model) and a MORE tile opening the list of every field the run
289+
publishes; one tile stands for a whole family and the level row on the
290+
transport capsule picks the surface. The pressure lines are a switch in the
291+
rail's overlay section, and the level row's ALONE member leaves them by
292+
themselves.
289293

290294
The view is in the fragment, `#map=<zoom>/<lat>/<lon>` (MapLibre's own
291295
spelling), kept current on every pan and zoom. A link without one opens on

0 commit comments

Comments
 (0)