vega / vega

A visualization grammar.

Home Page:https://vega.github.io/vega

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Change cursor style when hovering over interactive legends to indicate that they are clickable

joelostblom opened this issue · comments

It would be helpful to indicate that interactive legends are clickable, e.g. by changing the cursor style to the "click-hand" by default.

Related to vega/vega-lite#4155 and vega/vega-lite#9358

Why is this a Vega issue? This is already supported by Vega. e.g.
image


{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "background": "white",
  "padding": 5,
  "width": 300,
  "height": 200,
  "style": "cell",
  "data": [
    {"name": "industry_store"},
    {
      "name": "source_0",
      "url": "data/unemployment-across-industries.json",
      "format": {"type": "json", "parse": {"date": "date"}},
      "transform": [
        {
          "field": "date",
          "type": "timeunit",
          "units": ["year", "month"],
          "as": ["yearmonth_date", "yearmonth_date_end"]
        },
        {
          "type": "aggregate",
          "groupby": ["yearmonth_date", "series"],
          "ops": ["sum"],
          "fields": ["count"],
          "as": ["sum_count"]
        },
        {
          "type": "impute",
          "field": "sum_count",
          "groupby": ["series"],
          "key": "yearmonth_date",
          "method": "value",
          "value": 0
        },
        {
          "type": "stack",
          "groupby": ["yearmonth_date"],
          "field": "sum_count",
          "sort": {"field": ["series"], "order": ["descending"]},
          "as": ["sum_count_start", "sum_count_end"],
          "offset": "center"
        }
      ]
    }
  ],
  "signals": [
    {
      "name": "unit",
      "value": {},
      "on": [
        {"events": "pointermove", "update": "isTuple(group()) ? group() : unit"}
      ]
    },
    {
      "name": "industry_series_legend",
      "value": null,
      "on": [
        {
          "events": [
            {
              "source": "view",
              "type": "click",
              "markname": "series_legend_symbols"
            },
            {
              "source": "view",
              "type": "click",
              "markname": "series_legend_labels"
            },
            {
              "source": "view",
              "type": "click",
              "markname": "series_legend_entries"
            }
          ],
          "update": "isDefined(datum.value) ? datum.value : item().items[0].items[0].datum.value",
          "force": true
        },
        {
          "events": [{"source": "view", "type": "click"}],
          "update": "!event.item || !datum ? null : industry_series_legend",
          "force": true
        }
      ]
    },
    {
      "name": "industry",
      "update": "vlSelectionResolve(\"industry_store\", \"union\", true, true)"
    },
    {
      "name": "industry_tuple",
      "update": "industry_series_legend !== null ? {fields: industry_tuple_fields, values: [industry_series_legend]} : null"
    },
    {
      "name": "industry_tuple_fields",
      "value": [{"type": "E", "field": "series"}]
    },
    {
      "name": "industry_toggle",
      "value": false,
      "on": [
        {
          "events": {"merge": [{"source": "view", "type": "click"}]},
          "update": "event.shiftKey"
        }
      ]
    },
    {
      "name": "industry_modify",
      "on": [
        {
          "events": {"signal": "industry_tuple"},
          "update": "modify(\"industry_store\", industry_toggle ? null : industry_tuple, industry_toggle ? null : true, industry_toggle ? industry_tuple : null)"
        }
      ]
    }
  ],
  "marks": [
    {
      "name": "pathgroup",
      "type": "group",
      "from": {
        "facet": {
          "name": "faceted_path_main",
          "data": "source_0",
          "groupby": ["series"]
        }
      },
      "encode": {
        "update": {
          "width": {"field": {"group": "width"}},
          "height": {"field": {"group": "height"}}
        }
      },
      "marks": [
        {
          "name": "marks",
          "type": "area",
          "style": ["area"],
          "sort": {"field": "datum[\"yearmonth_date\"]"},
          "interactive": true,
          "from": {"data": "faceted_path_main"},
          "encode": {
            "update": {
              "orient": {"value": "vertical"},
              "fill": {"scale": "color", "field": "series"},
              "opacity": [
                {
                  "test": "!length(data(\"industry_store\")) || vlSelectionTest(\"industry_store\", datum)",
                  "value": 1
                },
                {"value": 0.2}
              ],
              "description": {
                "signal": "\"date (year-month): \" + (timeFormat(datum[\"yearmonth_date\"], '%Y')) + \"; Sum of count: \" + (format(datum[\"sum_count\"], \"\")) + \"; series: \" + (isValid(datum[\"series\"]) ? datum[\"series\"] : \"\"+datum[\"series\"])"
              },
              "x": {"scale": "x", "field": "yearmonth_date"},
              "y": {"scale": "y", "field": "sum_count_end"},
              "y2": {"scale": "y", "field": "sum_count_start"},
              "defined": {
                "signal": "isValid(datum[\"yearmonth_date\"]) && isFinite(+datum[\"yearmonth_date\"]) && isValid(datum[\"sum_count\"]) && isFinite(+datum[\"sum_count\"])"
              }
            }
          }
        }
      ]
    }
  ],
  "scales": [
    {
      "name": "x",
      "type": "time",
      "domain": {"data": "source_0", "field": "yearmonth_date"},
      "range": [0, {"signal": "width"}]
    },
    {
      "name": "y",
      "type": "linear",
      "domain": {
        "data": "source_0",
        "fields": ["sum_count_start", "sum_count_end"]
      },
      "range": [{"signal": "height"}, 0],
      "nice": true,
      "zero": true
    },
    {
      "name": "color",
      "type": "ordinal",
      "domain": {"data": "source_0", "field": "series", "sort": true},
      "range": {"scheme": "category20b"}
    }
  ],
  "axes": [
    {
      "scale": "x",
      "orient": "bottom",
      "gridScale": "y",
      "grid": true,
      "tickCount": {"signal": "ceil(width/40)"},
      "tickMinStep": {
        "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)"
      },
      "domain": false,
      "labels": false,
      "aria": false,
      "maxExtent": 0,
      "minExtent": 0,
      "ticks": false,
      "zindex": 0
    },
    {
      "scale": "x",
      "orient": "bottom",
      "grid": false,
      "title": "date (year-month)",
      "domain": false,
      "format": "%Y",
      "tickSize": 0,
      "labelFlush": true,
      "labelOverlap": true,
      "tickCount": {"signal": "ceil(width/40)"},
      "tickMinStep": {
        "signal": "datetime(2001, 1, 1, 0, 0, 0, 0) - datetime(2001, 0, 1, 0, 0, 0, 0)"
      },
      "zindex": 0
    }
  ],
  "legends": [
    {
      "fill": "color",
      "symbolType": "circle",
      "title": "series",
      "encode": {
        "labels": {
          "name": "series_legend_labels",
          "interactive": true, 
          "update": {  "cursor": {"value": "pointer"},
            "opacity": [
              {
                "test": "(!length(data(\"industry_store\")) || (industry[\"series\"] && indexof(industry[\"series\"], datum.value) >= 0))",
                "value": 1
              },
              {"value": 0.35}
            ]
          }
        },
        "symbols": {
          "name": "series_legend_symbols",
          "interactive": true,
          "update": {"cursor": {"value": "pointer"},
            "opacity": [
              {
                "test": "(!length(data(\"industry_store\")) || (industry[\"series\"] && indexof(industry[\"series\"], datum.value) >= 0))",
                "value": 1
              },
              {"value": 0.35}
            ]
          }
        },
        "entries": {
          "name": "series_legend_entries",
          "interactive": true,
          "update": {"fill": {"value": "transparent"}}
        }
      }
    }
  ]
}

Thanks for sharing that example @PBI-David . @domoritz you mention in vega/vega-lite#9358 (comment) that there is something in Vega we would need to fix before introducing this in Vega-Lite. Can you elaborate on what that would be or would the approach above be possible to add to Vega-Lite "as is" to make the legends indicate that they are clickable by default?