Skip to content

Implement updates tracking OWID grapher#6

Open
xrendan wants to merge 1566 commits into
BuildCanada:masterfrom
owid:master
Open

Implement updates tracking OWID grapher#6
xrendan wants to merge 1566 commits into
BuildCanada:masterfrom
owid:master

Conversation

@xrendan

@xrendan xrendan commented Feb 26, 2026

Copy link
Copy Markdown
Member

Context

Links to issues, Figma, Slack, and a technical introduction to the work.

Screenshots / Videos / Diagrams

Add if relevant, i.e. might not be necessary when there are no UI changes.

Testing guidance

Step-by-step instructions on how to test this change

  • Does the change work in the archive?
  • Does the staging experience have sign-off from product stakeholders?

Reminder to annotate the PR diff with design notes, alternatives you considered, and any other helpful context.

Checklist

(delete all that do not apply)

Before merging

  • Google Analytics events were adapted to fit the changes in this PR
  • Changes to CSS/HTML were checked on Desktop and Mobile Safari at all three breakpoints
  • Changes to HTML were checked for accessibility concerns

If DB migrations exists:

  • If columns have been added/deleted, all necessary views were recreated
  • The DB type definitions have been updated
  • The DB types in the ETL have been updated
  • If tables/views were added/removed, the Datasette export has been updated to take this into account
  • Update the documentation in db/docs

After merging

  • If a table was touched that is synced to R2, the sync script to update R2 has been run

