nteract / semiotic

A data visualization framework combining React & D3
https://semioticv1.nteract.io/
Other
2.43k stars 133 forks source link

Is there a way to pass a function to legend items and make them interactive? #535

Closed bengarvey closed 3 years ago

bengarvey commented 3 years ago

Working on a force directed graph and I'd love to be able to click a legend item and have it toggle that type of edge on or off. Is there way to pass in a function to do that? Ideally something like this:

let legendGroups = [ 
  { type: 'line',
    styleFn: d => (
      { stroke: d.color,
        strokeOpacity: 0.5,
        strokeWidth: "3px"
      }), 
    items: [
      { label: "Ancestor", color: colors.ancestor, onClick: {() => this.toggleRelationship('ancestor')} },
      { label: "Trained", color: colors.trained, onClick: {() => this.toggleRelationship('trained')}  },
      { label: "Killed", color: colors.killed, onClick: {() => this.toggleRelationship('killed')}  },
    ]   
  }
]
hydrosquall commented 3 years ago

From the looks of it such a property doesn't currently exist

https://github.com/nteract/semiotic/blob/d79503d7b90f25b6776c7b3e957ba3a12c87b1c5/src/components/types/legendTypes.tsx#L5-L7

However, I think I have an idea about where to add this. My suggestion would be to make the group itself take the customClickBehavior handler (for consistency with other parts of this library, e.g. https://semiotic.nteract.io/api/xyframe#customclickbehavior--function- ), and pass a reference to the clicked item in the callback, e.g. in your example:

let legendGroups = [ 
  { type: 'line',
    styleFn: d => (
      { stroke: d.color,
        strokeOpacity: 0.5,
        strokeWidth: "3px"
      }),
    customClickBehavior: d => { this.toggleRelationship(d.value) } ,
    items: [
      { label: "Ancestor", color: colors.ancestor, value: 'ancestor' } },
      { label: "Trained", color: colors.trained, value: 'trained' }  },
      { label: "Killed", color: colors.killed, value: 'killed' )}  },
    ]   
  }
]

What do you think, @emeeks ?

emeeks commented 3 years ago

I would simply pass d but otherwise yes I think this is good functionality to add to the legend. It would be nice if it had hover behavior, too but I worry about how that might cause issues with rerendering. Feel free to start a PR and I would be happy to give more feedback.

hydrosquall commented 3 years ago

As an aside, I'm surprised that people have been able to find the Legend as I don't see it documented on the public docs. If such a page were to be created, would it go into the "main" or "sub" components section?

*Edit: I see https://github.com/nteract/semiotic/blob/edff26a8e2f497fa298ae754be73edd1f69a931d/src/docs/Documentation.js#L135, but I'm not sure why I don't see it in the navbar of the public site.

**Second edit: I realized after running yarn start that the public docs build from semiotic-docs, so the presence of docs pages in this repo doesn't mean there will be content at https://semiotic.nteract.io/. I realized belatedly that I had filed this a year ago, and that Legend is on the list of items to port over :)

https://github.com/nteract/semiotic-docs/issues/17

emeeks commented 3 years ago

@bengarvey & @hydrosquall I finally managed to carve out some time, so sorry about how long it took. Take a look at 1.20.6 and see if it works for you.