From c7eece40f9dd2ee729dd540b0aab795c664e2582 Mon Sep 17 00:00:00 2001 From: Scott Hetrick Date: Mon, 30 Oct 2023 17:45:25 -0700 Subject: [PATCH 1/3] Fixed a lot, committing to switch workstations --- package-lock.json | 4 +- src/index.ts | 2 +- src/{assets => lib}/icons.ts | 0 .../summary-tile/summary-tile.stories.tsx | 74 +++++++--- src/reports/summary-tile/summary-tile.tsx | 134 +++++++++++++----- 5 files changed, 156 insertions(+), 58 deletions(-) rename src/{assets => lib}/icons.ts (100%) diff --git a/package-lock.json b/package-lock.json index 7e446fb..ed2535c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@broadlume/willow-ui", - "version": "0.0.0", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@broadlume/willow-ui", - "version": "0.0.0", + "version": "0.0.1", "dependencies": { "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-alert-dialog": "^1.0.4", diff --git a/src/index.ts b/src/index.ts index 2d8929d..6ace7bd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import './assets/typekit.css'; import './index.scss'; -export * from '@src/assets/icons'; +export * from '@src/lib/icons'; export * from '@components/accordion/accordion'; export * from '@components/alert-dialog/alert-dialog'; diff --git a/src/assets/icons.ts b/src/lib/icons.ts similarity index 100% rename from src/assets/icons.ts rename to src/lib/icons.ts diff --git a/src/reports/summary-tile/summary-tile.stories.tsx b/src/reports/summary-tile/summary-tile.stories.tsx index 2e6739e..6a6d622 100644 --- a/src/reports/summary-tile/summary-tile.stories.tsx +++ b/src/reports/summary-tile/summary-tile.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { SummaryTile } from './summary-tile'; +import { SummaryTile, SummaryTileNumProps } from './summary-tile'; import { FaMousePointer, FaPhoneAlt, FaShoppingCart } from 'react-icons/fa'; import { BsChatFill } from 'react-icons/bs'; @@ -11,24 +11,51 @@ const meta: Meta = { export default meta; type Story = StoryObj; -const data = [ - { number: 1355003, label: 'Sessions', delta: '6%' }, - { number: 1115314, label: 'Users', delta: '7%' }, - { number: 3945916, label: 'Page Views', delta: '6%' }, +const data: SummaryTileNumProps[] = [ + { + label: 'Users', + current: 18246, + previous: 19328, + }, + { + label: 'Sessions', + current: 10311, + previous: 10018, + }, + { + label: 'Lawsuits', + current: 19605, + previous: 21967, + negativeIsGood: true, + }, + { + label: 'Page Views', + number: 11674, + }, +]; + +const customData: SummaryTileNumProps[] = [ { number: '1:30', label: 'Average Session Duration', delta: '-3 Second', negative: true, }, + { + number: '0:10', + label: 'Average Page Load', + delta: '-8 Second', + negative: true, + negativeIsGood: true, + }, ]; -const stackedData = [ +const stackedData: SummaryTileNumProps[] = [ { - number: 81911, + current: 81911, + previous: 86006, + label: 'Total Leads', - delta: '-5%', - negative: true, }, { number: 57997, @@ -38,19 +65,16 @@ const stackedData = [ Calls ), - delta: '-4%', - negative: true, }, { - number: 21257, + current: 21257, + previous: 19866, label: ( <> Forms ), - delta: '-7%', - negative: true, }, { number: 2446, @@ -64,23 +88,31 @@ const stackedData = [ negative: true, }, { - number: 57997, + current: 57997, + previous: 58577, label: ( <> Sample Orders ), - delta: '-1%', - negative: true, }, ]; export const Demo: Story = { render: (_) => (
- {data.map((tile) => ( - + {data.map((tile, index) => ( + + ))} +
+ ), +}; +export const CustomUnits: Story = { + render: (_) => ( +
+ {customData.map((tile, index) => ( + ))}
), @@ -89,8 +121,8 @@ export const Demo: Story = { export const Loading: Story = { render: (_) => (
- {data.map((tile) => ( - + {data.map((tile, index) => ( + ))}
), diff --git a/src/reports/summary-tile/summary-tile.tsx b/src/reports/summary-tile/summary-tile.tsx index 0e27a6f..c950924 100644 --- a/src/reports/summary-tile/summary-tile.tsx +++ b/src/reports/summary-tile/summary-tile.tsx @@ -3,29 +3,108 @@ import { Skeleton } from '@components/skeleton/skeleton'; import { cn } from '@src/lib/utils'; import { FaArrowCircleDown, FaArrowCircleUp } from 'react-icons/fa'; -export type SummaryTileProps = { - number: number | string; - label: string | JSX.Element; - delta: string; +// Component to display the main number +const NumberDisplay = ({ loading, numberString }) => + loading ? ( + + ) : ( +
{numberString}
+ ); + +// Component to display the label +const LabelDisplay = ({ loading, label }) => + loading ? ( + + ) : ( +
{label}
+ ); + +// Component to display the delta value with arrow +const DeltaDisplay = ({ loading, Arrow, deltaString, deltaClass, stacked }) => ( +
+ {loading ? ( + + ) : deltaString ? ( + // Show the arrow only if there is a delta value. + <> + +  {deltaString}  + Change + + ) : ( + // Place the invisble arrow as a spacer if there is no delta value. + // If stacked, don't put the spacer. + !stacked && + )} +
+); + +type DefaultNumProps = { + current?: number; + previous?: number; +}; +type CustomNumProps = { + number?: number | string; + delta?: string; negative?: boolean; +}; +export type SummaryTileNumProps = DefaultNumProps & + CustomNumProps & { + label?: string | JSX.Element; + negativeIsGood?: boolean; + }; + +export type SummaryTileProps = SummaryTileNumProps & { + loading?: boolean; className?: string; stacked?: boolean; - loading?: boolean; }; const SummaryTile = ({ + current, + previous, number, label, delta, negative, + negativeIsGood = false, + stacked = false, + loading = false, className, - stacked, - loading, }: SummaryTileProps) => { - const deltaClass = negative ? '~text-danger' : '~text-beryl'; - const Arrow = negative ? FaArrowCircleDown : FaArrowCircleUp; - const numberString = - typeof number === 'number' ? number.toLocaleString('en-US') : number; + // Determine whether to use custom or default formatting. + const noCustomFormatting = current !== undefined && previous !== undefined; + + // Function to get the number as a string with formatting. + const getNumberString = () => { + if (noCustomFormatting) return current.toLocaleString('en-US'); + return ( + current?.toLocaleString('en-US') || + (typeof number === 'number' ? number.toLocaleString('en-US') : number) + ); + }; + + // Function to calculate and get the delta string. + const getDeltaString = () => { + if (noCustomFormatting) { + const delta = ((current - previous) / previous) * 100; + return `${Math.round(delta).toLocaleString('en-US')}%`; + } + return delta; + }; + + // Function to determine if the number is negative. + const isNegative = noCustomFormatting ? current < previous : negative; + + // Function to determine if the delta is good or not. + const isDeltaGood = isNegative ? !negativeIsGood : negativeIsGood; + + // Classes and components based on conditions. + const deltaClass = isDeltaGood ? '~text-danger' : '~text-beryl'; + const Arrow = isNegative ? FaArrowCircleDown : FaArrowCircleUp; + return (
{!stacked &&
} {/* spacer */} - {loading ? ( - - ) : ( -
{numberString}
- )} +

- {loading ? ( - - ) : ( -

{label}
- )} +

-
- {loading ? ( - - ) : ( - <> - -  {delta}  - Change - - )} -
+ +
); From 72c55c9d30929037d17a28325574c2ab81d2714e Mon Sep 17 00:00:00 2001 From: Scott Hetrick Date: Thu, 9 Nov 2023 08:22:34 -0800 Subject: [PATCH 2/3] Optimized Summary Tile --- .../summary-tile/summary-tile.stories.tsx | 10 +++++----- src/reports/summary-tile/summary-tile.tsx | 20 ++++++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/reports/summary-tile/summary-tile.stories.tsx b/src/reports/summary-tile/summary-tile.stories.tsx index 6a6d622..c38e933 100644 --- a/src/reports/summary-tile/summary-tile.stories.tsx +++ b/src/reports/summary-tile/summary-tile.stories.tsx @@ -30,19 +30,19 @@ const data: SummaryTileNumProps[] = [ }, { label: 'Page Views', - number: 11674, + current: 11674, }, ]; const customData: SummaryTileNumProps[] = [ { - number: '1:30', + current: '1:30', label: 'Average Session Duration', delta: '-3 Second', negative: true, }, { - number: '0:10', + current: '0:10', label: 'Average Page Load', delta: '-8 Second', negative: true, @@ -58,7 +58,7 @@ const stackedData: SummaryTileNumProps[] = [ label: 'Total Leads', }, { - number: 57997, + current: 57997, label: ( <> @@ -77,7 +77,7 @@ const stackedData: SummaryTileNumProps[] = [ ), }, { - number: 2446, + current: 2446, label: ( <> diff --git a/src/reports/summary-tile/summary-tile.tsx b/src/reports/summary-tile/summary-tile.tsx index c950924..3b1999e 100644 --- a/src/reports/summary-tile/summary-tile.tsx +++ b/src/reports/summary-tile/summary-tile.tsx @@ -42,30 +42,37 @@ const DeltaDisplay = ({ loading, Arrow, deltaString, deltaClass, stacked }) => ( ); type DefaultNumProps = { - current?: number; + /** The previous value. If no value is supplied, custom formatting is used. */ previous?: number; }; type CustomNumProps = { - number?: number | string; + /** FOR CUSTOM FORMATTING: What number + unit to show as the change, i.e. "3%", "-8 second". */ delta?: string; + /** FOR CUSTOM FORMATTING: Whether to show negative colors + arrows. */ negative?: boolean; }; export type SummaryTileNumProps = DefaultNumProps & CustomNumProps & { + /** The current value. */ + current?: number | string; + /** Label, i.e. "Total Sales" or "Users", or a JSX component to go where the label would be. */ label?: string | JSX.Element; + /** Should the colors for negative & positive be swapped? */ negativeIsGood?: boolean; }; export type SummaryTileProps = SummaryTileNumProps & { + /** Whether to display loading placeholder. */ loading?: boolean; + /** Classnames for the Card container. */ className?: string; + /** Whether to remove y-padding to display the tile as one of a stacked tile group. */ stacked?: boolean; }; const SummaryTile = ({ current, previous, - number, label, delta, negative, @@ -75,14 +82,17 @@ const SummaryTile = ({ className, }: SummaryTileProps) => { // Determine whether to use custom or default formatting. - const noCustomFormatting = current !== undefined && previous !== undefined; + const noCustomFormatting = + current !== undefined && + typeof current === 'number' && + previous !== undefined; // Function to get the number as a string with formatting. const getNumberString = () => { if (noCustomFormatting) return current.toLocaleString('en-US'); return ( current?.toLocaleString('en-US') || - (typeof number === 'number' ? number.toLocaleString('en-US') : number) + (typeof current === 'number' ? current.toLocaleString('en-US') : current) ); }; From 685f2421c221e8ec3a989fa9e9daf3a8e3356e7c Mon Sep 17 00:00:00 2001 From: Scott Hetrick Date: Thu, 9 Nov 2023 08:33:20 -0800 Subject: [PATCH 3/3] Updated version number for release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bfec382..1ca41b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@broadlume/willow-ui", - "version": "0.0.1", + "version": "0.0.3", "author": { "name": "dreadhalor", "url": "https://scotthetrick.com"