Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
@vx/tooltip
Advanced tools
The @vx/tooltip
package provides utilities for making it easy to add Tooltip
s to a visualization
and includes hooks, higher-order component (HOC) enhancers, and Tooltip components.
npm install --save @vx/tooltip
This package provides two ways to add tooltip state logic to your chart components:
useTooltip()
withTooltip()
The useTooltip
hook is the recommended way to add tooltip state logic to your components, but can
only be used in functional components. The withTooltip
HOC can be used with both functional and
class components, and is the recommended way to add tooltip state logic to class components.
Both useTooltip
and withTooltip
expose the same values and functions for use in your component:
Name | Type | Description |
---|---|---|
showTooltip | func | Call this function with the signature func({ tooltipData, tooltipLeft, tooltipTop }) to set the tooltip state to the specified values. |
hideTooltip | func | Call this function to close a tooltip, i.e., set the showTooltip state to false . |
tooltipOpen | bool | Whether the tooltip state is open or closed |
tooltipLeft | number | The tooltipLeft position passed to the showTooltip func, intended to be used for tooltip positioning |
tooltipTop | number | The tooltipTop position passed to the showTooltip func, intended to be used for tooltip positioning |
tooltipData | any | The tooltipData value passed to the showTooltip func, intended to be used for any data that your tooltip might need to render |
updateTooltip | func | Call this function with the signature func({ tooltipOpen, tooltipLeft, tooltipTop, tooltipData }) to set the tooltip state to the specified values. |
In the case of useTooltip
, these will be returned from the useTooltip()
call in your component.
In the case of withTooltip
, they will be passed as props to your wrapped component. Refer to the
Examples section for a basic demo of each approach.
If you would like to add tooltip state logic to a functional component, you may use the
useTooltip()
hook which will return an object with several properties that you can use to manage
the tooltip state of your component. For correct tooltip positioning, it is important to wrap your
component in an element (e.g., div
) with relative
positioning. This is handled for you by the
withTooltip
HOC, but not with the useTooltip()
hook.
If you would like to add tooltip state logic to a class component, you may wrap it in
withTooltip(BaseComponent [, containerProps [, renderContainer])
.
The HOC will wrap your component in a div
with relative
positioning by default and handle state
for tooltip positioning, visibility, and content by injecting the following props into your
BaseComponent
:
You may override the container by specifying containerProps
as the second argument to
withTooltip
, or by specifying renderContainer
as the third argument to withTooltip
.
Tooltip components render tooltip state and can be used in conjunction with useTooltip
and
withTooltip
above.
This is a simple Tooltip container component meant to be used to actually render a Tooltip. It accepts the following props, and will spread any additional props on the tooltip container div (i.e., ...restProps):
Name | Type | Default | Description |
---|---|---|---|
left | number or string | -- | Sets style.left of the tooltip container |
top | number or string | -- | Sets style.top of the tooltip container |
className | string | -- | Adds a class (in addition to vx-tooltip-portal ) to the tooltip container |
style | object | -- | Sets / overrides any styles on the tooltip container (including top and left) |
children | node | -- | Sets the children of the tooltip, i.e., the actual content |
unstyled | bool | true | Whether the tooltip should use styles from the style prop or not |
This tooltip component is exactly the same as Tooltip
above, but it is aware of its boundaries
meaning that it will flip left/right and bottom/top based on whether it would overflow its parent's
boundaries. It accepts the following props, and will spread any additional props on the Tooltip
component (i.e., ...restProps):
Name | Type | Default | Description |
---|---|---|---|
left | number | -- | The horizontal position of the cursor, tooltip will be place to the left or right of this coordinate depending on the width of the tooltip and the size of the parent container. |
top | number | -- | The vertical position of the cursor, tooltip will be place to the bottom or top of this coordinate depending on the height of the tooltip and the size of the parent container. |
offsetLeft | number | 10 | Horizontal offset of the tooltip from the passed left value, functions as a horizontal padding. |
offsetRight | number | 10 | Vertical offset of the tooltip from the passed top value, functions as a vertical padding. |
style | object | -- | Sets / overrides any styles on the tooltip container (including top and left) |
children | node | -- | Sets the children of the tooltip, i.e., the actual content |
unstyled | bool | true | Whether the tooltip should use styles from the style prop or not |
Note that this component is positioned using a transform
, so overriding left
and top
via
styles may have no effect.
ResizeObserver
dependencyThis hook relies on ResizeObserver
s. If you need a polyfill, you can either polute the window
object or inject it cleanly using the polyfill
config option below.
useTooltipInPortal
is a hook which gives you a TooltipInPortal
component for rendering Tooltip
or TooltipWithBounds
in a Portal
, outside of your component DOM tree which can be useful in many
circumstances (see below for more on Portal
s).
type Options = {
/** whether TooltipWithBounds should be used to auto-detect (page) boundaries and reposition itself. */
detectBounds?: boolean;
/** Debounce resize or scroll events in milliseconds (needed for positioning) **/
debounce?: number | { scroll: number; resize: number }
/** React to nested scroll changes, don't use this if you know your view is static */
scroll?: boolean
/** You can optionally inject a resize-observer polyfill */
polyfill?: { new (cb: ResizeObserverCallback): ResizeObserver }
}
useTooltipInPortal(
options: Options = { debounce: 0, scroll: true, detectBounds: true }
): {
/** Set `ref={containerRef}` on the element corresponding to the coordinate system that `left/top` (passed to `TooltipInPortal`) are relative to. */
containerRef: React.MutableRefObject<HTMLElement | SVGElement>;
/** Access to the container's bounding box if useful to you. This will be empty on first render. */
containterBounds: RectReadOnly;
/** React.FunctionComponent<TooltipProps> with the same API as Tooltip, which will be rendered in a Portal. */
TooltipInPortal ({ top: containerTop, left: containerLeft, ...tooltipProps }: TooltipProps) => ReactNode;
interface RectReadOnly {
readonly x: number
readonly y: number
readonly width: number
readonly height: number
readonly top: number
readonly right: number
readonly bottom: number
readonly left: number
}
Portal
is a component which simply renders its children inside a div
element appended to
document.body
created by ReactDOM
. A Portal
can be an effective strategy for solving the
(z-index
stacking context
problem)[rg/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context] for
Tooltip
s.
For example, if your chart is rendered inside a stacking context with a lower z-index
than a
surrounding container, it may get clipped by that container even if you specify a higher z-index
.
This is solvable with a Portal
because the separate container will not be subject to the stacking
context of your chart.
To use a Portal
, simply pass your Tooltip
as a child: <Portal><Tooltip {...} /></Portal>
. You
will also need to correct the left
and top
positions to be in page coordinates, not the
coordinates of your container which you would use when not using a Portal
. If reacting to a
mouse event, you can use event.pageX/Y
. Alternatively, if you have container coordinates, you can
convert them to page coordinates using the following (note: useTooltipInPortal
does handles this
for you):
const pageX = containerX + containerBoundingBox.left + window.scrollLeft;
const pageY = containerY + containerBoundingBox.top + window.scrollTop;
import { useTooltip, useTooltipInPortal, TooltipWithBounds } from '@vx/tooltip';
import { localPoint } from '@vx/event';
const ChartWithTooltip = () => {
const {
tooltipData,
tooltipLeft,
tooltipTop,
tooltipOpen,
showTooltip,
hideTooltip,
} = useTooltip();
// If you don't want to use a Portal, simply replace `TooltipInPortal` below with
// `Tooltip` or `TooltipWithBounds` and remove `containerRef`
const { containerRef, TooltipInPortal } = useTooltipInPortal({
// use TooltipWithBounds
detectBounds: true,
// when tooltip containers are scrolled, this will correctly update the Tooltip position
scroll: true,
})
const handleMouseOver = (event, datum) => {
const coords = localPoint(event.target.ownerSVGElement, event);
showTooltip({
tooltipLeft: coords.x,
tooltipTop: coords.y,
tooltipData: datum
});
};
return (
// Set `ref={containerRef}` on the element corresponding to the coordinate system that
// `left/top` (passed to `TooltipInPortal`) are relative to.
<>
<svg ref={containerRef} width={...} height={...}>
// Chart here...
<SomeChartElement
onMouseOver={this.handleMouseOver}
onMouseOut={hideTooltip}
/>
</svg>
{tooltipOpen && (
<TooltipInPortal
// set this to random so it correctly updates with parent bounds
key={Math.random()}
top={tooltipTop}
left={tooltipLeft}
>
Data value <strong>{tooltipData}</strong>
</TooltipInPortal>
)}
</>
)
};
render(<ChartWithTooltip />, document.getElementById("root"));
import { withTooltip, TooltipWithBounds } from '@vx/tooltip';
import { localPoint } from '@vx/event';
class Chart extends React.Component {
handleMouseOver = (event, datum) => {
const coords = localPoint(event.target.ownerSVGElement, event);
this.props.showTooltip({
tooltipLeft: coords.x,
tooltipTop: coords.y,
tooltipData: datum
});
};
render() {
const {
tooltipData,
tooltipLeft,
tooltipTop,
tooltipOpen,
hideTooltip
} = this.props;
return (
// note React.Fragment is only available in >= react@16.2
<React.Fragment>
<svg width={...} height={...}>
// Chart here...
<SomeChartElement onMouseOver={this.handleMouseOver} onMouseOut={hideTooltip} />
</svg>
{tooltipOpen && (
<TooltipWithBounds
// set this to random so it correctly updates with parent bounds
key={Math.random()}
top={tooltipTop}
left={tooltipLeft}
>
Data value <strong>{tooltipData}</strong>
</TooltipWithBounds>
)}
</React.Fragment>
);
}
}
const ChartWithTooltip = withTooltip(Chart);
render(<ChartWithTooltip />, document.getElementById("root"));
Example codesandbox here.
v0.0.199
rangeRound
field in the input of scaleLinear()
, scaleLog()
, scalePoint()
, scalePower()
, scaleSqrt()
, scaleTime()
and scaleUtc()
. #766
Instead of
scaleLinear({ rangeRound: xxx })
Do this instead
scaleLinear({ range: xxx, round: true });
ticks
and tickFormat
in the input of scaleQuantize()
. It was not really doing anything anyway as both scale.ticks()
and scale.tickFormat()
do not mutate the scale. #766scale.type
field that was attached to the d3 scales. #766@vx/grid
components now accept D3 Scale as generic type instead of ScaleInput
. Developers should not expect to specify this generic type as it can be inferred from the passed scale. #775GridColumnProps
=> GridColumnsProps
(+s
) to match GridRowsProps
. #787<Marker />
implementation of a Line and some Text. #783AnyD3Scale
, InferD3ScaleOutput
, InferD3ScaleDiscreteInput
, InferD3ScaleThresholdInput
and ScaleInput
. Add new utilities functions: getTicks
, coerceNumber
and toString
. #773@vx/legend
shapes from the index
for convenience / non-deep imports. #772children
prop to GridRows
+ GridColumns
to support animated rendering. #787<BarRounded />
shape. #774d3-shape
and export as part of vx/shape
(arc
, area
, line
, pie
, radialLine
),
similar to vx/scale
has factories for d3-scale
. #776SplitLinePath
component to @vx/shape
that allows you to create a line path split into multiple smaller line paths that can be styled independently. #778vx/scale
and vx/axis
. More fields passed to child render props of Axis
. #773Axis
is refactored to accept a ticksComponent
which allows us to animate them. #779values
to tickFormat(value, index, values)
so that format logic can more easily leverage all ticks (because numTicks
is approximate, lib consumers do not know how many tick values exist a priori). #779<Marker />
that matches actual SVG <marker>
. #783<MarkerArrow />
, <MarkerCross />
, <MarkerX />
, <MarkerCircle />
, <MarkerLine />
. #783@vx/react-spring
that includes react-spring
as a peerDep
and can be a home for things that depend on react-spring
. #779<AnimatedAxis />
and <AnimatedTicksRender />
in @vx/react-spring
. #779vx-demo/axis
demo to use <AnimatedAxis />
. #779AnimatedGridRows
+ AnimatedGridColumns
. #787AnimatedTicks/useAnimatedTicksConfig
to spring-configs/useAnimatedLineTransitionConfig
so it can power both animated tick + grid lines. #787animationTrajectory=outside | inside | min | max
to AnimatedAxis
and AnimatedGridRows/Columns
. #787enableDebounceLeadingCall
prop being passed into div
. #763vx/scale
package has 100% test coverage. #766<Marker>
. #783/axis
demo to include AnimatedGrid*
and a animationTrajectory
config. #787 - @vx/annotation: 0.0.198 => 0.0.199
- @vx/axis: 0.0.198 => 0.0.199
- @vx/bounds: 0.0.198 => 0.0.199
- @vx/brush: 0.0.198 => 0.0.199
- @vx/chord: 0.0.198 => 0.0.199
- @vx/clip-path: 0.0.198 => 0.0.199
- @vx/curve: 0.0.198 => 0.0.199
- @vx/demo: 0.0.198 => 0.0.199
- @vx/drag: 0.0.198 => 0.0.199
- @vx/event: 0.0.198 => 0.0.199
- @vx/geo: 0.0.198 => 0.0.199
- @vx/glyph: 0.0.198 => 0.0.199
- @vx/gradient: 0.0.198 => 0.0.199
- @vx/grid: 0.0.198 => 0.0.199
- @vx/group: 0.0.198 => 0.0.199
- @vx/heatmap: 0.0.198 => 0.0.199
- @vx/hierarchy: 0.0.198 => 0.0.199
- @vx/legend: 0.0.198 => 0.0.199
- @vx/marker: 0.0.198 => 0.0.199
- @vx/mock-data: 0.0.198 => 0.0.199
- @vx/network: 0.0.198 => 0.0.199
- @vx/pattern: 0.0.198 => 0.0.199
- @vx/point: 0.0.198 => 0.0.199
- @vx/react-spring: 0.0.198 => 0.0.199
- @vx/responsive: 0.0.198 => 0.0.199
- @vx/scale: 0.0.198 => 0.0.199
- @vx/shape: 0.0.198 => 0.0.199
- @vx/stats: 0.0.198 => 0.0.199
- @vx/text: 0.0.198 => 0.0.199
- @vx/threshold: 0.0.198 => 0.0.199
- @vx/tooltip: 0.0.198 => 0.0.199
- @vx/voronoi: 0.0.198 => 0.0.199
- @vx/vx: 0.0.198 => 0.0.199
- @vx/xychart: 0.0.0 => 0.0.199 (private)
- @vx/zoom: 0.0.198 => 0.0.199
FAQs
vx tooltip
The npm package @vx/tooltip receives a total of 76,917 weekly downloads. As such, @vx/tooltip popularity was classified as popular.
We found that @vx/tooltip demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.