FIREFLY-2033: React Component Library for Firefly Visualizations#1970
FIREFLY-2033: React Component Library for Firefly Visualizations#1970loitly wants to merge 1 commit into
Conversation
robyww
left a comment
There was a problem hiding this comment.
Summary
Overall it looks really good. There are so many files here it is hard to take it all in. These are my initial comments.
Things I really like
- The storybook demo and documentation is pretty cool. This will really help.
- The components in general and how easily usable they are.
- The npm packages though I doin't have my head around it all yet.
- A clear way to add more components.
Things I don't yet understand
- the role of vite?
- Rollup bundling? are we using rollup?
- should be replace webpack with vite in general?
- Are out input component working with html forms?. I think they are going to have to.
Comments
- How about the default chart?
- image, table, and chart components need to take arrays for url or request
- It is often more readable to
import {string,bool,object,etc} from prop-typesinstead of using PropTypes.bool etc.
|
|
||
| import Enum from 'enum'; | ||
|
|
||
| // ─── From ImagePlotCntlr.js ────────────────────────────────────────────────── |
There was a problem hiding this comment.
Glad you did this. I have been meaning to for a lone time.
| </Tab> | ||
| <Tab key='ImageSearchBlue' name='blue' label={<div style={{width:40, color:'blue'}}>Blue</div>}> | ||
| <SingleChannel {...{key: FG_KEYS.blue, groupKey: FG_KEYS.blue, imageMasterData, multiSelect, archiveName, noScroll}}/> | ||
| <SingleChannel key={FG_KEYS.blue} {...{groupKey: FG_KEYS.blue, imageMasterData, multiSelect, archiveName, noScroll}}/> |
There was a problem hiding this comment.
why did you have to break this up like this? was it not picking up the key?
There was a problem hiding this comment.
In React 19, key is now treated as a regular prop. However, because object spread operations pass the key as generic data rather than an explicit structural identifier, it bypasses React's Virtual DOM tracking engine, causing React 19 to trigger a runtime warning.
| <Stack {...{width:1, height:1, flexWrap:'nowrap', alignItems:'stretch'}}> | ||
| <Stack {...{flex: '1 1 auto', direction:'row'}}> | ||
| <ImageExpandedMode {...{key:'results-plots-expanded', closeFunc, viewerId}}/> | ||
| <ImageExpandedMode key='results-plots-expanded' {...{closeFunc, viewerId}}/> |
There was a problem hiding this comment.
see as below, why break it up?
| setRootURL(serverUrl); | ||
| return firefly.bootstrap({}, { serverUrl, ...appOptions }); |
There was a problem hiding this comment.
The first line should probably be
if (window?.firefly?.initialized) return Promise.resolve(); firefly.bootstrap does do this but I don't think we want to call setRootUrl twice.
|
|
||
| // ─── Utils ─────────────────────────────────────────────────────────────────── | ||
|
|
||
| export * from 'firefly/visualize/VisUtil.js'; |
There was a problem hiding this comment.
I am not totally sure if this is necessary. However, I am sure PlotViewUtil.js should be exported. Actually there is a lot, we need to think about it. An attempt at this is ApiUtilImage.jsx
There was a problem hiding this comment.
Sure, we can selectively export only those we want to publish.
| * - **Full-screen expand**: expand the image to fill the viewport. | ||
| * - **Advanced requests**: supply a `WebPlotRequest` for service-based or workspace images. | ||
| */ | ||
| export function ImagePlot({ plotId: plotId_prop, viewerId: viewerId_prop, url, request, sx }) { |
There was a problem hiding this comment.
we probably need to all url and request properties to optionally be an array.
There was a problem hiding this comment.
Ok. We'll handle this in a separate ticket.
| __PROPS__: { | ||
| BUILD_ENV: JSON.stringify('dev'), | ||
| SCRIPT_NAME: JSON.stringify([]), | ||
| MODULE_NAME: JSON.stringify('firefly-component-library'), | ||
| MIN_SAFARI_VERSION: '17', | ||
| MIN_CHROME_VERSION: '130', | ||
| MIN_FIREFOX_VERSION: '134', | ||
| MIN_EDGE_VERSION: '130', |
There was a problem hiding this comment.
This was hard-coded in webpack. I'll try to move them into configurable props.
| <Card {...{ | ||
| color:'warning', variant:'soft', position:'relative', | ||
| zIndex: maskShowing ? 10 : 'auto', | ||
| color:'warning', variant:'soft', |
There was a problem hiding this comment.
how did you decide the zIndex was not necessary?
There was a problem hiding this comment.
Since position and zIndex are not defined properties of Card, and the statusTextSx property in the next line (line 90) defines and overrides them, they should be removed.
There was a problem hiding this comment.
I second this, I noticed it when using BGMaskPanel for image type job results.
|
|
||
| **Storybook performance.** `@storybook/react-vite` serves stories through Vite's native ES module dev server. Each story loads only its own imports on demand, so the dev server starts immediately and individual stories load in milliseconds. A webpack-based Storybook must build an upfront bundle before any story can render, which in this codebase produces a 9+ MB bundle. | ||
|
|
||
| **Inline Web Worker.** Firefly loads one of its workers using webpack's `worker-loader` import convention. Vite handles the equivalent case natively via the `?worker&inline` query suffix. A small transform plugin in `vite.config.js` rewrites the webpack-style import to the Vite form, keeping the Firefly source unchanged while making the worker work correctly in the library build. |
There was a problem hiding this comment.
webpack is advising a change in how this is done. I was going to look into it. I wonder if it will break something.
|
More Comments:
|
React component library wrapping Firefly's table, chart, and image visualization components for use as a standalone npm package. Includes Storybook for interactive development and documentation.
8923eeb to
02f3ee6
Compare
Use
I'll look to add this into this PR.
This is uncommon for a library but we can add it if you like. |
jaladh-singhal
left a comment
There was a problem hiding this comment.
@loitly this is excellent work! The component library looks very neat and storybook demo renders code documentation very nicely along with rendering the examples 👏
I tried to go over most of the files except the vite.config.js which seems a lot of configuration tweaking to make our existing codebase designed for webpack play nice with vite/rollup?! The code looks mostly good and clean. Most of my comments are minor improvements or broad questions.
I haven't build it locally yet. The storybook demo online looks awesome. I did notice one issue with the chart stories however:
In "Charts Panel", click on "Static Data" then -> "Linked table" -> "Event Hooks": all components load fine. Now click on "Linked table" then -> "Event Hooks": the chart panel component disappears. Same behavior in "Histogram Chart" and "Scatter Chart" stories when you click on them top to bottom and then go bottom to top. Maybe it has to do with some chart viewer ID collision? I don't see any traceback so can't tell.
The following are some big ideas/directions we should consider after we merge this PR:
- Make the components skinnable (easy-to-change styling/look): HEASARC has a style guide (design system) they have to follow and IIRC NED also wanted to do a different look than default firefly styling. I know we are limited by the styling machinery of JoyUI but:
- we can maybe create some stories to demo customizing components look and point to relevant documentation in joy-ui docs explaining how to customize the styling
- [super ambitious high-effort route] redo our firefly components to use https://v5.mui.com/base-ui/ and then use joy ui as the default styling layer rather than as the component layer.
- We should consider using Vite/Rollup also for the firefly/src instead of webpack. The Vite seems to be industry standard now-a-days and requires much lesser config setup than we do with webpack.
- We should also be deliberate about putting param/props description in jsdoc docstring and minimize PropTypes since it's discouraged in react 19+. And maybe incrementally add typescript?!
| <Card {...{ | ||
| color:'warning', variant:'soft', position:'relative', | ||
| zIndex: maskShowing ? 10 : 'auto', | ||
| color:'warning', variant:'soft', |
There was a problem hiding this comment.
I second this, I noticed it when using BGMaskPanel for image type job results.
|
|
||
| A React component library for astronomical data visualization, built on | ||
| [Firefly](https://github.com/Caltech-IPAC/firefly), the web visualization | ||
| framework from [IPAC / Caltech](https://www.ipac.caltech.edu/). |
There was a problem hiding this comment.
| framework from [IPAC / Caltech](https://www.ipac.caltech.edu/). | |
| framework from [Caltech/IPAC](https://www.ipac.caltech.edu/). |
that's what the recommended way is for written materials.
| framework from [IPAC / Caltech](https://www.ipac.caltech.edu/). | ||
|
|
||
| The library provides ready-to-use components for displaying catalog tables, | ||
| interactive charts, and FITS sky images that integrate with a running Firefly |
There was a problem hiding this comment.
Maybe mention: FITS and HiPS sky images? or astronomical images?
| @@ -0,0 +1,67 @@ | |||
| { | |||
| "name": "@ipac/firefly-component-library", | |||
There was a problem hiding this comment.
I think we can just do @ipac/firefly-components for brevity. NPM package implicitly implies that it's a library and we also explain that in description.
| "@mui/joy": "^5.0.0-beta.52", | ||
| "@mui/material": "^5.18", | ||
| "@mui/x-date-pickers": "^6.19", | ||
| "moment": "~2.30", |
There was a problem hiding this comment.
Is ~ on moment deliberate? In general, peerDependencies should be broad version ranges (hence ^)
| @@ -0,0 +1,6 @@ | |||
| import { Meta, Markdown } from '@storybook/blocks'; | |||
| import Readme from '../README.md?raw'; | |||
| (Story, ctx) => { | ||
| const desc = ctx.parameters.storyDescription; | ||
| return ( | ||
| <CssVarsProvider defaultMode='system' theme={theme}> |
There was a problem hiding this comment.
is there a way we can expose and pass the mode from storybook layer to firefly components?
Currently I can't test the components in storybook stories in dark mode even when my system theme is dark.
| * For large row counts Firefly automatically switches from SVG `scatter` | ||
| * to WebGL `scattergl` for performance. | ||
| */ | ||
| export function ScatterChart({ chartId, tbl_id, x_axis, y_axis, chartData, options, events, ...props }) { |
There was a problem hiding this comment.
Do we really need to make Scatter and Histogram separate components? They seem like a specific case of ChartPanel controlled via chartData prop - can't we just document that in ChartPanel's story as more cases?
In broader context: are we ok with this component library API not mirroring the existing API of main firefly source? I can see some advantages for not mirroring but it may create a shadow API that's hard to maintain if overused.
There was a problem hiding this comment.
Part of my work involves demonstrating our capabilities. This example show how to simplify our existing components. By keeping the Scatter chart as it is, we can hide the internal mapping scheme used to map a table column’s data to a chart’s data array. Also, it highlights the required parameters.
However, I understand your concern. Another idea is to move these components into Firefly’s source code so that Firefly can utilize them instead of maintaining them as a separate component within the library.
These are considerations to keep in mind before the actual release.
| import { DEFAULT_COVERAGE_VIEWER_ID } from 'firefly/visualize/PlotViewUtil.js'; | ||
|
|
||
| /** | ||
| * Displays table coverage/footprint overlaid on a sky image. |
There was a problem hiding this comment.
| * Displays table coverage/footprint overlaid on a sky image. | |
| * Displays table coverage/footprint overlaid on a sky image as markers. |
| */ | ||
| request: PropTypes.object, | ||
|
|
||
| /** MUI Joy `sx` prop applied to the container. Use to set height, width, etc. */ |
There was a problem hiding this comment.
these param descriptions render nicely in storybook demo. But I'm wondering if we can move them to jsdoc above since PropTypes are discouraged in React 19+? (which will also remove proptype as ome more dependency)
There was a problem hiding this comment.
I vaguely recalled encountering errors while storybook parses the jsdoc, but it’s worth revisiting.
Ticket: https://jira.ipac.caltech.edu/browse/FIREFLY-2033
his PR introduces a React component library that wraps Firefly’s table, chart, and image visualization components and packages them as a standalone npm library.
The library source is located under /component-library.
Documentation
Development and Build Modes
The component library has three modes of operation:
1. Distributed Mode
Components are built and packaged for publication to npm.
2. Storybook Development Mode
Interactive development environment for component development and testing.
3. Storybook Static Mode
Generates a fully static Storybook build suitable for deployment.
Firefly Integration
As part of the (full) Firefly build process, a deployed Storybook instance for this library is published at:
/firefly/component-library/
This deployment serves as the primary reference for component examples, documentation, and interactive testing.
Notes for Reviewers
There are additional implementation and architectural details that may be easier to discuss in person.
For this review, please focus on:
Demo: https://fireflydev.ipac.caltech.edu/firefly-2033-component-library/firefly/component-library/
NOTES:
The Java files in this branch are from a separate fix (multiple webapp local deployment) that I accidentally included. I can pull them out if you'd prefer to keep this PR focused.