Appearance
Guide: Adding a New Data Section to the Tooltip
This document outlines the procedure for adding a new data section (e.g., GO Terms, Phenotypes) to the gene tooltip. The package uses a modular pattern involving configuration, data formatting, rendering, and lifecycle management.
For this guide, we'll use GO Terms (go field from mygene.info) as the example.
The 5-Step Pattern
- Configure: Define types and defaults in
src/config.ts. - Fetch: Request data in
src/api.ts. - Format: Transform raw API data into standard objects in
src/formatters.ts. - Render: Generate HTML in
src/renderer.ts. - Integrate: Wire up nested tooltips in
src/lifecycle.ts.
Step 1: Configure (src/config.ts)
Define the shape of the data and user configuration options.
A. Define the data interface
Add the interface for the raw API data.
typescript
// src/config.ts
export interface MyGeneGoTerm {
id: string;
term: string;
category: 'CC' | 'BP' | 'MF';
}B. Update MyGeneInfoResult
Add the new field to the main result interface.
typescript
// src/config.ts
export interface MyGeneInfoResult {
// ... existing fields
generif?: GeneRIF[] | GeneRIF;
go?: MyGeneGoTerm[] | MyGeneGoTerm; // <--- ADD THIS
}C. Update TooltipDisplayConfig
Add a visibility flag. Note that sections now use SectionVisibility (boolean | 'expanded' | 'collapsed').
typescript
// src/config.ts
export interface TooltipDisplayConfig {
// ... existing fields
generifs: SectionVisibility;
goTerms: SectionVisibility; // <--- ADD THIS
// ...
}D. Update GeneTooltipConfig and defaultConfig
Add an item count setting and set defaults.
typescript
// src/config.ts
export interface GeneTooltipConfig {
// ...
generifCount: number;
goTermCount: number; // <--- ADD THIS
}
export const defaultConfig: GeneTooltipConfig = {
// ...
display: {
// ...
generifs: true,
goTerms: true, // <--- SET DEFAULT VISIBILITY
},
// ...
generifCount: 3,
goTermCount: 3, // <--- SET DEFAULT COUNT
};Step 2: Fetch (src/api.ts)
Add the API field name to the query list.
typescript
// src/api.ts
export async function fetchMyGeneBatch(/*...*/) {
// ...
const fields = [
// ...
'generif',
'wikipedia.url_stub',
'go' // <--- ADD API FIELD NAME
].join(',');
// ...
}Step 3: Format (src/formatters.ts)
Create a pure function to transform raw API data into a standard list of items ({ name, url }).
typescript
// src/formatters.ts
import type { MyGeneGoTerm } from './config'; // Import your new type
// ... existing functions
export function formatGoTerms(data: MyGeneGoTerm[] | MyGeneGoTerm | undefined): FormattedItem[] {
if (!data) return [];
// Use asArray helper to handle single objects vs arrays
return asArray(data)
.map(item => ({
name: `${item.term} (${item.category})`,
url: `https://www.ebi.ac.uk/QuickGO/term/${item.id}`
}))
.sort((a, b) => a.name.localeCompare(b.name));
}Step 4: Render (src/renderer.ts)
Generate the HTML. We use renderParagraphContent for comma-separated lists or renderListContent for bullet points.
A. Import the formatter
typescript
import {
// ...
formatGoTerms // <--- Import
} from './formatters';B. Create a specific render function
Use the uniqueId to ensure the "Show more" button works correctly.
typescript
function renderGoTerms(data: MyGeneInfoResult, count: number, uniqueId: string): string {
const items = formatGoTerms(data.go);
// Use renderParagraphContent (comma separated) or renderListContent (<ul>)
return renderParagraphContent(items, count, `goterms-more-${uniqueId}`);
}C. Update renderTooltipHTML
Update the options interface and the main HTML template.
typescript
// Inside src/renderer.ts
// 1. Update RenderOptions interface
interface RenderOptions {
// ...
generifCount?: number;
goTermCount?: number; // <--- Add
}
export function renderTooltipHTML(data: MyGeneInfoResult | null | undefined, options: RenderOptions = {}): string {
// ...
const {
// ...
generifCount = 3,
goTermCount = 3, // <--- Destructure
} = options;
// ...
// 2. Generate the content
const goTermContent = renderGoTerms(data, goTermCount, uniqueId);
return `
<div class="gene-tooltip-content" ...>
<!-- ... -->
${buildSection('generifs', 'GeneRIFs', generifContent)}
<!-- 3. Add the section using buildSection -->
${buildSection('goTerms', 'GO Terms', goTermContent)}
<!-- ... -->
</div>
`;
}Step 5: Integrate Lifecycle (src/lifecycle.ts)
This step activates the "Show more" button functionality (nested tooltips).
A. Update renderVisualsAndNestedTippys
typescript
// src/lifecycle.ts
import {
// ...
formatGoTerms // <--- Import formatter
} from './formatters.js';
async function renderVisualsAndNestedTippys(instance: TippyInstanceWithCustoms, config: GeneTooltipConfig) {
// ... setup code ...
// 1. Format the data again for the nested tooltip
const goItems = formatGoTerms(data.go);
// 2. Register the nested tooltip
// Arguments: instance, options, selector_id, items_array
createNestedTippy(
instance,
finalNestedTippyOptions,
`#goterms-more-${uniqueId}`,
goItems
);
// ... existing calls for transcripts, structures, etc.
}B. Update createOnShowHandler
Pass the new count configuration to the renderer options.
typescript
// src/lifecycle.ts
export function createOnShowHandler(...) {
return function onShow(instance: TippyInstanceWithCustoms) {
// ...
const renderOptions = {
// ...
generifCount: config.generifCount,
goTermCount: config.goTermCount, // <--- Pass from config
uniqueId: instance._uniqueId,
};
// ...
}
}By following these five steps, you can cleanly and consistently add new sections while maintinaing flexible configuration options.