Conversation
Migrates from react-router-dom v6.30.4 to the unified react-router package (v7.18.1) across apps/platform, apps/docs, packages/ui, and packages/sections. react-router-dom was retired in favor of the unified package; v8 was skipped since it requires React 19, which would force an unrelated major upgrade. Usage is purely declarative (BrowserRouter/Routes/Route/hooks), so this is a straightforward import-path migration with no behavioral changes. Also fixes tech debt surfaced while verifying this change (confirmed unrelated to react-router, predating this branch): adds the repo-wide-missing @types/lodash package, declares 3dmol and lodash as explicit dependencies where they were used but undeclared (relying on accidental hoisting), and restores skipLibCheck to true to stop type-checking third-party packages' broken .d.ts files.
It's Yarn Berry's internal resolution cache, regenerated on every install, and not needed since this repo doesn't use Zero-Installs (nodeLinker: node-modules, no committed .yarn/cache).
Applies the existing lazy-wrapper pattern (already used by Downloads/API/Projects pages) to the 8 remaining eager pages: Disease, Drug, Target, Evidence, Variant, Study, CredibleSet, and Analysis. Each gets a thin Wrapper that lazy-imports the real page behind a Suspense boundary; App.tsx itself is unchanged since it already imports pages through their directory index. HomePage and NotFoundPage stay eager intentionally: HomePage is the default landing route (lazy-loading it would add a loading flash for the most common entry point), and NotFoundPage is rendered inline without a Suspense boundary in a couple of data pages. Cuts the main platform bundle from ~9MB (2.66MB gzip) to ~2.6MB (767KB gzip); heavy dependencies like cytoscape (5.2MB) and the associations network view now load on demand instead of upfront.
CI run for this PR showed the disease page header test consistently timing out at the default 5000ms expect() timeout - Playwright's own page snapshot at failure time showed the page still on its loading spinner, not a broken page (other tests confirm the same page renders correctly with more time). Root cause: page components are now code-split (previous commit), so the first navigation to any of the 8 newly-lazy pages needs to fetch an extra JS chunk before rendering, on top of normal query latency. That's normally trivial (~5-12KB gzipped) but a cold Netlify PR preview plus CI runner contention pushed it past 5s here. The same profile-page-header-text assertion pattern is used across multiple page specs (disease, target, drug, etc.), so this is scoped as a global default rather than a single-test patch.
…outer-v7 # Conflicts: # apps/docs/package.json # apps/platform/package.json # packages/sections/package.json # packages/ui/package.json # yarn.lock
… chore/upgrade-react-router-v7
… analysis, and implement lazy loading for Viewer component
Both were importing from the deprecated @mui/styles path, which also meant their theme type wasn't augmented with MUI's palette/spacing (surfaced as spurious "Property 'palette' does not exist" tsc errors). Part of removing @mui/styles ahead of an MUI v6/v7 upgrade.
Same fix as packages/ui: these files imported useTheme from the deprecated @mui/styles path instead of @mui/material/styles.
Same fix as packages/ui and packages/sections: these files imported useTheme/styled from the deprecated @mui/styles path instead of @mui/material/styles.
Replaces sectionStyles.ts (makeStyles/JSS) with colocated SectionItem.styles.ts using @mui/material/styles' styled(). Drops three style keys (cardHeader, cardHeaderAction, loadingPlaceholder) that were defined but never applied anywhere. Preserves the exact current rendering, including two pre-existing JSS cascade quirks: avatarHasData's `!important` background always beat avatarError's non-important one, and descriptionHasData's rule was declared after descriptionError's, so it always won at equal specificity. In practice only the title ever visually turned "error" colored; avatar and description did not. Left as-is here rather than fixed, since this migration is scoped to be a pure refactor — worth a follow-up decision on whether to make all three consistent.
Replaces summaryStyles.ts (makeStyles/JSS) with colocated
SummaryItem.styles.ts using @mui/material/styles' styled(). The old
hover cascade ("&:hover $titleHasData" etc., JSS class-ref selectors
with no sx equivalent) is reproduced via emotion's component-selector
interpolation, referencing the sibling styled components directly in
StyledCard's hover block.
Drops classes.cardError, which was referenced in SummaryItem's
classNames() call but never existed in summaryStyles.ts - a
pre-existing dead reference (confirmed by a matching tsc error that's
now gone). Also drops the cardContent/content style keys, which were
defined but never applied anywhere.
Preserves a pre-existing JSS specificity quirk: subheaderError was
applied unconditionally (not gated on the actual error value) and its
rule came after subheaderHasData's, so it always won at equal
specificity - the subheader was always rendered in the error color.
Left as-is per the same "pure refactor" rule as the Section migration.
Without shouldForwardProp, styled("div") forwards unknown props to the
DOM by default, which would leak an "error" attribute onto the
rendered element and trigger a React warning.
Replaces tableStyles.ts's makeStyles hooks (tableStyles,
globalSearchStyles) with styled() components, consumed by Table.tsx,
TableHeader.tsx, TableRow.tsx, and GlobalFilter.tsx.
Drops Table's untyped `classes` prop (classes.root/classes.table
merged via classNames) in favor of typed `containerSx`/`tableSx`
props. One real external consumer existed - PublicationsList.tsx in
packages/sections, which used classes.root to zero out the
container's marginTop - migrated to `containerSx={{ marginTop: 0 }}`
and its own single-purpose makeStyles hook removed as a drive-by
(it existed only to produce that one class).
Also drops TableHeader's `headerClasses.headerSpan` reference, which
was never defined in tableStyles.ts and was already a no-op (JSS
resolved it to undefined, silently dropped by classnames() as a
falsy positional arg) - confirmed by a matching tsc error that's now
gone. And drops the never-applied `tooltipCardContent` style key.
Verified &:first-child/&:last-child in the header/body cell styles
still target the correct DOM element: the Hidden wrapper around each
cell renders a bare React.Fragment (no DOM node) when visible, so
TableCell remains a direct, adjacent child - no behavior change from
preserving these selectors verbatim.
Tooltip.tsx was the one real exception to the rest of this migration:
it called makeStyles inline in the render body, merged with a `style`
prop, for genuine per-instance overrides rather than static theming.
Traced actual usage: only classes.tooltip and classes.tooltipIcon were
ever applied to any element - tooltipBadge and tooltipArrow were
defined but never used. Of the two real (non-empty) `style` callers,
only ClinicalRecordDrawer.tsx's { tooltipIcon: {...} } shape ever hit
a key the base object actually had (lodash's merge() deep-merges
matching keys). DirectionalityDrawer.tsx's { background: "red" } had
no matching key, so it was appended as an inert sibling property -
already a no-op today, preserved as such rather than "fixed".
Replaces the base tooltip/tooltipIcon styles with a styled(MUITooltip)
targeting .MuiTooltip-tooltip, and the per-instance tooltipIcon
override with a plain inline style spread on the <sup> element.
ArrowTurnDownLeft, BrokenSearchIcon, EllsWrapper, PlotContainer, PlotContainerSection, ClinvarStars: static/single-instance makeStyles usages converted to inline style/sx props (raw svg/div elements get plain `style`, MUI components get `sx`; ClinvarStars' color moves to FontAwesomeIcon's native `color` prop via useTheme).
Chip, NewChip, ChipList: converted to styled() since these are reusable atoms rendered many times per page (ChipList renders per item in a .map()). StyledChip needs `as typeof Chip` to preserve MUI's polymorphic `component` prop typing, which styled() otherwise drops. LongList, LongText, OtLongText: single-instance styles converted to sx (Typography/Box), since each style key maps to exactly one JSX element per render.
Link.tsx is the highest-leverage file in this batch (rendered
hundreds of times per page), so it gets styled() with shouldForwardProp
filtering the footer/hasTooltip boolean props, rather than sx. Variant
priority (footer > tooltip > default) is preserved to match the old
JSS declaration-order precedence when multiple conditions overlap.
TepLink, CopyUrlButton: MUI Tooltip/Snackbar slot overrides (classes
prop) converted to styled() targeting the stable .MuiTooltip-tooltip /
.MuiSnackbarContent-* global class names.
XRefLinks, EmailLink: single-instance styles converted to sx/styled
as appropriate (EmailLink's <a> needs :hover, so styled("a") rather
than plain inline style).
…ckages/ui DirectionOfEffectIcon, DataDownloader: MUI Tooltip/Snackbar slot overrides converted to styled() targeting stable global class names. GlobalSearchIcon: single fontSize override moved to a shared style const passed via native `style` prop (raw FontAwesomeIcon, not an MUI component). Highlights, LoadingBackdrop, OpenTargetsTitle: single-instance styles converted to sx.
…es/ui PublicationActionsTooltip: withStyles -> styled(Tooltip) targeting .MuiTooltip-tooltip. PublicationsDrawer: two makeStyles hooks removed. sourceDrawerStyles had 5 dead keys (AccordionExpanded/AccordionRoot/AccordionSubtitle/ AccordionTitle/summaryBoxRoot) never referenced anywhere in this file - dropped. listComponentStyles was never called as a hook at all; its only reference was `listComponentStyles.AccordionSubtitle`, a static property read on the hook function itself (always undefined) - confirmed by a matching tsc error that's now gone. Deleted the whole dead hook and the dead className reference. PublicationSummary: createStyles wrapper removed (folded into this file's full conversion instead of a separate import-only fix, since it still had real makeStyles usage). Dropped its unused `fileLabel` key. PublicationWrapper: dropped its unused `matchTable` key. Both PublicationSummary/PublicationWrapper's Box `sx` callbacks use theme.palette.grey directly since MUI's spacing-string shorthand doesn't apply to `background`.
…packages/ui DirectionalityDrawer, KnownDrugsSourceDrawer: same drawer pattern as PublicationsDrawer (Paper/Drawer/Typography slot overrides -> styled() targeting stable MUI global class names). DirectionalityDrawer's Accordion/summary classes were dead here (never used); dropped, unlike KnownDrugsSourceDrawer's identical-looking keys which ARE used and get a real styled(Accordion) with a &.Mui-expanded selector. Footer: 5 separate makeStyles hooks (one per sub-component) converted to sx/styled/inline style depending on instance count. Dropped the unused linkContainer key. LicenseCC0's two Link instances need styled(Link) since our Link component doesn't accept sx, only className - styled() works generically here since Link forwards className. GlobalSearchListHeader: sectionHeader/label divs converted to Box+sx.
…es/ui Header: dropped unused mainIconContainer key (superseded by the existing iconHeaderStyles/iconTextStyles sx objects already in the file), converted the rest to sx/color props. HeaderMenu: menuLink applies to our custom Link component, which only forwards className (not sx), so it needs styled(Link) rather than sx. NavBar: the highest-risk file here (rendered on every page, the navbar class carried the classic JSS-vs-MUI-defaults !important). Converted to styled(AppBar) with a homepage boolean prop. Dropped 4 dead keys (flex, menuList, navLogo, navSearch) never referenced. MenuExternalLink no longer takes `classes` as a prop - it's a NavBar-local subcomponent, no external callers. Page (both packages/ui/src/components/Page.tsx and packages/ui/src/pages/Page.tsx - near-duplicate files) and EmptyPage: converted to Box/Grid sx. EmptyPage drops an unused marginTop key and an empty no-op messageLogoContainer key, and reuses one hiddenMobileSx object across its two responsive elements via sx array syntax.
Bumped in all 7 workspaces that declare it directly (ui, sections, platform, docs, and the 3 shared @ot/* packages - ot-config, ot-constants, ot-utils were missed in the initial audit and would have caused a duplicate v5/v6 MUI install if left behind). Added a react-is resolution pin (^18.3.1) per MUI's v6 upgrade guide for React 18 projects. Ran the official v6 codemods (styled, sx-prop, theme-v6) as a sanity check; reverted their output - the styled codemod introduced two real TS2304 "cannot find name 'hasData'" bugs in SummaryItem.styles.ts by incompletely migrating ternary conditionals to the new variants API, and touched 30 other files for a purely optional modernization (v5-style conditional styled() already works unchanged in v6). Not worth the risk for zero functional benefit. Verified via a strict before/after tsc diff per package (stashing the package.json/lockfile changes to get a true v5 baseline): zero new errors in ui, sections, or platform. Every diff is either a cosmetic MUI-internal type rename (e.g. an inlined union now named `Placement`) or a pre-existing broken file (HeatmapTable.tsx) picking up the same cosmetic rename. Full turbo build, biome check, and a 9-page Playwright smoke test (home, target, disease, drug, variant, study, credible-set, downloads, api) all clean.
Bumped in all 7 workspaces (same set as the v6 bump). Two required
changes per MUI's v7 upgrade guide:
- Renamed Grid -> GridLegacy across all 43 files using the classic
xs=/md=/item prop API (grep for `<Grid\b` found 43, not the 36 an
earlier single-line-import regex caught - 7 files use multi-line
import statements that missed the first pass, including
BaselineExpressionTable.tsx, caught via a before/after tsc diff
showing a genuine new Grid-prop type error). No prop-level changes -
this is a mechanical rename deferring the real Grid v2 migration
(xs={12} -> size={{xs:12}}) to the eventual shadcn migration, where
Grid gets replaced entirely anyway.
- Replaced <Hidden> (fully removed in v7) in TableHeader.tsx/TableRow.tsx.
Its breakpoint props came from column.hidden, which is never set
anywhere in the codebase - the wrapper was a permanent no-op, so it's
simply removed rather than reimplemented.
One real v7 behavior change found via the browser smoke test (not
tsc): Dialog's `role` prop is now runtime-validated to "dialog" |
"alertdialog" only (PropTypes.oneOf, not just a TS type). Fixed
GlobalSearchDialog's intentional role="searchbox" (for accessibility)
by moving it to slotProps.paper.role, which lands on the same DOM
element without going through Dialog's own restricted prop.
Verified via strict before/after tsc diff per package (stashing to
get a true v6 baseline): every remaining diff is either the expected
Hidden-fix line shift or a cosmetic MUI-internal type rename
(Variant -> TypographyVariant, TypographyOptions ->
TypographyVariantsOptions, etc.) for already-broken pre-existing code.
Full turbo build, biome check, and a 9-page Playwright smoke test all
clean - including catching and fixing a stale Vite dependency-cache
issue (GridLegacy import failing at runtime despite tsc passing,
resolved by clearing node_modules/.vite and restarting).
sx's theme-path string resolution ("grey.50" -> theme.palette.grey[50])
applies to backgroundColor/bgcolor, not the generic `background`
shorthand. The original JSS migration (7e9aca8) wrote `background:
"grey.50"` instead of `backgroundColor`, which happened to still resolve
under MUI v5/v6 but silently stopped working under v7 - "grey.50" isn't
valid CSS for the `background` property, so it was dropped, leaving the
page background transparent (showing white body) instead of the
intended light grey. Confirmed by diffing against production, which
still renders the correct #fafafa background. Same bug in both Page.tsx
files (packages/ui/src/pages and packages/ui/src/components - a known
near-duplicate pair).
apps/platform already had this declaration (src/documentNode.d.ts) but packages/ui and packages/sections didn't - each has its own separate tsconfig, so the declaration doesn't carry over between them. Without it, TypeScript (and therefore VS Code's hover/intellisense) can't resolve any `import X from "./Y.gql"`, showing "Cannot find module" on every single one - 148 files in sections, 7 in ui - each also cascading into extra implicit-any errors on the resulting untyped import elsewhere in the same file. Mirrors platform's existing file exactly. Confirmed via tsc: 0 "Cannot find module *.gql" errors remaining in either package (was 148+7), ~105 fewer total errors per package from the cascading any-noise clearing up too.
…imports Adds a facade layer in packages/ui for common @mui/material primitives (Box, Typography, GridLegacy, etc.) so consumers import from "ui" instead of "@mui/material" directly, making a future design-system swap (shadcn) a single-point change. Pilot: packages/sections' 82 affected files moved over; apps/platform and apps/docs left for a follow-up pass. Chip/Button/ Tooltip/Link intentionally excluded — ui already has custom wrapped versions under those names.
ui already exports custom Chip/Button/Tooltip/Link under those bare names, so raw MUI usages are re-exported as MuiChip/MuiButton/ MuiTooltip/MuiLink instead — collision-free, local identifiers unchanged (import aliasing absorbs the rename, no JSX touched). Follow-up: audit these ~19 raw usages against the custom wrappers' prop APIs for possible consolidation (design consistency).
…ersions Chip: widened ui's Chip prop type from a hand-picked subset (label: ReactElement only) to Omit<MuiChipProps, "variant"|"size">, so it accepts the full MUI API (color, sx, clickable, onClick, ReactNode label) while still forcing the outlined/small look. Swapped the 7 sections call sites whose props already matched (variant="outlined" size="small" exactly) to use it, dropping the now-redundant props. Bonus: this also fixed 2 pre-existing type errors in ProfileChipList.tsx, which was already fighting the old, too-strict label type. 3 Chip call sites (evidence/OTEncore, evidence/OTValidation, common/ Literature/Entities) and common/Bibliography/Body.tsx keep raw MuiChip — their chips are filled/medium by default, a different design already in place, not a fit for the fixed outlined/small contract. Tooltip: OntologyTooltip.tsx had copy-pasted ui's Tooltip theme override CSS verbatim. Exported the underlying styled component (StyledMUITooltip) from ui instead of re-declaring it. Button: audited but left alone — ui's custom Button hardcodes `border: none`, which would strip the visible border off every variant="outlined"/"contained" button (2 of 6 call sites use those). Not a safe swap without changing the custom Button first. Link: the 2 raw MuiLink imports found in the earlier facade pass turned out to be pre-existing dead imports (already flagged by tsc as unused, unrelated to this migration) — deleted them.
Rounds out the swap-point migration started in packages/sections: moved apps/platform's 96 @mui/material-importing files onto the ui barrel. Surfaced real gaps the sections-only census missed (multi-line imports undercounted several names) — added Card*, Dialog*, Menu*, List*, Accordion*, Stepper family, Divider, Stack, Snackbar, Radio*, Switch, Select, Modal, Popover, NativeSelect, FormHelperText, Slide to the facade; retroactively swept packages/sections too so both packages share one complete list. Chip/Button/Tooltip/Link raw usages aliased (MuiChip/MuiButton/ MuiTooltip/MuiLink) same as the sections pass — the collision/consistency review from that pass (Button's border:none incompatibility, etc.) applies here too and is deferred the same way. Verified: tsc --noEmit on apps/platform, packages/sections, packages/ui all produce byte-identical error sets before/after (line-shift only); yarn build:platform succeeds.
ui's custom Button hardcoded border:none, which silently strips the
visible border off any variant="outlined"/"contained" button. Confirmed
via its one real pre-existing consumer (DataUploader.tsx), whose
variant="outlined" Back/Upload buttons have been rendering borderless
in production — a pre-existing bug, not introduced by this branch.
With that fixed, swapped 21 of the 26 sections/platform files carrying
raw MuiButton onto the real Button — all had zero startIcon/endIcon
usage, so the only remaining behavioral difference (Button's
".MuiButton-startIcon { fontSize: 14px !important }") is a no-op for
them. Bonus: ColumnOptionsMenu.tsx had locally re-declared that exact
CSS rule (plus a redundant border:none) on top of the raw import —
deleted the duplicate wrapper and used Button directly.
Left on raw MuiButton (5 files): EuropePmc/Publication.tsx builds its
own styled(Button) with explicit startIcon sizing; RunHistorySidebar,
StandaloneGeneInput, and ExportButtons pass startIcon on
outlined/small-or-medium buttons where the 14px override isn't
guaranteed to be visually identical to current rendering. Consolidating
those needs a visual check, not a mechanical swap.
Button's ".MuiButton-startIcon { fontSize: 14px !important }" was the
same class of bug as the border:none one fixed earlier: correct only for
size="medium" (whose default font-size is 14px anyway), wrong for
size="small" (13px) and size="large" (15px). Confirmed a no-op for the
one real consumer (DataUploader.tsx never sets size), so removing it
changes nothing today and fixes small/large going forward. Button is
now a genuine no-op wrapper around MuiButton — exactly the swap point
this facade is for.
With that gone, the remaining 4 raw-MuiButton call sites held back
last commit (EuropePmc/Publication, RunHistorySidebar,
StandaloneGeneInput, ExportButtons) have zero behavioral difference
from the real Button, so consolidated them too. All 26 Button call
sites across sections/platform now use the real ui Button.
Chip's variant/size were forced via Omit<MuiChipProps, "variant"|"size">,
which blocked the 4 remaining raw-MuiChip sites — they rely on MUI's
native filled/medium defaults for selectable/interactive chips, a
genuinely different design than the outlined/small "tag chip" look this
component was built for. Forcing them onto Omit-typed Chip would have
silently converted them.
Changed ChipProps to plain MuiChipProps (no Omit) and made the compact
sizing (height 20px, tight margins) conditional on the *resolved*
variant/size being outlined+small, computed inside styled()'s callback
rather than baked into the base class. variant="outlined" size="small"
in the component body are now defaults, not forced — {...props} already
spread last, so passing either explicitly overrides them; the 7
already-consolidated sites are unaffected since they don't pass either.
Swapped the last 4 sites (evidence/OTEncore, evidence/OTValidation,
common/Literature/Entities, common/Bibliography/Body) onto the real
Chip, adding explicit variant="filled" size="medium" (or size="medium"
alone where variant was already outlined) to each call site — since
they previously relied on MUI's implicit defaults by omission, and
Chip's own default is now outlined/small, that implicit reliance had to
become explicit to preserve their current look.
All 15 Chip call sites across sections/platform now use the real ui
Chip. Verified: tsc byte-identical, yarn build:platform green.
Same treatment as the sections pass: swapped all raw MuiChip imports to the real ui Chip across apps/platform (ActiveFiltersPanel, NoveltyInlinePanel, RunHistorySidebar, AnalysisForm, ResultsPlotlySunburst, ResultsTable, SunburstFilters, ResultsTreeView, EnrichmentMapDetailsModal, EnrichmentMapLegend, EnrichmentMapControls, DownloadsCard, DownloadsTags, DownloadsFilter, HomePageSuggestions, ProjectsFilter, ProjectCard). Most of these omitted variant (relying on MUI's native "filled" default) or omitted size (relying on "medium"). Since Chip's own defaults are now "outlined"/"small", every call site that previously relied on the implicit MUI default had that made explicit (variant="filled" and/or size="medium") to preserve its current look — 30+ individual Chip instances touched, all mechanical prop additions, no new visual behavior. This batch had denser sx pixel-tuning than sections (height/fontSize overrides on top of variant+size), so it depends on MUI's sx-over-styled precedence to still apply the caller's own sizing on top of Chip's conditional compact styling — standard, well-documented MUI cascade behavior, not independently visually verified in this session (user opted to proceed on that basis rather than screenshot-verify). tsc byte-identical before/after aside from one pre-existing, unrelated type error in HomePageSuggestions.tsx whose message text reordered (same underlying error, not new). yarn build:platform green.
Chip was a plain function component, so it couldn't receive a ref. common/Literature/Entities.tsx wraps each selectable-entity Chip in <Grow>, which attaches a ref to its child to measure/animate it — that combination threw in the browser once Entities.tsx was swapped from raw MuiChip (which does forward its ref) onto the ui Chip, breaking target profile's Bibliography section (reported: crashing on localhost). Verified via Playwright against the running dev server: error was "Invalid prop `children` supplied to `ForwardRef(Grow2)`", traced through EntitiesToSelect -> Entities -> Grow -> Chip. Wrapped Chip in forwardRef, forwarding to the underlying styled MUI Chip. Re-verified in the browser: bibliography section (entity selector chips, filters, publication list) now renders correctly on BRAF's target profile.
The app theme (ot-config's theme.ts) forces a 1px grey border onto every MuiButton root by default, regardless of variant. That border reads fine on most buttons but not on AOTF's toolbar triggers (Advanced filters, Column options, Upload diseases, Export) — a dense row of icon+label dropdown-style buttons where the border looks noisy. Added ButtonNoBorder (styled(Button) with border: none) alongside Button/ButtonPrimary in ui's Button.tsx, plus an optional `noBorder` prop on PopoverButton that swaps its base component. Applied it to all 4 flagged buttons: FacetsSearch and ExportMenu (both via PopoverButton's new prop), ColumnOptionsMenu and DataUploader's upload trigger (direct component swap). AnalysisMenu, the 5th button in the same row, also uses PopoverButton but wasn't in scope — left with the default border. Verified visually against the running dev server: all 4 buttons render borderless, rest of the toolbar unaffected.
Replaced the noBorder boolean + internal branch with an `as` prop that takes the actual button component (Button/ButtonNoBorder/...) — callers now pass the real variant instead of a leaky flag that only encoded one of them. Also changed ButtonNoBorder itself: border is transparent by default (same 1px reserved, so no layout shift) and turns visible on hover, rather than being permanently invisible — gives the button a hover affordance instead of looking dead. Verified default/hover states against the running dev server.
The "Ot" prefix on custom ui components had no consistent rule — some components had it (OtCodeBlock, OtPopper, OtBtnGroup...), most didn't (Chip, Button, Tooltip, Table). Dropped it from the 7 components where it was safe to do so with zero naming collision against the rest of the barrel: BtnGroup, CodeBlock, CopyToClipboard, InvalidResultFilters, Popper (aliased its own MuiPopper import to avoid self-shadowing), ScoreLinearBar, and GenomicLocation (file was already unprefixed, only the export alias carried "Ot"). Explicitly NOT renamed: - OtAsyncTooltip: real infrastructure for the separate MCP widgets server repo, which likely imports "ui" directly — renaming would be a breaking change for a consumer outside this monorepo. - OtTable/OtTableSSP: "Table" is already taken by the older MUI-table implementation (Table/DataTable) that OtTable's Tanstack-based replacement is mid-migration away from (63 vs 34 call sites) — a real convergence question, not a rename, and out of scope here. Also merged LongText + OtLongText (near-identical, only real diff was default label text) into one LongText with an optional `displayText` prop. The two had a subtle structural difference beyond the default text — LongText always prepends "... " before the bracketed link, OtLongText didn't — preserved via the prop's presence/absence rather than flattening them, so both existing behaviors survive unchanged. Found and fixed one more deep-import consumer bypassing the barrel (ClinicalRecordDrawer.tsx re missed by the barrel-only grep sweep, now passes displayText="...show more" explicitly to preserve its exact prior look). Verified: tsc byte-identical/improved (a few pre-existing type errors got fixed as a side effect — LongText's `variant` prop was oddly required despite always having a default), yarn build:platform green, and manually confirmed in the browser (Downloads page: cards use the merged LongText, Schema modal uses CodeBlock, Access Data modal uses BtnGroup — all render correctly, zero console errors).
Removed packages/ui from biome.json's exclusion list — it had no lint or format safety net until now. Ran `biome check --write` (safe fixes only): reformatted + reorganized imports across 158 files, dropping violations from 250 errors/392 warnings to 37 errors/297 warnings. Verified zero behavior change: tsc --noEmit output identical aside from cosmetic reordering (two named exports' error messages swapped source file order after imports got resorted), yarn build:platform green. 37 errors remain, spanning noDangerouslySetInnerHtml (4, security- sensitive), useUniqueElementIds (12), a11y issues (9), useValidTypeof (2 errors + 16 warnings — some may be real typo bugs, needs a look), noUnreachable (3), and a few others — none auto-fixable, all need actual code review rather than mechanical fixes. 297 warnings, mostly useExhaustiveDependencies (121, real risk to blind-fix — can silently introduce infinite render loops) and noExplicitAny (95). Left for a follow-up pass.
Enabling biome surfaced 37 errors that would fail CI. Rather than silence them via rule-severity overrides, just excluding packages/ui from biome's scope again (like before this branch) — same as the original config, single-line diff. The auto-formatted/reorganized code from the previous commit stays as-is (real improvement, just not CI-enforced yet); actually fixing the remaining lint debt and turning the check back on is follow-up work, not part of this PR.
Adds a new MCP (Model Context Protocol) server that exposes Open Targets data visualisation widgets as MCP App tools for use in Claude Desktop. - Express HTTP server with Streamable HTTP MCP transport - Widget tools auto-generated from the sections registry (target, disease, drug, evidence, credible-set, variant, study entities) - Server-side GraphQL prefetch via ot_fetch_widget_data tool, working around Claude Desktop bug #696 that strips structuredContent from tool-result notifications - IIFE widget bundles built with Vite, inlined into HTML shells served as MCP App resources - Molecular structure widget with AlphaFold 3D viewer (manual entry) - Dockerfile for Cloud Run deployment (max-instances=1 for session stickiness); stdio transport for local Claude Desktop use via mcp-remote
- Updated SectionDef to remove prefetch-related properties and directFetch flag. - Modified SECTION_REGISTRY to reflect changes in widget definitions. - Simplified widget derivation logic in index.ts, removing prefetch handling. - Adjusted molecularStructureWidget to fetch data directly from the iframe. - Cleaned up types related to prefetching in types.ts. - Removed unused prefetch data handling and fetch interceptor logic in createWidgetEntry.tsx.
…nd improved link handling
…pdate naming conventions
CI's --immutable install failed since polished was added to apps/mcp-widgets-server/package.json but the lockfile was never regenerated to match.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[WidgetsMCP]: First look at the open targets widgets-mcp
Type of change
Checklist: