Appearance
Guide: Adding a New Data Section to the Tooltip
This document outlines the general procedure for adding a new, optional data section to the gene tooltip (e.g., GO Terms, Phenotypes, etc.). The package is designed with an extensible pattern, so adding new sections involves touching four key files in a predictable way.
For this guide, we'll use "GO Terms" as our running example. The mygene.info API provides this data under a go
field.
The 4-Step Pattern
- Configure: Define the data shape and user-facing options.
- Fetch: Request the new data from the API.
- Render: Create the HTML for the new section.
- Integrate: Wire up the renderer and any interactivity (like "more" buttons).
WARNING
This is an untested example, and may contain out of date information.
Step 1: Configure the New Section (src/config.ts)
This is the source of truth for your data structures and user settings.
A. Define the incoming data shape:
If the API returns a complex object, create a new interface for it.
typescript
// src/config.ts
// ... other interfaces
export interface MyGeneGoTerm {
id: string;
term: string;
category: "CC" | "BP" | "MF";
}
B. Add the new field to MyGeneInfoResult:
Update the main data interface to include your new field.
typescript
// src/config.ts
export interface MyGeneInfoResult {
// ... other fields
interpro?: MyGeneInterproDomain[] | MyGeneInterproDomain;
go?: MyGeneGoTerm[] | MyGeneGoTerm; // <--- ADD YOUR NEW FIELD
// ... other fields
}
C. Add a display flag to TooltipDisplayConfig:
This gives users a boolean switch to show or hide the section.
typescript
// src/config.ts
export interface TooltipDisplayConfig {
// ... other flags
geneTrack: boolean;
generifs: boolean;
goTerms: boolean; // <--- ADD YOUR NEW DISPLAY FLAG
links: {
// ...
};
}
D. Add configuration options to GeneTooltipConfig and defaultConfig:
Add a ...Count
property to control how many items are shown initially, and set its default value.
typescript
// src/config.ts
export interface GeneTooltipConfig {
// ... other counts
generifCount: number;
goTermCount: number; // <--- ADD YOUR NEW COUNT
tooltipWidth?: number;
}
export const defaultConfig: GeneTooltipConfig = {
// ... other defaults
display: {
// ...
generifs: true,
goTerms: true, // <--- SET DISPLAY DEFAULT
},
// ...
generifCount: 3,
goTermCount: 5, // <--- SET COUNT DEFAULT
// ...
};
Step 2: Fetch the Data (src/api.ts)
This is the simplest step. You just need to tell the mygene.info query to include your new field in its response.
A. Add the new field name to the fields array:
typescript
// src/api.ts
export async function fetchMyGeneBatch(/*...*/) {
// ...
const fields = [
// ... other fields
'pdb',
'generif',
'go' // <--- ADD THE API FIELD NAME HERE
].join(',');
// ...
}
Step 3: Render the HTML (src/renderer.ts)
This is where you transform the raw JSON data into user-friendly HTML.
A. Create a new render...
function for your section:
Follow the pattern of the existing renderPathways
or renderDomains
functions. The goal is to convert the raw data into an array of { name: string, url: string }
objects that the generic renderParagraphSection helper can use.
typescript
// src/renderer.ts
// Helper to ensure data is an array
function asArray<T>(data: T | T[] | undefined): T[] {
if (!data) return [];
return Array.isArray(data) ? data : [data];
}
// NEW RENDER FUNCTION
function renderGoTerms(data: MyGeneInfoResult, count: number): string {
const rawGoTerms = asArray(data.go);
if (rawGoTerms.length === 0) return '';
// 1. Map raw data to the { name, url } format
const goTerms = rawGoTerms.map(go => ({
name: `${go.term} (${go.category})`, // e.g., "nucleus (CC)"
url: `https://www.ebi.ac.uk/QuickGO/term/${go.id}`
})).sort((a, b) => a.name.localeCompare(b.name));
// 2. Define a unique ID for the "more" button
const moreButtonId = `goterms-more-${data._id}`;
// 3. Call the generic helper to create the HTML
return renderParagraphSection('GO Terms', goTerms, count, moreButtonId);
}
B. Call your new function from renderTooltipHTML:
Add the function call inside the main template, wrapped in its display flag check.
typescript
// src/renderer.ts
export function renderTooltipHTML(/*...*/) {
// ... destructure new count
const {
// ...
generifCount = 3,
goTermCount = 5, // <--- GET YOUR NEW COUNT
// ...
} = options;
return `
<div class="gene-tooltip-content" ...>
<!-- ... other sections -->
${display.generifs !== false ? renderGeneRIFs(data, generifCount) : ''}
${display.goTerms !== false ? renderGoTerms(data, goTermCount) : ''} {/* <--- ADD YOUR NEW SECTION */}
${renderLinks(data, display)}
</div>
`;
}
Step 4: Integrate Interactivity (src/index.ts)
The final step is to wire up the "more" button so it shows a nested tooltip with the full list of items.
A. Pass the new count to the renderOptions:
In the onShow hook, make sure the count from the configuration is passed down to the renderer.
typescript
// src/index.ts
// ...
onShow(instance: Instance) {
// ...
const renderOptions = {
// ...
generifCount: config.generifCount,
goTermCount: config.goTermCount, // <--- PASS THE COUNT
tooltipWidth: config.tooltipWidth,
// ...
};
// ...
}
B. Add the nested tippy logic in onMount:
In the onMount hook, add logic to find your new "more" button and attach a nested tippy to it. Use the createNestedTippy helper for consistency.
typescript
// src/index.ts
// ...
onMount(instance: TippyInstanceWithCustoms) {
// ...
if (!data) return;
// ... (existing helper and other sections)
// NEW: Handle GO Terms
const goTermItems = asArray(data.go)
.map(go => ({
name: `${go.term} (${go.category})`,
url: `https://www.ebi.ac.uk/QuickGO/term/${go.id}`
}))
.sort((a, b) => a.name.localeCompare(b.name));
createNestedTippy(`#goterms-more-${data._id}`, goTermItems);
}
By following these four steps, you can cleanly and consistently add new data-driven sections to the tooltip while maintinaing flexible configuration options.