Recipes & Customization
A recipe is an ordered list of token entries that controls what text appears in a node's description. The customization store manages active recipes per role and supports presets.
RecipeEntry
interface RecipeEntry {
token: TokenName;
brevity: Brevity;
}| Property | Type | Required | Description |
|---|---|---|---|
token | string | yes | The token name to include (e.g., 'name', 'visData'). |
brevity | 'short' | 'long' | yes | Which form of the token value to use. |
A recipe is simply RecipeEntry[]. The order of entries determines the order of text fragments in the assembled description.
Customization
interface Customization {
role: string;
recipe: readonly RecipeEntry[];
}| Property | Type | Required | Description |
|---|---|---|---|
role | string | yes | The hyperedge role this customization applies to (e.g., 'root', 'xAxis', 'filteredData'). |
recipe | RecipeEntry[] | yes | The ordered token entries. |
Customizations are automatically persisted to localStorage and restored on subsequent page loads.
CustomizationStore
The runtime creates a CustomizationStore that manages customizations per role:
interface CustomizationStore {
activeFor(role: string): Accessor<Customization>;
setFor(role: string, customization: Customization): void;
resetFor(role: string): void;
registerPreset(name: string, customizations: readonly Customization[]): void;
applyPreset(name: string): void;
activePresetName(): string | null;
listPresets(): ReadonlyArray<{ name: string; customizations: readonly Customization[] }>;
setRecipeFilter(fn: RecipeFilter | null): void;
recipeFilter(): RecipeFilter | null;
}Key methods
| Method | Description |
|---|---|
activeFor(role) | Returns a reactive accessor for the active customization for a role. |
setFor(role, customization) | Sets a custom recipe for a role. |
resetFor(role) | Resets to the default recipe. |
registerPreset(name, customizations) | Adds a named preset. |
applyPreset(name) | Applies all customizations from a preset. |
activePresetName() | Returns the currently active preset name, or null. |
listPresets() | Returns all registered presets. |
setRecipeFilter(fn) | Sets a function that post-processes recipes (e.g., hiding the parent token when there are no multi-parent nodes). |
Default recipe
When no customization or preset is active, the default recipe is:
const DEFAULT_RECIPE: RecipeEntry[] = [
{ token: 'name', brevity: 'long' },
{ token: 'index', brevity: 'short' },
{ token: 'parent', brevity: 'long' },
{ token: 'children', brevity: 'short' },
];Virtual parent-context nodes have their own default:
const DEFAULT_VIRTUAL_RECIPE: RecipeEntry[] = [
{ token: 'parentContext', brevity: 'long' },
];Recipe filters
The runtime installs a recipe filter that removes the parent token when no edges of the given role have multiple parents. This prevents announcing "parent: X" on nodes where there's only one possible parent — the information adds no value.
type RecipeFilter = (role: string, recipe: readonly RecipeEntry[]) => readonly RecipeEntry[];How recipes drive descriptions
When the describe function assembles a description for a nav node:
- It looks up the node's role (from
edge.role). - It calls
customization.activeFor(role)()to get the current recipe. - For each
RecipeEntryin the recipe, it finds the corresponding token by name. - It calls
token.compute(context)and selectsshortorlongbased onentry.brevity. - Non-empty results are assembled into a single string using join hints.
This means you can customize descriptions by:
- Reordering entries in the recipe.
- Changing
brevityfrom'long'to'short'(or vice versa). - Adding or removing token entries.
- Registering entirely new tokens and including them in a recipe.
Next
- Presets — the built-in vis presets.
- Tokens — the token types and built-in tokens.
- Contributing Tokens — adding custom tokens.