Skip to content

Commit

Permalink
fix(analytics): hover state is not applied on serie's button
Browse files Browse the repository at this point in the history
- Update CustomSeriesButtons component to toggle the visibility of series buttons for a Highcharts chart
- Add useEffect hook to update series visibility based on buttonsVisibility state
- Add toggleSeriesVisibility function to toggle the buttonsVisibility state
- Update SeriesButton component to support onMouseEnter and onMouseLeave events
- Add toggleState prop to SeriesButton component to control whether the button toggles visibility on click
- Update propTypes for CustomSeriesButtons and SeriesButton components
- Add ChartRefProperty type definition to types.js
  • Loading branch information
jalezi committed Oct 20, 2024
1 parent b928100 commit a9ccdc6
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 23 deletions.
80 changes: 62 additions & 18 deletions src/pages/Analytics/CustomSeriesButtons/index.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
/** @import * as Types from "../types" */

import PropTypes from 'prop-types';
import { useEffect, useState } from 'react';

import SeriesButton from '../SeriesButton';

/**
* CustomSeriesButtons component renders a list of series buttons for a Highcharts chart.
* The buttons allow the user to toggle the visibility of each series.
* @component
* @param {Object} props - The properties object.
* @param {Types.ChartRefProperty} props.chart - The Highcharts chart instance.
* @returns {JSX.Element} The rendered CustomSeriesButtons component.
* @example
* return <CustomSeriesButtons chart={chartRef} />;
*/
const CustomSeriesButtons = function CustomSeriesButtons({ chart }) {
const [buttonsVisibility, setButtonsVisibility] = useState(true);

// eslint-disable-next-line consistent-return
useEffect(() => {
chart?.series.forEach(series => {
series.setVisible(buttonsVisibility);
});
}, [buttonsVisibility, chart]);

if (!chart) {
return null;
}
Expand All @@ -12,22 +35,44 @@ const CustomSeriesButtons = function CustomSeriesButtons({ chart }) {
return null;
}

// eslint-disable-next-line arrow-body-style
return seriesLabelsToShow.map((series, index) => {
return (
<SeriesButton
key={series?.name}
onClick={() => {
chart.series[index].setVisible(!chart.series[index].visible);
}}
visible={chart?.series[index]?.visible ?? true}
color={chart?.series[index]?.color}
borderColor={chart?.series[index]?.color}
>
{series.name}
const toggleSeriesVisibility = () => {
setButtonsVisibility(prev => !prev);
};

// // eslint-disable-next-line arrow-body-style
return (
<>
{seriesLabelsToShow.map((series, index, arr) => (
<SeriesButton
key={`${series?.name}${buttonsVisibility}`}
onClick={() => {
chart.series[index].setVisible(!chart.series[index].visible);
}}
onMouseEnter={() => {
series.setState('hover');
arr.forEach((s, i) => {
if (i !== index) {
s.setState('inactive');
}
});
}}
onMouseLeave={() => {
arr.forEach(s => {
s.setState('normal');
});
}}
visible={buttonsVisibility}
color={chart?.series[index]?.color}
borderColor={chart?.series[index]?.color}
>
{series.name}
</SeriesButton>
))}
<SeriesButton type="button" onClick={toggleSeriesVisibility} toggleState={false}>
{buttonsVisibility ? 'Skrij vse' : 'Pokaži vse'}
</SeriesButton>
);
});
</>
);
};

CustomSeriesButtons.propTypes = {
Expand All @@ -38,11 +83,10 @@ CustomSeriesButtons.propTypes = {
visible: PropTypes.bool,
color: PropTypes.string,
setVisible: PropTypes.func,
// eslint-disable-next-line react/forbid-prop-types
group: PropTypes.object,
}),
),
fullscreen: PropTypes.shape({
open: PropTypes.func,
}),
}).isRequired,
};

Expand Down
21 changes: 16 additions & 5 deletions src/pages/Analytics/SeriesButton/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,44 @@ import styles from './SeriesButton.module.css';
*
* @param {Object} props - The properties object.
* @param {Function} props.onClick - The function to call when the button is clicked.
* @param {Function} [props.onMouseEnter] - The function to call when the mouse enters the button.
* @param {Function} [props.onMouseLeave] - The function to call when the mouse leaves the button.
* @param {boolean} props.visible - The initial visibility state of the button.
* @param {React.ReactNode} props.children - The content to be displayed inside the button.
* @param {string} [props.className=''] - Additional CSS class names to apply to the button.
* @param {string} [props.color='inherit'] - The color of the button text.
* @param {string} [props.toggleState] - The button will not toggle state on click; It will keep the visibility state as value of visible prop.
*
* @returns {JSX.Element} The rendered button component.
*/
const SeriesButton = function SeriesButton({
onClick,
visible,
onMouseEnter = () => {},
onMouseLeave = () => {},
visible = true,
children,
className = '',
color = 'inherit',
borderColor = 'inherit',
toggleState = true,
}) {
const ref = useRef(null);
const [isVisible, setIsVisible] = useState(visible);

const onNeki = () => {
setIsVisible(!isVisible);
const toggleVisibility = () => {
if (toggleState) setIsVisible(!isVisible);
onClick();
};

return (
<button
ref={ref}
type="button"
onClick={onNeki}
onClick={toggleVisibility}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
className={`${styles.SeriesButton} ${className}`}
data-visible={isVisible}
data-visible={toggleState ? isVisible : undefined}
style={{
color: isVisible ? color : '#666666',
borderColor: isVisible ? borderColor : '#666666',
Expand All @@ -51,11 +59,14 @@ const SeriesButton = function SeriesButton({

SeriesButton.propTypes = {
onClick: PropTypes.func.isRequired,
onMouseEnter: PropTypes.func,
onMouseLeave: PropTypes.func,
visible: PropTypes.bool.isRequired,
children: PropTypes.node.isRequired,
color: PropTypes.string,
borderColor: PropTypes.string,
className: PropTypes.string,
toggleState: PropTypes.bool,
};

export default SeriesButton;
4 changes: 4 additions & 0 deletions src/pages/Analytics/types.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @typedef {import('highcharts-react-official').HighchartsReactRefObject["chart"]} ChartRefProperty
*/

/**
* @typedef {import('highcharts').Options} HighchartsOptions
*/
Expand Down

0 comments on commit a9ccdc6

Please sign in to comment.