Context
<protvista-uniprot> is a light-DOM Web Component consumed by React hosts, most prominently uniprot-website. The current React integration pattern — disable the built-in tooltip popover via notooltip, listen for change events on the element, read detail.feature.tooltipContent + detail.coords, render a React-controlled overlay positioned at those coordinates — works cleanly and has been in production use. But it is nowhere documented in this repo. A new React adopter today has to reverse-engineer the pattern from consumer code (uniprot-website's FeatureViewer.tsx), which is both friction and a correctness hazard (the event shape, attribute name, and dismissal vocabulary are all load-bearing and aren't discoverable from the viewer's types or README).
This gap became visible during a uniprot-website migration discussion on the config-approach branch. The consumer already uses the event-listening pattern and asked how they are "supposed to" integrate with the new config-approach tooltip pipeline. The answer is simple — add notooltip, keep everything else — but that answer doesn't exist as canonical documentation yet.
Task
Add a "React integration" section to specs/config-approach.md (or a standalone page under docs/) that codifies the event-listening pattern as the canonical path for React hosts, and cross-link it from the README's API section and from the tooltips property's JSDoc on <protvista-uniprot>.
Scope:
- New section in
specs/config-approach.md titled something like "React host integration" (placement: after the "Intent" section, before "Security and trust model"). Contents:
- A preamble making the library-vs-consumer split explicit: declarative tooltips (
kind: fields / kind: markdown in YAML, rendered by the library's built-in Floating-UI popover) OR consumer-owned rich tooltips (event listener + host-rendered overlay, with notooltip set on the element). There is no in-between — the library does not ship a programmatic per-kind override registry.
- The
notooltip attribute — what it does, when to set it, why a React host always wants it. Note that notooltip does not suppress feature.tooltipContent resolution; it only disables the built-in popover's DOM mount, so a consumer can still read detail.feature.tooltipContent off the event if it wants the pre-rendered declarative string.
- The event-listening pattern:
- Attach a listener for the
change event on the <protvista-uniprot> element.
- Inspect
detail.eventType — click opens a tooltip, mouseover/mouseout/reset drive your own hover and dismissal logic.
- Read
detail.feature (the full adapter-output item, including any tooltipContent the library pre-computed) and detail.coords (an [x, y] tuple in page coordinates).
- Render your React overlay into a portal or Floating-UI-positioned div at
[x, y]. Host owns the JSX, the lifecycle, and the styling.
- Hide the overlay on
undefined / reset / subsequent click events (the dismissal set that uniprot-website uses).
- A worked minimal React example (no dependencies beyond React itself + Floating UI, roughly 30 lines). The uniprot-website
FeatureViewer.tsx is the real reference but has a lot of ambient app concerns; a stripped-down example is more digestible for a new adopter.
- README cross-link: the existing API-section entry for
notooltip gains a "See React host integration for the consumer-side pattern." pointer.
- JSDoc update on the
notooltip property in src/protvista-uniprot.ts: a one-line link to the new spec section, so IDE tooltip-on-hover points the right way.
docs/react-integration.md: optional second home for the same content, closer to docs/data-tooltip.md. Decide between "single source in the spec" vs. "tutorial-flavoured copy in docs/ and normative contract in the spec" when drafting.
Notes:
Three things to pin down while writing the section, all surfaced during the original discussion:
-
detail.eventType value vocabulary. Current values: 'click', 'mouseover', 'mouseout', 'reset'. Document every one, including what reset means (Nightingale emits it when the user scrolls / zooms, effectively "stop showing any per-feature tooltip"). The set is load-bearing — uniprot-website's hideTooltipEvents = new Set([undefined, 'reset', 'click']) assumes all three dismissal triggers.
-
detail.coords coordinate space. Document that these are page-coordinates (clientX / clientY-style) so the consumer knows whether they need to transform to container-local coordinates. Worth sanity-checking against the Nightingale source before committing a statement either way.
-
React 19 forward-looking note. The uniprot-website code has a TODO referencing ref-callback-with-cleanup — a React 19 feature that replaces the separate mount/unmount useEffect pair. Worth mentioning in the doc as the preferred pattern once React 19 is available, so new adopters don't copy the older split-useEffect shape as the canonical form.
No code changes in this issue — pure documentation. The existing event-listening integration path works today on the config-approach branch; the gap is that nobody would know from the docs alone that this is the intended path. Estimated effort: half a day to draft, half a day to shake down with a real uniprot-website migration trial run.
Cross-links with existing next-branch issues:
- Issue "Tame Nightingale's click-highlight fill swap on collapsed group aggregate tracks" — if that one lands as option 1 (drop
highlight-event="onclick" from the aggregate), the React integration doc should mention that a click on the collapsed aggregate opens a tooltip without a highlight state change, distinct from a click on the expanded detail track.
- Issue "Add a generic
linegraph semantic kind for bring-your-own-data authors" — BYOD consumers who pair generic kinds with a React host are the second audience for this doc; worth cross-referencing.
Context
<protvista-uniprot>is a light-DOM Web Component consumed by React hosts, most prominently uniprot-website. The current React integration pattern — disable the built-in tooltip popover vianotooltip, listen forchangeevents on the element, readdetail.feature.tooltipContent+detail.coords, render a React-controlled overlay positioned at those coordinates — works cleanly and has been in production use. But it is nowhere documented in this repo. A new React adopter today has to reverse-engineer the pattern from consumer code (uniprot-website'sFeatureViewer.tsx), which is both friction and a correctness hazard (the event shape, attribute name, and dismissal vocabulary are all load-bearing and aren't discoverable from the viewer's types or README).This gap became visible during a uniprot-website migration discussion on the config-approach branch. The consumer already uses the event-listening pattern and asked how they are "supposed to" integrate with the new config-approach tooltip pipeline. The answer is simple — add
notooltip, keep everything else — but that answer doesn't exist as canonical documentation yet.Task
Add a "React integration" section to
specs/config-approach.md(or a standalone page underdocs/) that codifies the event-listening pattern as the canonical path for React hosts, and cross-link it from the README's API section and from thetooltipsproperty's JSDoc on<protvista-uniprot>.Scope:
specs/config-approach.mdtitled something like "React host integration" (placement: after the "Intent" section, before "Security and trust model"). Contents:kind: fields/kind: markdownin YAML, rendered by the library's built-in Floating-UI popover) OR consumer-owned rich tooltips (event listener + host-rendered overlay, withnotooltipset on the element). There is no in-between — the library does not ship a programmatic per-kind override registry.notooltipattribute — what it does, when to set it, why a React host always wants it. Note thatnotooltipdoes not suppressfeature.tooltipContentresolution; it only disables the built-in popover's DOM mount, so a consumer can still readdetail.feature.tooltipContentoff the event if it wants the pre-rendered declarative string.changeevent on the<protvista-uniprot>element.detail.eventType—clickopens a tooltip,mouseover/mouseout/resetdrive your own hover and dismissal logic.detail.feature(the full adapter-output item, including anytooltipContentthe library pre-computed) anddetail.coords(an[x, y]tuple in page coordinates).[x, y]. Host owns the JSX, the lifecycle, and the styling.undefined/reset/ subsequentclickevents (the dismissal set that uniprot-website uses).FeatureViewer.tsxis the real reference but has a lot of ambient app concerns; a stripped-down example is more digestible for a new adopter.notooltipgains a "See React host integration for the consumer-side pattern." pointer.notooltipproperty insrc/protvista-uniprot.ts: a one-line link to the new spec section, so IDE tooltip-on-hover points the right way.docs/react-integration.md: optional second home for the same content, closer todocs/data-tooltip.md. Decide between "single source in the spec" vs. "tutorial-flavoured copy indocs/and normative contract in the spec" when drafting.Notes:
Three things to pin down while writing the section, all surfaced during the original discussion:
detail.eventTypevalue vocabulary. Current values:'click','mouseover','mouseout','reset'. Document every one, including whatresetmeans (Nightingale emits it when the user scrolls / zooms, effectively "stop showing any per-feature tooltip"). The set is load-bearing — uniprot-website'shideTooltipEvents = new Set([undefined, 'reset', 'click'])assumes all three dismissal triggers.detail.coordscoordinate space. Document that these are page-coordinates (clientX/clientY-style) so the consumer knows whether they need to transform to container-local coordinates. Worth sanity-checking against the Nightingale source before committing a statement either way.React 19 forward-looking note. The uniprot-website code has a TODO referencing
ref-callback-with-cleanup — a React 19 feature that replaces the separate mount/unmountuseEffectpair. Worth mentioning in the doc as the preferred pattern once React 19 is available, so new adopters don't copy the older split-useEffect shape as the canonical form.No code changes in this issue — pure documentation. The existing event-listening integration path works today on the config-approach branch; the gap is that nobody would know from the docs alone that this is the intended path. Estimated effort: half a day to draft, half a day to shake down with a real uniprot-website migration trial run.
Cross-links with existing next-branch issues:
highlight-event="onclick"from the aggregate), the React integration doc should mention that a click on the collapsed aggregate opens a tooltip without a highlight state change, distinct from a click on the expanded detail track.linegraphsemantic kind for bring-your-own-data authors" — BYOD consumers who pair generic kinds with a React host are the second audience for this doc; worth cross-referencing.