@flourish/info-popup

中文文档
8.3.3发布于 2026/09/01LicenseRef-LICENSEES Module近 30 天下载 4142

Popup with data insertion

原始使用文档
文档目录18 节
  1. 1 - Installation
  2. 2 - Add a state property for the module, with an object as …
  3. 3 - Import the settings into your template.yml file
  4. 4 - Initialize the popup
  5. 5 - Attach event-based methods to the data
  6. 6 - Making sure the popup displays the correct, formatted, …
  7. 7 - Updating the popup with .update()
  8. 8 - Set up locking functionality (optional)
  9. Methods
  10. Event-based methods
  11. Setting a title and subtitle
  12. Specifying a default template
  13. Positional methods
  14. Hiding methods
  15. Getter methods
  16. Misc methods
  17. Adjusting which data bindings to show in the custom content…
  18. Templates to reference

Flourish Info Popup

Add data-driven popups (tooltips) and panels to any Flourish template, with style settings.

There are typically seven steps to using the module:

1 - Installation

npm install @flourish/info-popup

2 - Add a state property for the module, with an object as a value

const state = {
    popup: {} // Add any properties to this object to override the default settings
}

3 - Import the settings into your template.yml file

  - Popups & panels
  - property: popup
    import: "@flourish/info-popup"

4 - Initialize the popup

Initialize the popup, passing in the state property and optionally containers that determine the position of the popups and panels

import initialisePopup from "@flourish/info-popup";

const popup = initialisePopup(state.popup, panel_container, popup_container);

If you want the panel to fill the whole page (i.e. cover the header & footer), just ignore the panel_container and popup_container arguments.

5 - Attach event-based methods to the data

The important thing to understand with this module is that the template passes on information about user triggered events (e.g. click, mouseover etc) and then the module decides what should happen as a result of this event. This is because there are many different ways that popups and panels behave in response to user events depending on the settings selected. For example here are some of the different scenarios for the mouseover event:

  • When in Popup mode: popup shows over data point
  • When in Popup mode, with sticky content: nothing happens
  • When in Panel mode: nothing happens
  • When in Panel mode, Always show turned on: content loads in panel
  • When in Panel mode, Always show turned on, with sticky content: nothing happens
  • When in Both mode: Popup with preview content shows over data point

So for consistency this logic is abstracted from the template. This is why there is no method for actions such as opening a popup because instead we call popup.mouseover() and let the module look at all the different settings and decide what should happen as a result of that event.

All event based methods are listed below in the methods section but a common implementation will look something like this:

import { popup } from "./popup";

function updateGraphic() {
    d3.selectAll(...) // datapoints
        .on("mouseover", function() {
            const el = this;
            popup.mouseover(el, el.__data__);
        })
        .on("mouseout", function() {
            popup.mouseout();
        })
        .on("click", function() {
            const el = this;
            const data = el.__data__
            const locked_id = data.id
            popup.click(el, data, locked_id); // See step 8 for more information on locked_id
        });
}

6 - Making sure the popup displays the correct, formatted, data with .setColumnNames() and .setFormatters()

For each popup we want to make sure we're displaying the correct labels and formatted values from the data. There are two parts to making this work:

Part One - passing in the data

This happens as part of step 5 when passing data in to popup.click, popup.mouseover or popup.touch. You pass in the data that is bound to the node that you are interacting with. If you had the following data bindings: binding_one,binding_two, binding_three and binding_four the data on each data point (and therefore the data you would be passing to the popup module) would look something like this:

{
    binding_one: "Joe Biden",
    binding_two: "President",
    binding_three: "https://public.flourish.studio/uploads/ff3f9984-470c-4ed9-beb8-2a86bb7019ea.jpg",
    binding_four: "Democrat"
}

Part Two - setting the column names

Currently the popup has been passed a set of values that correlate to data bindings, we now have to set a column name for each data binding we wish to appear in the popup:

popup
    .setColumnNames({
        binding_one: "Name",
        binding_two: "Job title",
        binding_four: "Party"
    })
    .update()