[Cycle issue](#6169) / [Designs](https://www.figma.com/design/dCB69o19cAVtuk283STAcY/Dumbbell-Plots?node-id=1-31&m=dev)

Implements the chart legend for dumbbell plots.

### Description

If possible, an in-chart legend is plotted above the chart where the two legend labels are aligned with the top-most dots.

- If series strategy = entity (one indicator, time range): show in-chart legend if possible, hide legend otherwise (two dates not fitting next to each other is rare, and the arrow design makes the start/end dots relatively clear)
- If series strategy = column (two indicators, time point); show in-chart legend if possible, horizontal categorical legend otherwise

There's a new component `HorizontalLabelPair` for plotting the in-chart legend. It currently only works for exactly two labels because that's what I needed here.

### Follow-up work

* ~Dumbbell elements~
* ~New dumbbell-specific options: value labels, end points~
* ~In-chart legend, aligned with the top-most dots~
* Color (hard-coded for now)
* Interaction (focus, hover, tooltips)
* More entity sorting options
* Dumbbell plots in search
* Dumbbell chart thumbnails
[Cycle issue](#6169) / [Designs](https://www.figma.com/design/dCB69o19cAVtuk283STAcY/Dumbbell-Plots?node-id=1-31&m=dev)

Implements hover, focus and tooltips for dumbbell plots.

### Description

* Focus mode is only available to authors, i.e. via the admin or by editing the URL params directly
    * Hovering and updating the selection clears focus (this is how it works for other chart types as well)
* The hovered dumbbell is highlighted by muting all other dumbbells
    * I wasn’t sure whether it’s better to use the entire row, including the label and whitespace on the left and right, as the hover hit area, or only the actual dumbbell. I opted for the former because it makes hovering a bit easier I think
* The two modes, entity and column series strategy, have different tooltips:
    * If series strategy = entity, the tooltip is similar to the slope tooltip (start value -> end value)
    * If series strategy = column, the tooltip is similar to the scatter tooltip (start and end value on separate rows)
        * The change value is also shown if it’s used to label the dumbbell

### Follow-up work

* ~Dumbbell elements~
* ~New dumbbell-specific options: value labels, end points~
* ~In-chart legend, aligned with the top-most dots~
* ~Interaction (focus, hover, tooltips)~
* Color (hard-coded for now)
* More entity sorting options
* Dumbbell plots in search
* Dumbbell chart thumbnails
Small refactor of the props passed to tooltip components
Adds support for dumbbell charts in search.

This includes:
- Constructing the data table rendered in search
- Making sure the big data value on the right is appropriate
    - Should say `Start value -> End value` in time-range mode (same as slope charts)
    - Otherwise, it should be hidden (we never show a value for multi-y charts)

The thumbnail PNGs (with imMinimal=0/1) look good as is, I think.

This is a bit difficult to test. I mainly looked at the various endpoints (`.search-result.json`, `values.json`) and added tests.

This PR also includes a refactor that drops the dumbbell's series strategy and replaces it with a custom `mode`. If the series strategy is set to `column`, search expects the series items to refer to columns, not entities. But dumbbell charts always plot entities, so the appropriate series strategy is `entity`, and we should differentiate between time-range and two-column mode separately.

### Follow-up work

* ~Dumbbell elements~
* ~New dumbbell-specific options: value labels, end points~
* ~In-chart legend, aligned with the top-most dots~
* ~Interaction (focus, hover, tooltips)~
* Color (hard-coded for now)
* More entity sorting options
* ~Dumbbell plots in search~ (addressed in this PR)
* ~Dumbbell chart thumbnails~ (addressed in this PR)
Adds three more sorting options for dumbbell plots: by start and end value, and by change.

Also refactors the sorting code a bit: Chart types now expose `availableSortKeys`, which is then used in the admin to construct dropdown options, and to narrow the type for the object specifying the sorting options.

Marimekkos are excluded from the refactor because their sorting is intermingled with other code, and sooner or later we'll rewrite the Marimekko chart component anyway.

### Follow-up work

* ~Dumbbell elements~
* ~New dumbbell-specific options: value labels, end points~
* ~In-chart legend, aligned with the top-most dots~
* ~Interaction (focus, hover, tooltips)~
* Color (hard-coded for now)
* ~More entity sorting options~
* ~Dumbbell plots in search~
* ~Dumbbell chart thumbnails~
Allows color customisation for dumbbell charts.

* For two-column mode: Authors can assign an indicator colour via the admin
* For time-range mode: Authors can assign colours in the dumbbell section via the admin. These are mapped to the new `dumbbell.trendColorMap` config field.
    * Instead of introducing a dumbbell-specific colour mapping, we could also re-use the top-level colorMap config field. But the `colorMap` is shared between all chart types, so if the dumbbell chart is shown next to a line chart, the line chart colour scheme would also apply to the dumbbell chart, which isn’t ideal
    * Instead of introducing a new config field type, we could also re-use the existing colorMap type inside the dumbbell namespace. This feels like overkill though, and it’s also not a great fit because the internal ColorScale needs a color column, which doesn’t exist for dumbbells since there’s no column encoding increase/decrease/noChange. Of course, we could create one on the fly, but that seemed unnecessarily complex
    * I also considered simply not allowing customisation, but at the very least, we’d need an “invert colors” config because mapping increase to green and decrease to red doesn’t work when “decrease is good”. So if we have to add one piece of config anyway, we might as well allow customisation
    * I also considered not allowing customisation and simply choosing neutral colours for increase/decrease, but Marwa wasn’t a fan
ikesau and others added 30 commits July 1, 2026 09:38
✨🤖 (food-trade) reword trade reporting note to use 'prioritize'
deleteAlgoliaIndex only removed PAGES_INDEX + CHARTS_INDEX, so every torn-down
staging left its <prefix>-pages-chronological index orphaned. These accumulated
(one per algolia staging ever built) and contributed to exhausting the Algolia
record quota. Add PAGES_CHRONOLOGICAL_INDEX to the deletion set so teardown
removes all three indices a staging builds.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* Improve scroll to selected topic in /latest

Move the scroll to selected topic to a callback ref. This now works both
for on load and on selection change.

* Simplify latest topic pill scrolling

We can use the element from the focus event as a scroll target. Also
switch from "nearest" to "center", since otherwise the whole pill might
not be visible.
Add click-to-select behaviour to Sankey nodes, adapted from #6613
Adds a population share tooltip for the migration bespoke viz, adapted from #6613
The "download displayed data" button on the data table tab exported the
full timeline instead of the currently selected time range, unlike the
chart/map tabs which already filter via transformedTable.

Filter tableForDisplay by [startTime, endTime] in filteredTableForDownload
when on the table tab. This fixes both the client-side and server-side
download paths, since both read the same getter.

Fixes #6602

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* 🐝 🤖 Clean up tsconfig base options

Switch `module` from `commonjs` to `preserve` so it matches our
`bundler` module resolution and the ESM reality of our toolchain — the
emitted JS is never run (tsx and Vite consume the TS source directly),
so the previous CommonJS setting was both inert and inconsistent.

Drop options that are redundant with the inherited `@tsconfig/node24`
base or with current TS defaults:
- `sourceMap` — emitted .js.map files are never used; nothing runs or
  debugs the tsc output.
- `alwaysStrict` — implied by the base's `strict: true`.
- `forceConsistentCasingInFileNames`, `allowJs` — already the defaults.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Remove explorerJobsWorker examples using bare Node

We only deploy it using tsx and supporting Node is not necessary.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Fix styling: it rendered unstyled at the bottom of the page because
  the SCSS is scoped to .GrapherComponent. Since we use it only on
  standalone Grapher pages, it can render inside Grapher instead.
- Convert it to a plain function component.
- Replace imperative toggle with React state.
- Ensure all commands run in a MobX action
🐛 Restrict table-tab data download to the selected time range
Signed-off-by: dependabot[bot] <support@github.com>
Rename the whole-slideshow delete button/confirm to say
'Delete slideshow' and the single-slide delete action to say
'Delete slide' (with a tooltip/aria-label since it's icon-only),
so the two destructive actions are unambiguous at the point of
the click. Also strengthen the slideshow delete confirmation copy
to make clear the whole deck is being permanently deleted.
Makes the destructive whole-slideshow delete action visually more
distinct from the lightweight single-slide delete confirmation, in
both the editor footer and the slideshows index page.
Authenticate staging admin via Tailscale Serve headers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.