diff --git a/CHANGELOG.md b/CHANGELOG.md index 6980ab422..a99b9fd19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Not released +- Bar & Histogram & Formula & ComparativeFormula Widgets: Add a skeleton for loading state [#674](https://github.com/CartoDB/carto-react/pull/674) + ## 2.0 ## 2.0.4 (2023-05-19) diff --git a/packages/react-ui/__tests__/widgets/BarWidgetUI.test.js b/packages/react-ui/__tests__/widgets/BarWidgetUI.test.js index db5e29700..f956698cc 100644 --- a/packages/react-ui/__tests__/widgets/BarWidgetUI.test.js +++ b/packages/react-ui/__tests__/widgets/BarWidgetUI.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { render, fireEvent, screen } from '../widgets/utils/testUtils'; -import BarWidgetUI from '../../src/widgets/BarWidgetUI'; +import BarWidgetUI from '../../src/widgets/BarWidgetUI/BarWidgetUI'; import { mockEcharts } from './testUtils'; describe('BarWidgetUI', () => { diff --git a/packages/react-ui/__tests__/widgets/FormulaWidgetUI.test.js b/packages/react-ui/__tests__/widgets/FormulaWidgetUI.test.js index 899ba8edb..04532bfa3 100644 --- a/packages/react-ui/__tests__/widgets/FormulaWidgetUI.test.js +++ b/packages/react-ui/__tests__/widgets/FormulaWidgetUI.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { render, screen } from '../widgets/utils/testUtils'; -import FormulaWidgetUI from '../../src/widgets/FormulaWidgetUI'; +import FormulaWidgetUI from '../../src/widgets/FormulaWidgetUI/FormulaWidgetUI'; import { currencyFormatter } from './testUtils'; describe('FormulaWidgetUI', () => { diff --git a/packages/react-ui/__tests__/widgets/WrapperWidgetUI.test.js b/packages/react-ui/__tests__/widgets/WrapperWidgetUI.test.js index fe143aaf6..966cd9ac4 100644 --- a/packages/react-ui/__tests__/widgets/WrapperWidgetUI.test.js +++ b/packages/react-ui/__tests__/widgets/WrapperWidgetUI.test.js @@ -6,7 +6,7 @@ import { waitForElementToBeRemoved } from '../widgets/utils/testUtils'; import WrapperWidgetUI from '../../src/widgets/WrapperWidgetUI'; -import FormulaWidgetUI from '../../src/widgets/FormulaWidgetUI'; +import FormulaWidgetUI from '../../src/widgets/FormulaWidgetUI/FormulaWidgetUI'; describe('WrapperWidgetUI', () => { const TITLE = 'test'; diff --git a/packages/react-ui/src/index.d.ts b/packages/react-ui/src/index.d.ts index ba1bab35f..9093088cb 100644 --- a/packages/react-ui/src/index.d.ts +++ b/packages/react-ui/src/index.d.ts @@ -1,8 +1,8 @@ import { theme, cartoThemeOptions, CartoTheme } from './theme/carto-theme'; import WrapperWidgetUI from './widgets/WrapperWidgetUI'; import CategoryWidgetUI from './widgets/CategoryWidgetUI'; -import FormulaWidgetUI from './widgets/FormulaWidgetUI'; -import BarWidgetUI from './widgets/BarWidgetUI'; +import FormulaWidgetUI from './widgets/FormulaWidgetUI/FormulaWidgetUI'; +import BarWidgetUI from './widgets/BarWidgetUI/BarWidgetUI'; import HistogramWidgetUI from './widgets/HistogramWidgetUI/HistogramWidgetUI'; import PieWidgetUI from './widgets/PieWidgetUI'; import LegendWidgetUI, { LEGEND_TYPES } from './widgets/legend/LegendWidgetUI'; @@ -35,7 +35,7 @@ import SelectField, { SelectFieldProps } from './components/atoms/SelectField'; import UploadField, { UploadFieldProps } from './components/molecules/UploadField/UploadField'; -import AppBar, {AppBarProps} from './components/organisms/AppBar/AppBar'; +import AppBar, { AppBarProps } from './components/organisms/AppBar/AppBar'; import LabelWithIndicator, { LabelWithIndicatorProps } from './components/atoms/LabelWithIndicator'; @@ -92,7 +92,6 @@ export { UploadFieldProps, AppBar, AppBarProps, - LabelWithIndicator, LabelWithIndicatorProps, getCartoColorStylePropsForItem, diff --git a/packages/react-ui/src/index.js b/packages/react-ui/src/index.js index 99fd88069..93770d7ff 100644 --- a/packages/react-ui/src/index.js +++ b/packages/react-ui/src/index.js @@ -1,8 +1,8 @@ import { theme, cartoThemeOptions } from './theme/carto-theme'; import WrapperWidgetUI from './widgets/WrapperWidgetUI'; import CategoryWidgetUI from './widgets/CategoryWidgetUI'; -import FormulaWidgetUI from './widgets/FormulaWidgetUI'; -import BarWidgetUI from './widgets/BarWidgetUI'; +import FormulaWidgetUI from './widgets/FormulaWidgetUI/FormulaWidgetUI'; +import BarWidgetUI from './widgets/BarWidgetUI/BarWidgetUI'; import HistogramWidgetUI from './widgets/HistogramWidgetUI/HistogramWidgetUI'; import PieWidgetUI from './widgets/PieWidgetUI'; import LegendWidgetUI, { LEGEND_TYPES } from './widgets/legend/LegendWidgetUI'; diff --git a/packages/react-ui/src/theme/sections/components/feedback.js b/packages/react-ui/src/theme/sections/components/feedback.js index 10665a608..bd04fa653 100644 --- a/packages/react-ui/src/theme/sections/components/feedback.js +++ b/packages/react-ui/src/theme/sections/components/feedback.js @@ -1,3 +1,6 @@ +import { getSpacing } from '../../themeUtils'; +import { commonPalette } from '../palette'; + export const feedbackOverrides = { // SnackBar MuiSnackbar: { @@ -7,5 +10,30 @@ export const feedbackOverrides = { horizontal: 'center' } } + }, + + // Skeleton + MuiSkeleton: { + defaultProps: { + animation: 'wave', + variant: 'rounded' + }, + + styleOverrides: { + root: { + backgroundColor: commonPalette.black[8] + }, + rounded: { + borderRadius: getSpacing(0.5) + }, + text: { + borderRadius: getSpacing(0.5) + }, + wave: { + '&::after': { + background: `linear-gradient( 90deg, transparent, ${commonPalette.black[4]}, transparent )` + } + } + } } }; diff --git a/packages/react-ui/src/types.d.ts b/packages/react-ui/src/types.d.ts index 3ee799b4f..b0f2e942a 100644 --- a/packages/react-ui/src/types.d.ts +++ b/packages/react-ui/src/types.d.ts @@ -38,6 +38,7 @@ export type FormulaWidgetUIData = export type FormulaWidgetUI = { data: FormulaWidgetUIData; formatter?: Function; + isLoading?: boolean; }; export type HistogramWidgetUIData = number[]; @@ -51,6 +52,7 @@ export type HistogramWidgetUI = { name?: string; onSelectedBarsChange?: Function; height?: number; + isLoading?: boolean; }; export type BarWidgetUI = { @@ -69,6 +71,7 @@ export type BarWidgetUI = { height?: string | number; filterable?: boolean; animation?: boolean; + isLoading?: boolean; }; export type PieWidgetUIData = { name: string; value: number }[]; @@ -223,6 +226,7 @@ export type ComparativeFormulaWidgetUI = { animated?: boolean; animationOptions?: AnimationOptions; formatter?: (n: number) => React.ReactNode; + isLoading?: boolean; }; export enum ORDER_TYPES { diff --git a/packages/react-ui/src/widgets/BarWidgetUI/BarSkeleton.js b/packages/react-ui/src/widgets/BarWidgetUI/BarSkeleton.js new file mode 100644 index 000000000..f1c66968c --- /dev/null +++ b/packages/react-ui/src/widgets/BarWidgetUI/BarSkeleton.js @@ -0,0 +1,22 @@ +import { Box, Skeleton } from '@mui/material'; +import { SkeletonBarsGrid, SkeletonBarItem, SKELETON_HEIGHT } from '../SkeletonWidgets'; + +const BarSkeleton = ({ height }) => { + return ( + <> + + + + + + + + + + + + + ); +}; + +export default BarSkeleton; diff --git a/packages/react-ui/src/widgets/BarWidgetUI.js b/packages/react-ui/src/widgets/BarWidgetUI/BarWidgetUI.js similarity index 96% rename from packages/react-ui/src/widgets/BarWidgetUI.js rename to packages/react-ui/src/widgets/BarWidgetUI/BarWidgetUI.js index 6b2e82cb3..27ff0f026 100644 --- a/packages/react-ui/src/widgets/BarWidgetUI.js +++ b/packages/react-ui/src/widgets/BarWidgetUI/BarWidgetUI.js @@ -1,10 +1,11 @@ import React, { useCallback, useMemo } from 'react'; import PropTypes from 'prop-types'; -import ReactEcharts from '../custom-components/echarts-for-react'; +import ReactEcharts from '../../custom-components/echarts-for-react'; import { Grid, Link, useTheme, darken, styled } from '@mui/material'; -import detectTouchScreen from './utils/detectTouchScreen'; -import { processFormatterRes } from './utils/formatterUtils'; -import Typography from '../components/atoms/Typography'; +import detectTouchScreen from '../utils/detectTouchScreen'; +import { processFormatterRes } from '../utils/formatterUtils'; +import Typography from '../../components/atoms/Typography'; +import BarSkeleton from './BarSkeleton'; const IS_TOUCH_SCREEN = detectTouchScreen(); @@ -42,7 +43,8 @@ function BarWidgetUI(props) { stacked, height, filterable, - animation + animation, + isLoading } = useProcessedProps(props); const isMultiSeries = series.length > 1; @@ -287,6 +289,8 @@ function BarWidgetUI(props) { [filterable, clickEvent] ); + if (isLoading) return ; + return (
{onSelectedBarsChange && ( @@ -352,7 +356,8 @@ BarWidgetUI.propTypes = { onSelectedBarsChange: PropTypes.func, height: numberOrString, filterable: PropTypes.bool, - animation: PropTypes.bool + animation: PropTypes.bool, + isLoading: PropTypes.bool }; export default BarWidgetUI; diff --git a/packages/react-ui/src/widgets/FormulaWidgetUI/FormulaSkeleton.js b/packages/react-ui/src/widgets/FormulaWidgetUI/FormulaSkeleton.js new file mode 100644 index 000000000..6e3c1c13c --- /dev/null +++ b/packages/react-ui/src/widgets/FormulaWidgetUI/FormulaSkeleton.js @@ -0,0 +1,7 @@ +import { Skeleton } from '@mui/material'; + +const FormulaSkeleton = () => { + return ; +}; + +export default FormulaSkeleton; diff --git a/packages/react-ui/src/widgets/FormulaWidgetUI.js b/packages/react-ui/src/widgets/FormulaWidgetUI/FormulaWidgetUI.js similarity index 88% rename from packages/react-ui/src/widgets/FormulaWidgetUI.js rename to packages/react-ui/src/widgets/FormulaWidgetUI/FormulaWidgetUI.js index 22860447f..ed92664a5 100644 --- a/packages/react-ui/src/widgets/FormulaWidgetUI.js +++ b/packages/react-ui/src/widgets/FormulaWidgetUI/FormulaWidgetUI.js @@ -1,8 +1,9 @@ import React, { useEffect, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import { styled } from '@mui/material'; -import { animateValue } from './utils/animations'; -import Typography from '../components/atoms/Typography'; +import { animateValue } from '../utils/animations'; +import Typography from '../../components/atoms/Typography'; +import FormulaSkeleton from './FormulaSkeleton'; const Prefix = styled('span')(() => ({ marginRight: '2px' @@ -21,7 +22,7 @@ function usePrevious(value) { } function FormulaWidgetUI(props) { - const { data, formatter, animation } = props; + const { data, formatter, animation, isLoading } = props; const [value, setValue] = useState('-'); const requestRef = useRef(); const prevValue = usePrevious(value); @@ -63,6 +64,8 @@ function FormulaWidgetUI(props) { const isComplexFormat = typeof formattedValue === 'object' && formattedValue !== null; + if (isLoading) return ; + return isComplexFormat ? ( {formattedValue.prefix} @@ -95,7 +98,8 @@ FormulaWidgetUI.propTypes = { }) ]), formatter: PropTypes.func, - animation: PropTypes.bool + animation: PropTypes.bool, + isLoading: PropTypes.bool }; export default FormulaWidgetUI; diff --git a/packages/react-ui/src/widgets/HistogramWidgetUI/HistogramSkeleton.js b/packages/react-ui/src/widgets/HistogramWidgetUI/HistogramSkeleton.js new file mode 100644 index 000000000..daf2b44b6 --- /dev/null +++ b/packages/react-ui/src/widgets/HistogramWidgetUI/HistogramSkeleton.js @@ -0,0 +1,33 @@ +import { Box, Skeleton } from '@mui/material'; +import { + SKELETON_HEIGHT, + SkeletonGraphGrid, + SkeletonThinBarItem +} from '../SkeletonWidgets'; + +const HistogramSkeleton = ({ height }) => { + return ( + <> + + + + + + + + + + + + + + + + + + + + ); +}; + +export default HistogramSkeleton; diff --git a/packages/react-ui/src/widgets/HistogramWidgetUI/HistogramWidgetUI.js b/packages/react-ui/src/widgets/HistogramWidgetUI/HistogramWidgetUI.js index 845efe8ea..b7647af2d 100644 --- a/packages/react-ui/src/widgets/HistogramWidgetUI/HistogramWidgetUI.js +++ b/packages/react-ui/src/widgets/HistogramWidgetUI/HistogramWidgetUI.js @@ -7,6 +7,7 @@ import { processFormatterRes } from '../utils/formatterUtils'; import detectTouchscreen from '../utils/detectTouchScreen'; import useHistogramInteractivity from './useHistogramInteractivity'; import Typography from '../../components/atoms/Typography'; +import HistogramSkeleton from './HistogramSkeleton'; const IS_TOUCH_SCREEN = detectTouchscreen(); @@ -39,7 +40,8 @@ function HistogramWidgetUI({ tooltipFormatter, animation, filterable: _filterable, - height + height, + isLoading }) { const theme = useTheme(); @@ -262,6 +264,8 @@ function HistogramWidgetUI({ 0 ); + if (isLoading) return ; + return (
{filterable && ( @@ -311,7 +315,8 @@ HistogramWidgetUI.propTypes = { onSelectedBarsChange: PropTypes.func, animation: PropTypes.bool, filterable: PropTypes.bool, - height: PropTypes.number + height: PropTypes.number, + isLoading: PropTypes.bool }; export default HistogramWidgetUI; diff --git a/packages/react-ui/src/widgets/SkeletonWidgets.js b/packages/react-ui/src/widgets/SkeletonWidgets.js new file mode 100644 index 000000000..eca87a61a --- /dev/null +++ b/packages/react-ui/src/widgets/SkeletonWidgets.js @@ -0,0 +1,55 @@ +import { Skeleton, styled } from '@mui/material'; + +export const SKELETON_HEIGHT = 240; + +export const SkeletonBarsGrid = styled('div')(({ theme }) => ({ + display: 'flex', + alignItems: 'flex-end', + justifyContent: 'space-between', + width: '100%', + position: 'relative', + padding: theme.spacing(0, 2), + + // Linear grid effect + '&::before': { + content: '""', + position: 'absolute', + top: 0, + right: 0, + left: 0, + bottom: 0, + backgroundSize: theme.spacing(4, 4), + backgroundImage: `linear-gradient(to bottom, ${theme.palette.grey[50]} 1px, transparent 1px)`, + transform: 'scaleY(-1)' + } +})); + +export const SkeletonGraphGrid = styled('div')(({ theme }) => ({ + display: 'flex', + alignItems: 'flex-end', + justifyContent: 'space-between', + width: '100%', + + // Square grid effect + backgroundImage: `linear-gradient(${theme.palette.grey[50]} 0.5px, transparent 0.5px, transparent calc(100% - 0.5px), ${theme.palette.grey[50]} calc(100% - 0.5px)), linear-gradient(90deg, ${theme.palette.grey[50]} 0.5px, transparent 0.5px, transparent calc(100% - 0.5px), ${theme.palette.grey[50]} calc(100% - 0.5px))`, + backgroundSize: '8.33% 20%', + border: `0.5px solid ${theme.palette.grey[50]}` +})); + +export const SkeletonBarItem = styled(Skeleton)(({ theme }) => ({ + flex: 1, + maxWidth: theme.spacing(12), + + '& + &': { + marginLeft: theme.spacing(1) + } +})); + +export const SkeletonThinBarItem = styled(Skeleton)(({ theme }) => ({ + flex: 1, + maxWidth: theme.spacing(8), + + '& + &': { + marginLeft: '1px' + } +})); diff --git a/packages/react-ui/src/widgets/comparative/ComparativeFormulaWidgetUI/ComparativeFormulaWidgetUI.js b/packages/react-ui/src/widgets/comparative/ComparativeFormulaWidgetUI/ComparativeFormulaWidgetUI.js index 6c188d4bb..3ea1bf1c3 100644 --- a/packages/react-ui/src/widgets/comparative/ComparativeFormulaWidgetUI/ComparativeFormulaWidgetUI.js +++ b/packages/react-ui/src/widgets/comparative/ComparativeFormulaWidgetUI/ComparativeFormulaWidgetUI.js @@ -6,6 +6,7 @@ import { animationOptionsPropTypes } from '../../../custom-components/AnimatedNu import FormulaValue from './FormulaValue'; import FormulaLabel from './FormulaLabel'; +import FormulaSkeleton from '../../FormulaWidgetUI/FormulaSkeleton'; const IDENTITY_FN = (v) => v; const EMPTY_ARRAY = []; @@ -25,6 +26,7 @@ const FormulaGroup = styled('div')(({ theme }) => ({ * @param {boolean} [props.animated] * @param {{ duration?: number; animateOnMount?: boolean; initialValue?: number; }} [props.animationOptions] * @param {(v: number) => React.ReactNode} [props.formatter] + * @param {boolean} [props.isLoading] * --> */ function ComparativeFormulaWidgetUI({ @@ -32,10 +34,15 @@ function ComparativeFormulaWidgetUI({ colors = EMPTY_ARRAY, animated = true, animationOptions, - formatter = IDENTITY_FN + formatter = IDENTITY_FN, + isLoading = false }) { const formulaValues = prepareFormulaValues(data, colors); + if (isLoading) { + return ; + } + return (
{formulaValues.map((row, index) => ( @@ -90,7 +97,8 @@ ComparativeFormulaWidgetUI.propTypes = { colors: PropTypes.arrayOf(PropTypes.string), animated: PropTypes.bool, animationOptions: animationOptionsPropTypes, - formatter: PropTypes.func + formatter: PropTypes.func, + isLoading: PropTypes.bool }; export default ComparativeFormulaWidgetUI; diff --git a/packages/react-ui/storybook/stories/Introduction.stories.mdx b/packages/react-ui/storybook/stories/Introduction.stories.mdx index 8d17b83bf..65565a73e 100644 --- a/packages/react-ui/storybook/stories/Introduction.stories.mdx +++ b/packages/react-ui/storybook/stories/Introduction.stories.mdx @@ -16,7 +16,7 @@ This storybook includes the UI Components (@carto/react-ui) for CARTO for React. The components are based on [Mui v5](https://mui.com/), and they include a CARTO theme + custom components and widgets. -We have currently support for `React` 17 (and we're working on having it for v18 asap) +We have currently support for `React` 17 and 18. ## Library version @@ -27,15 +27,16 @@ We have currently support for `React` 17 (and we're working on having it for v18 We have a label in the story of each component that indicates its maturity and recommended use: **Recommended use** + - `Validated`: Fully validated and ready-to-use implementation of a component - `Needs update`: Needs an update due to some design changes, but it can be used in this state - `Deprecated`: Legacy component that might be currently in use, but it shouldn't be used in new projects **Not supported** + - `In development`: Work in progress or experimental. Not ready to use in production yet - `Ready to review`: Ready to review and validation by CARTO design team and other stakeholders, prior to be consider fully done (it can be considered as a 2nd phase of `In development`). - ## Resources
diff --git a/packages/react-ui/storybook/stories/widgetsUI/BarWidgetUI.stories.js b/packages/react-ui/storybook/stories/widgetsUI/BarWidgetUI.stories.js index 7e919730a..87021cdb8 100644 --- a/packages/react-ui/storybook/stories/widgetsUI/BarWidgetUI.stories.js +++ b/packages/react-ui/storybook/stories/widgetsUI/BarWidgetUI.stories.js @@ -1,6 +1,7 @@ import React from 'react'; -import BarWidgetUI from '../../../src/widgets/BarWidgetUI'; +import BarWidgetUI from '../../../src/widgets/BarWidgetUI/BarWidgetUI'; import { buildReactPropsAsString } from '../../utils/utils'; +import { Label, ThinContainer } from '../../utils/storyStyles'; const options = { title: 'Organisms/Widgets/BarWidgetUI', @@ -17,6 +18,28 @@ const Template = (args) => { return ; }; +const LoadingTemplate = (args) => { + if (args.series && !Array.isArray(args.series)) { + args.series = []; + } + + return ( + <> + + + + + + + + + ); +}; + const yAxisData = [100, 300, 500, 250, 50, 200]; const xAxisData = yAxisData.map((_, idx) => `Store ${idx + 1}`); @@ -135,3 +158,12 @@ MultipleBarsCustomColors.parameters = buildReactPropsAsString( MultipleBarsCustomColorsProps, 'BarWidgetUI' ); + +export const Loading = LoadingTemplate.bind({}); +const LoadingProps = { + yAxisData, + xAxisData, + isLoading: true +}; +Loading.args = LoadingProps; +Loading.parameters = buildReactPropsAsString(LoadingProps, 'BarWidgetUI'); diff --git a/packages/react-ui/storybook/stories/widgetsUI/ComparativeFormulaWidgetUI.stories.js b/packages/react-ui/storybook/stories/widgetsUI/ComparativeFormulaWidgetUI.stories.js index e95f81c35..0faee1f46 100644 --- a/packages/react-ui/storybook/stories/widgetsUI/ComparativeFormulaWidgetUI.stories.js +++ b/packages/react-ui/storybook/stories/widgetsUI/ComparativeFormulaWidgetUI.stories.js @@ -1,6 +1,7 @@ import React from 'react'; import ComparativeFormulaWidgetUI from '../../../src/widgets/comparative/ComparativeFormulaWidgetUI/ComparativeFormulaWidgetUI'; import { buildReactPropsAsString } from '../../utils/utils'; +import { Label, ThinContainer } from '../../utils/storyStyles'; const options = { title: 'Organisms/Widgets/ComparativeFormulaWidgetUI', @@ -10,6 +11,25 @@ const options = { export default options; const Template = (args) => ; + +const LoadingTemplate = (args) => { + return ( + <> + + + + + + + + + ); +}; + const sampleProps = { data: [ { prefix: '$', suffix: ' sales', label: 'label 1', value: 1245 }, @@ -21,3 +41,7 @@ const sampleProps = { export const Default = Template.bind({}); Default.args = sampleProps; Default.parameters = buildReactPropsAsString(sampleProps, 'ComparativeFormulaWidgetUI'); + +export const Loading = LoadingTemplate.bind({}); +Loading.args = { ...sampleProps, isLoading: true }; +Loading.parameters = buildReactPropsAsString(sampleProps, 'ComparativeFormulaWidgetUI'); diff --git a/packages/react-ui/storybook/stories/widgetsUI/FormulaWidgetUI.stories.js b/packages/react-ui/storybook/stories/widgetsUI/FormulaWidgetUI.stories.js index b7bc5244c..acd7937df 100644 --- a/packages/react-ui/storybook/stories/widgetsUI/FormulaWidgetUI.stories.js +++ b/packages/react-ui/storybook/stories/widgetsUI/FormulaWidgetUI.stories.js @@ -1,5 +1,6 @@ import React from 'react'; -import FormulaWidgetUI from '../../../src/widgets/FormulaWidgetUI'; +import FormulaWidgetUI from '../../../src/widgets/FormulaWidgetUI/FormulaWidgetUI'; +import { Label, ThinContainer } from '../../utils/storyStyles'; const options = { title: 'Organisms/Widgets/FormulaWidgetUI', @@ -22,7 +23,27 @@ const options = { export default options; -const Template = (args) => ; +const Template = (args) => { + return ; +}; + +const LoadingTemplate = (args) => { + return ( + <> + + + + + + + + + ); +}; const data = 10000; @@ -54,3 +75,7 @@ const formatter = (value) => }).format(value); const FormatterTextProps = { data, formatter }; FormatterText.args = FormatterTextProps; + +export const Loading = LoadingTemplate.bind({}); +const LoadingProps = { data, isLoading: true }; +Loading.args = LoadingProps; diff --git a/packages/react-ui/storybook/stories/widgetsUI/HistogramWidgetUI.stories.js b/packages/react-ui/storybook/stories/widgetsUI/HistogramWidgetUI.stories.js index cd352208a..5a10c43e5 100644 --- a/packages/react-ui/storybook/stories/widgetsUI/HistogramWidgetUI.stories.js +++ b/packages/react-ui/storybook/stories/widgetsUI/HistogramWidgetUI.stories.js @@ -1,5 +1,6 @@ import React from 'react'; import HistogramWidgetUI from '../../../src/widgets/HistogramWidgetUI/HistogramWidgetUI'; +import { Label, ThinContainer } from '../../utils/storyStyles'; const options = { title: 'Organisms/Widgets/HistogramWidgetUI', @@ -19,6 +20,24 @@ const Template = (args) => { return ; }; +const LoadingTemplate = (args) => { + return ( + <> + + + + + + + + + ); +}; + const defaultProps = { data: [100, 300, 500, 250, 50, 200, 100], ticks: [100, 200, 300, 400, 500, 600], @@ -60,3 +79,10 @@ const NonEqualSizeBinsProps = { ticks: [100, 200, 250, 450, 500, 600] }; NonEqualSizeBins.args = NonEqualSizeBinsProps; + +export const Loading = LoadingTemplate.bind({}); +const LoadingProps = { + ...defaultProps, + isLoading: true +}; +Loading.args = LoadingProps; diff --git a/packages/react-ui/storybook/stories/widgetsUI/WrapperWidgetUI.stories.js b/packages/react-ui/storybook/stories/widgetsUI/WrapperWidgetUI.stories.js index e09fd5eaf..8fde89920 100644 --- a/packages/react-ui/storybook/stories/widgetsUI/WrapperWidgetUI.stories.js +++ b/packages/react-ui/storybook/stories/widgetsUI/WrapperWidgetUI.stories.js @@ -54,7 +54,7 @@ const NotExpandableProps = { title: 'Not Expandable', expandable: false }; NotExpandable.args = NotExpandableProps; export const Loading = Template.bind({}); -const LoadingProps = { title: 'Loading', loading: true }; +const LoadingProps = { title: 'Loading', isLoading: true }; Loading.args = LoadingProps; export const Disabled = Template.bind({}); diff --git a/packages/react-ui/storybook/utils/storyStyles.js b/packages/react-ui/storybook/utils/storyStyles.js index 23a8253c5..a1efbdf4c 100644 --- a/packages/react-ui/storybook/utils/storyStyles.js +++ b/packages/react-ui/storybook/utils/storyStyles.js @@ -29,6 +29,10 @@ export const Container = styled(Standalone)(({ theme }) => ({ marginTop: theme.spacing(4) })); +export const ThinContainer = styled(Box)(({ theme }) => ({ + maxWidth: theme.spacing(36) +})); + export const FilledContainer = styled(Box)(({ theme }) => ({ display: 'flex', alignItems: 'center', diff --git a/packages/react-widgets/src/widgets/BarWidget.js b/packages/react-widgets/src/widgets/BarWidget.js index 68554db08..0442d6bf6 100644 --- a/packages/react-widgets/src/widgets/BarWidget.js +++ b/packages/react-widgets/src/widgets/BarWidget.js @@ -164,6 +164,7 @@ function BarWidget({ height={height} animation={animation} filterable={filterable} + isLoading={isLoading} /> )} diff --git a/packages/react-widgets/src/widgets/FormulaWidget.js b/packages/react-widgets/src/widgets/FormulaWidget.js index e6d91d67b..23f7da32b 100644 --- a/packages/react-widgets/src/widgets/FormulaWidget.js +++ b/packages/react-widgets/src/widgets/FormulaWidget.js @@ -67,7 +67,12 @@ function FormulaWidget({ showDroppingFeaturesAlert={!remoteCalculation} > {value !== undefined && ( - + )}