Data will only show if we have set a column name for that data binding. We didnt set a column name for binding_three so the resulting information displayed in the popup would be:

Name: Joe Biden
Job title: President
Party: Democrat

If there are no columns that you wish to exclude you can pass in the column_names object from the Flourish dataset:

popup
    .setColumnNames(data.data.column_names)
    .update()

If there are columns you'd like to be available for custom content, but don't want to show in the default popup or panel content (eg. long series data), you can exclude them using .hideColumnNames(). This takes an array of binding names. In the above example, calling .hideColumnNames(["binding_four"]) will not show the Party information in the default popup or panel.

Part Three - setting the formatters

Optionally, you can also set formatters for each data binding. These must match the data bindings passed in .setColumnNames() but you do not need to provide a formatter for all bindings.

Formatters take two forms:

  • A function taking a value and returning a string. Any formatters generated by initNumberFormatter in @flourish/formatters should by passed like this so that formatting changes in the settings panel are reflected in the popup.
  • An object containing an output_format_id string property used in the [@flourish/interpreter] module. This is passed to @flourish/formatters to generate a formatter function.

For multi-column bindings you can pass in an array of formatters (where each formatter is a function or an object containing output_format_id).

popup
    .setColumnNames({
        binding_one: "Name",
        binding_two: "Cost",
        binding_three: "Sold", 
        binding_four: "Released"
    })
    .setFormatters({
        binding_two: d => `£${d}`,
        binding_three: { output_format_id: "number$comma_point" } 
        binding_four: { output_format_id: "datetime$%d/%m/%Y" },
    })
    .update()

If the data below was passed to the popup:

{
    binding_one: "Pain au chocolat",
    binding_two: 2,
    binding_three: 1235000,
    binding_four: new Date("2022-05-12T03:24:00")
}

The resulting information would be displayed in the popup:

Name: Pain au chocolat
Cost: £2
Sold: 1,235,000
Released: 05/12/2022

If you do not want to pass any custom formatter functions you can set formatters for all bindings by passing the metadata object for a dataset. This object includes entries with an output_format_id string property for each binding (these can be set by the user in the data panel).

popup
    .setColumnNames(data.data.column_names)
    .setFormatters(data.data.metadata)
    .update()

7 - Updating the popup with .update()

To make sure that the popup is using the latest settings, adds the correct content based on what's passed in via .setColumnNames(), we need to call popup.update() inside the template's update() loop.

8 - Set up locking functionality (optional)

Locked functionality is the ability to 'lock' a popup in an open state. A locked popup will remain open until clickout is triggered and while locked it will have CSS pointer events enabled, so that the end viewer can for example click a link inside the popup.

To set up locking functionality you need to define a getLockedPosition function. If there is a locked popup this function will retreive the locked node or coordinate information of the locked item, and the data that's associated with it. It returns an array: [node_or_coordinate, data]

This function needs only be called once so can be called straight after the popup is initialised, but can also be called as part of an update function.

popup.getLockedPosition(getLockedPositionCallback)

function getLockedPositionCallback(locked_id) {
    // get the node that relates to this id (this is just one common way you might do this)
    const el_node = select(`#${locked_id}`).node();

    // if there is no locked popup, or there is currently no element on the screen
    // corresponding to the stored locked popup return null
    if (!el_node) return null;

    // get the data from that node
    const datum = el_node && el_node.__data__;

    // return node and data
    return [el_node, datum];
}

Methods

Event-based methods

  • popup.click(coords_or_node, data, locked_id, callback) Used when the viewer clicks a data point. coords_or_node can be a coordinate array ([x, y]) or an DOM element. data is the data to display (usually the data attached to the element you are clicking). locked_id is an identifier for the clicked data point. If locked_id is undefined it wont be locked, if it is defined the value will be stored as the locked_id and passed to the getLockedPositionCallback function.

  • popup.mouseover(coords_or_node, data, callback) Used when the viewer mouseovers a data point. (Note: this doesn't take the locked_id argument since you can never lock a popup by mousing over a data point.)

  • popup.touch(coords_or_node, data, locked_id, callback) Used when the viewer is on a touch device and touches a data point. It has the same behavior as mouseover except that in "Both" mode it makes it possible to touch once to open a popup and then touch the popup to open the panel. (Hence it needs the locked_id argument since this second touch locks the panel open.)

  • popup.mouseout() Used when the viewer mouse leaves a data point. It closes or resets the popup or panel unless it is locked.

  • popup.clickout() Used when the viewer clicks on something that isnt a data point. It closes the popup if it's locked; typically used in a click handler for the background (e.g. an SVG or canvas element). Note: this method can make code look quite counterintuitive e.g:

          document.body.onclick = function() { popups.clickout(); };
    

    This is because to the browser you are clicking but to the popups you are clicking out (because you are clicking on something that isnt a data point).

Setting a title and subtitle

It's possible to specify that certain keys in the data represent the title and subtitle for the popup or panel. These appear in the header section of the popup with different styling from the rest of the popup.

  • popup.titleKey(data_binding_name)
  • popup.subtitleKey(data_binding_name)

Specifying a default template

You can specify a different template for the popup or panel content, for instance if you want to add an <img> tag or the content needs to be shown in a specific order. This is done when initializing:

  • popup.popupDefaultTemplate(template_string)
  • popup.panelDefaultTemplate(template_string)

The template_string can include data binding keys between curly brackets, such as <h1>{{name}}</h1> where name is your data binding.

Positional methods

  • popup.popupDirections(directions) – gets or sets the popup directions.
  • popup.margins() – gets the space on the visualisation edges being used for the panel. This is useful for when you don't want the panel to overlay over the content.

Hiding methods

  • popup.hidePopup() will hide the popup without resetting the locked_id.
  • popup.hidePanel() will hide the panel without resetting the locked_id.

Getter methods

  • popup.locked() – gets the current locked_id from the popup state. Returns null if there is currently no popup "locked" open.
  • popup.mode() – gets the current mode from the popup state.

Misc methods

  • popup.onPanelClose(fn) will fire when the panel gets closed

Adjusting which data bindings to show in the custom content setting

On default, all data bindings are used as little buttons below the custom content setting. You can change this by adding a setting override:

overrides:
      - property: [ popup_custom_main, popup_custom_header ]
        editor:
          style: true
          url: true
          flourish_embed: true
          bindings: [ dataset_name.databinding_name_1, dataset_name.databinding_name_2 ]

Templates to reference

Templates that use info-popups in a fairly straightforward way inculde:

A template that uses info-popups with canvas include:

For templates with multiple datasheets

If a template has multiple datasheets you will need to pass in the name of the datasheet that the info popup binding relates to. If it is not passed in the tests will use the first datasheet in the column_names object.

版本与发布记录

@flourish/info-popup 共发布 52 个版本,首次发布于 2020/07/29;过去 12 个月发布了 4 个版本。

版本发布日期距今
8.3.3latest2026/09/012 个月前
8.3.22026/05/285 个月前
8.3.12026/05/225 个月前
8.3.02026/03/267 个月前
8.2.02025/07/231.3 年前
8.1.32025/06/201.4 年前

关于 @flourish/info-popup 的常见问题

@flourish/info-popup 是什么?

Popup with data insertion

如何安装 @flourish/info-popup?

在项目目录运行 npm install @flourish/info-popup,或使用 pnpm add / yarn add / bun add。

@flourish/info-popup 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/flourish__info-popup 是否存在。

@flourish/info-popup 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@flourish/info-popup 可以商用吗?

@flourish/info-popup 使用 LicenseRef-LICENSE 许可。声明的许可为 LicenseRef-LICENSE,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

@flourish/info-popup 的下载量有多少?

根据 npm 官方下载统计,@flourish/info-popup 在 2026/10/15 – 2026/11/13 这 30 天内被下载 4,142 次,日均约 138 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@flourish/info-popup 还在维护吗?

最新版本 8.3.3 发布于 2026/09/01(2 个月前);至今共发布 52 个版本,其中过去 12 个月发布了 4 个;首次发布于 2020/07/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。