-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
19253d4
commit 87675f3
Showing
9 changed files
with
309 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { InlineMetricsConfig } from './InlineMetrics.styles'; | ||
|
||
export type TrendType = 'None' | 'Positive' | 'Negative'; | ||
|
||
export type InlineMetricsProps = { | ||
metrics?: string; | ||
label?: string; | ||
trend?: TrendType; | ||
trendValue?: string; | ||
custom?: InlineMetricsConfig; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import type { Meta, StoryObj } from '@storybook/react'; | ||
|
||
import { InlineMetrics } from './InlineMetrics'; | ||
|
||
import { InlineMetricsDocs } from '@/docs-components/InlineMetricsDocs'; | ||
import { TetDocs } from '@/docs-components/TetDocs'; | ||
|
||
const meta = { | ||
title: 'Metrics / InlineMetrics', | ||
component: InlineMetrics, | ||
tags: ['autodocs'], | ||
args: {}, | ||
parameters: { | ||
backgrounds: {}, | ||
docs: { | ||
description: { | ||
component: | ||
'A set of several grouped components that displays numerical data, such as, for example, key performance indicators (KPIs). Metrics provide users with a clear, visual representation of essential statistics or progress.', | ||
}, | ||
page: () => ( | ||
<TetDocs docs="https://docs.tetrisly.com/components/in-progress/metrics"> | ||
<InlineMetricsDocs /> | ||
</TetDocs> | ||
), | ||
}, | ||
}, | ||
} satisfies Meta<typeof InlineMetrics>; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof meta>; | ||
|
||
export const Default: Story = { | ||
args: { | ||
trend: 'Negative', | ||
trendValue: '+24%', | ||
metrics: '$123.12', | ||
label: 'Total Earnings', | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import type { TrendType } from './InlineMetrics.props'; | ||
|
||
import type { BaseProps } from '@/types/BaseProps'; | ||
import { IconName } from '@/utility-types/IconName'; | ||
|
||
export type InlineMetricsConfig = { | ||
innerElements: { | ||
label: BaseProps; | ||
metric: BaseProps; | ||
trendContainer: BaseProps; | ||
trend: { trend: Partial<Record<TrendType, BaseProps>> } & BaseProps; | ||
icon: BaseProps; | ||
trendValue: BaseProps; | ||
}; | ||
} & BaseProps; | ||
|
||
export const defaultConfig = { | ||
w: 'fill', | ||
h: '', | ||
display: 'flex', | ||
flexDirection: 'column', | ||
innerElements: { | ||
trendContainer: { | ||
display: 'flex', | ||
color: '$color-content-primary', | ||
gap: '$space-component-gap-medium', | ||
}, | ||
label: { | ||
color: '$color-content-secondary', | ||
text: '$typo-body-medium', | ||
marginBottom: '$space-component-gap-medium', | ||
}, | ||
metric: { | ||
text: '$typo-header-4xLarge', | ||
color: '$color-content-primary', | ||
}, | ||
trend: { | ||
gap: '$space-component-gap-small', | ||
padding: '$space-component-padding-xSmall 0', | ||
display: 'flex', | ||
alignItems: 'center', | ||
alignSelf: 'flex-end', | ||
trend: { | ||
None: {}, | ||
Positive: { | ||
color: '$color-content-positive-secondary', | ||
}, | ||
Negative: { | ||
color: '$color-content-negative-secondary', | ||
}, | ||
}, | ||
}, | ||
icon: { | ||
display: 'flex', | ||
}, | ||
trendValue: { | ||
text: '$typo-body-strong-medium', | ||
display: 'flex', | ||
alignItems: 'end', | ||
}, | ||
}, | ||
} satisfies InlineMetricsConfig; | ||
|
||
export const inlineMetricsStyles = { | ||
defaultConfig, | ||
}; | ||
|
||
export const resolveIconName = (trend: TrendType) => { | ||
const iconConfig = { | ||
None: '20-minus', | ||
Positive: '20-trend-up', | ||
Negative: '20-trend-down', | ||
} satisfies Record<TrendType, IconName<20>>; | ||
|
||
return iconConfig[trend]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { InlineMetrics } from './InlineMetrics'; | ||
import { render } from '../../tests/render'; | ||
|
||
import { customPropTester } from '@/tests/customPropTester'; | ||
|
||
const getInlineMetrics = (jsx: JSX.Element) => { | ||
const { getByTestId } = render(jsx); | ||
return { | ||
container: getByTestId('inline-metrics'), | ||
trendContainer: getByTestId('inline-metrics-trend'), | ||
}; | ||
}; | ||
|
||
describe('Inline Metrics', () => { | ||
customPropTester(<InlineMetrics />, { | ||
containerId: 'inline-metrics', | ||
props: { | ||
trend: ['Negative', 'None', 'Positive'], | ||
}, | ||
}); | ||
|
||
it('should render the inline metrics', () => { | ||
const { container } = getInlineMetrics(<InlineMetrics />); | ||
expect(container).toBeInTheDocument(); | ||
}); | ||
|
||
it('should render the inline metrics with trend with proper color (Positive)', () => { | ||
const { trendContainer } = getInlineMetrics( | ||
<InlineMetrics trend="Positive" />, | ||
); | ||
expect(trendContainer).toHaveStyle('color: rgb(29, 124, 77)'); | ||
}); | ||
|
||
it('should render the inline metrics with trend with proper color (None)', () => { | ||
const { trendContainer } = getInlineMetrics(<InlineMetrics trend="None" />); | ||
expect(trendContainer).toHaveStyle('color: rgb(39, 46, 53)'); | ||
}); | ||
|
||
it('should render the inline metrics with trend with proper color (Negative)', () => { | ||
const { trendContainer } = getInlineMetrics( | ||
<InlineMetrics trend="Negative" />, | ||
); | ||
expect(trendContainer).toHaveStyle('color: rgb(197, 52, 52)'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { Icon } from '@virtuslab/tetrisly-icons'; | ||
import { MarginProps } from '@xstyled/styled-components'; | ||
import { type FC, useMemo } from 'react'; | ||
|
||
import { InlineMetricsProps } from './InlineMetrics.props'; | ||
import { resolveIconName } from './InlineMetrics.styles'; | ||
import { stylesBuilder } from './stylesBuilder'; | ||
import { Label } from '../Label'; | ||
|
||
import { tet } from '@/tetrisly'; | ||
|
||
export const InlineMetrics: FC<InlineMetricsProps & MarginProps> = ({ | ||
metrics, | ||
label, | ||
trend = 'None', | ||
trendValue, | ||
custom, | ||
...restProps | ||
}) => { | ||
const styles = useMemo( | ||
() => stylesBuilder({ trend, custom }), | ||
[trend, custom], | ||
); | ||
|
||
const iconName = useMemo(() => resolveIconName(trend), [trend]); | ||
|
||
return ( | ||
<tet.div {...styles.container} data-testid="inline-metrics" {...restProps}> | ||
{label && ( | ||
<Label | ||
label={label} | ||
{...styles.label} | ||
data-testid="inline-metrics-label" | ||
/> | ||
)} | ||
|
||
<tet.div | ||
{...styles.trendContainer} | ||
data-testid="inline-metrics-trend-container" | ||
> | ||
<tet.div {...styles.metric} data-testid="inline-metrics-metric"> | ||
{metrics} | ||
</tet.div> | ||
<tet.div {...styles.trend} data-testid="inline-metrics-trend"> | ||
<Icon {...styles.icon} name={iconName} /> | ||
<tet.span | ||
{...styles.trendValue} | ||
data-testid="inline-metrics-trend-value" | ||
> | ||
{trendValue} | ||
</tet.span> | ||
</tet.div> | ||
</tet.div> | ||
</tet.div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { InlineMetrics } from './InlineMetrics'; | ||
export type { InlineMetricsProps } from './InlineMetrics.props'; | ||
export { inlineMetricsStyles } from './InlineMetrics.styles'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { InlineMetricsProps, TrendType } from './InlineMetrics.props'; | ||
import { defaultConfig } from './InlineMetrics.styles'; | ||
|
||
import { mergeConfigWithCustom } from '@/services'; | ||
|
||
type StylesBuilderParams = { | ||
trend: TrendType; | ||
custom: InlineMetricsProps['custom']; | ||
}; | ||
|
||
export const stylesBuilder = ({ trend, custom }: StylesBuilderParams) => { | ||
const { innerElements, ...restStyles } = mergeConfigWithCustom({ | ||
defaultConfig, | ||
custom, | ||
}); | ||
const { trend: trendContainer } = innerElements; | ||
const { trend: trendStyles, ...restTrendStyles } = trendContainer; | ||
|
||
const trendContainerStyles = { ...trendStyles[trend], ...restTrendStyles }; | ||
|
||
return { | ||
container: restStyles, | ||
...innerElements, | ||
trend: trendContainerStyles, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { InlineMetrics } from '@/components/InlineMetrics/InlineMetrics'; | ||
import { TrendType } from '@/components/InlineMetrics/InlineMetrics.props'; | ||
import { tet } from '@/tetrisly'; | ||
|
||
const trends: TrendType[] = ['None', 'Positive', 'Negative'] as const; | ||
const intentNames: Record<TrendType, string> = { | ||
None: 'Neutral', | ||
Positive: 'Positive', | ||
Negative: 'Negative', | ||
}; | ||
|
||
export const InlineMetricsDocs = () => ( | ||
<tet.section py="$space-component-padding-4xLarge"> | ||
<tet.div px="$dimension-800" py="$dimension-300"> | ||
<tet.div display="flex"> | ||
{trends.map((trend) => ( | ||
<tet.section | ||
key={trend} | ||
display="flex" | ||
flexDirection="column" | ||
px="$dimension-400" | ||
my="auto" | ||
> | ||
<tet.div | ||
color="$color-content-secondary" | ||
text="$typo-body-large" | ||
borderBottom="1px solid" | ||
borderColor="$color-border-default" | ||
> | ||
Intent: {intentNames[trend]} | ||
</tet.div> | ||
<tet.div | ||
key={trend} | ||
display="flex" | ||
flexBasis="100px" | ||
flexShrink="0" | ||
flexGrow="1" | ||
mt={40} | ||
> | ||
<InlineMetrics | ||
trend={trend} | ||
trendValue="24%" | ||
metrics="$123.12" | ||
label="Total Earnings" | ||
/> | ||
</tet.div> | ||
</tet.section> | ||
))} | ||
</tet.div> | ||
</tet.div> | ||
</tet.section> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters