Skip to content

Make the graph page read correctly - #149

Merged
WaylandYang merged 33 commits into
mainfrom
ui/derived-switch-and-fade
Aug 31, 2026
Merged

Make the graph page read correctly#149
WaylandYang merged 33 commits into
mainfrom
ui/derived-switch-and-fade

Conversation

@WaylandYang

@WaylandYang WaylandYang commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Thirty-odd rounds of looking at the graph page and fixing what did not read.
Frontend only, except two small backend additions noted below.

Derived edges

  • The toggle moved out of the class legend into the bottom-left tower. It looked
    like a tenth class there, and the fix could not be colour: this file's own rule
    is chrome carries no hue, colour belongs to data. So it moved instead.
  • Derived edges fade in after the asserted ones, on load and on toggle.
    Order is the content: what people wrote lands first, what the engine worked out
    arrives second.
  • Two richer attempts were tried and dropped — see "What we tried and rejected".
  • The selected/hovered state keeps a derived edge gold instead of turning it
    white. Selection is when you look closest; that is the worst moment to erase
    where an edge came from.
  • Inference panel: opens in place from its button (the shared FLIP popover, same
    as notifications and the user menu), and "Run now" asks first — on a second
    button, because two clicks on one control already means "close" here.

Class legend

  • Capped at 6 pills, ordered by how many nodes each class actually has. The rest
    collapse into "All N classes", which opens a searchable list of every class
    with per-class counts.
  • Each row has "Only"; a "Show all (N hidden)" chip appears whenever anything is
    hidden, so filtering is never silent.

Timeline

  • A step unit (year / month / day) that drives both playback and the histogram
    buckets. Before this the bars were years while playback stepped by days, and
    nothing on screen said how long one step was.
  • Playback advances continuously instead of jumping bucket to bucket; scrubbing
    seeks instead of stopping; bars ahead of the playhead are no longer lit; the
    track glows once when a run finishes.
  • Bar width scales with the unit — fat blocks for years, hairlines for days.

Routing

  • The knowledge base is now a path segment: /kb/$kbId/... for graph, search,
    chat, library, ontology, mappings, review and settings. Old paths still work
    and redirect. A link that omits the base used to silently show the reader
    their base — same screen, different data.
  • The graph page writes entity, focus and at into the URL, so a link
    reproduces what you are looking at, including the moment in time.
  • A no-access / missing base lands on a real page instead of an empty graph.

Correctness

  • Timezone. World time (valid_from/valid_to) is a calendar date from a
    document and renders in UTC everywhere; belief time (recorded_at) is a real
    instant and renders in the reader's zone. Entity history was doing the former
    to the latter, shifting revisions by a day for anyone east of UTC. The two
    functions now sit side by side with comments saying they are deliberately
    different.
  • Popover surfaces had a blue cast (rgba(14,14,16)), which reached the
    notification card, the user menu and both new panels. Now neutral.
  • Panels grow more opaque on pointer-enter and while playback runs — glass is
    for when you are not reading it.
  • Facts count in the top-right now reads "N of M" like the entity count did;
    the two idioms in one sentence made it look broken when the budget changed.
  • An entity count control (150 / 300 / 600 / 1000) next to those stats, with a
    limit parameter on the overview endpoint (clamped server-side).

Bugs fixed along the way

  • Finishing playback twice reloaded the page: an onAnimationEnd handler was
    calling .remove() on a React-owned node, so the next keyed render threw
    NotFoundError and unmounted the tree.
  • Hovering brightened edges and nodes that do not exist at the current instant —
    the hover branches returned before the time filter.
  • Turning derived off with a node selected flashed unrelated edges: the fade-out
    started from full gold instead of from the colour they already had.
  • A dense histogram rendered empty: a fixed 2px gap consumed the whole track at
    214 bars.
  • A transition shorthand on .glass-strong silently dropped the island's width
    transition, because unlayered CSS beats a Tailwind utility.

What we tried and rejected

  • Animating the derivation (premises lighting in order, then the conclusion).
    Two versions, neither readable: with hundreds of edges on screen you cannot
    tell which premises belong to which conclusion. The entity sidebar's Derived
    tab already says it one row at a time. The backend field added for it was
    reverted rather than left unread.
  • Scaling the ForceAtlas2 constants with graph size. It spread better and
    felt limp; the deliberately strong values are back.
  • A Morandi palette — rejected earlier, noted here because the comment
    explaining why now sits in palette.rs.

Backend

Two additions only: limit on graph/overview, and nothing else that ships —
the derived-premise field was added and then reverted with the animation.

Notes

Verified against the demo base (548 entities / 912 facts / 28 derived edges).
Animation timing could not be observed in the preview environment, which does
not advance CSS transitions or requestAnimationFrame; end states and layout
were measured instead, and that limitation is called out where it matters.

🤖 Generated with Claude Code

WaylandYang and others added 30 commits August 31, 2026 21:42
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
WaylandYang and others added 3 commits September 1, 2026 02:52
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…-fade

# Conflicts:
#	web/src/pages/Review.tsx
@WaylandYang WaylandYang changed the title The derived toggle should not look like a tenth class Make the graph page read correctly Aug 31, 2026
@WaylandYang
WaylandYang merged commit ab25806 into main Aug 31, 2026
3 checks passed
@WaylandYang
WaylandYang deleted the ui/derived-switch-and-fade branch August 31, 2026 19:53
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.

1 participant