Skip to content

Commit

Permalink
feat: TET-863 add Status component (#134)
Browse files Browse the repository at this point in the history
* feat: TET-863 add Status component

* feat: TET-863 add type to an import

Co-authored-by: Mateusz Wlekliński <[email protected]>

* feat: TET-863 review changes

* feat: TET-863 review changes

* feat: TET-863 fix styling

* feat: TET-863 change required prop

* feat: TET-863 move stylesBuilder into main component folder

* feat: TET-863-fix-build

* feat: TET-863 fix dot styles

---------

Co-authored-by: Mateusz Wlekliński <[email protected]>
  • Loading branch information
karolinaszarek and mwleklinski authored Apr 25, 2024
1 parent 05eb801 commit c81b1a6
Show file tree
Hide file tree
Showing 10 changed files with 527 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/components/Status/Status.props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { StatusConfig } from './Status.styles';
import type { StatusAppearance } from './StatusAppearance.type';
import type { StatusEmphasis } from './StatusEmphasis.type';

export type StatusProps = {
appearance?: StatusAppearance;
custom?: StatusConfig;
emphasis?: StatusEmphasis;
label: string;
};
49 changes: 49 additions & 0 deletions src/components/Status/Status.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Meta, StoryObj } from '@storybook/react';

import { Status } from './Status';
import { StatusEmphasis } from './StatusEmphasis.type';

import { StatusDocs } from '@/docs-components/StatusDocs';
import { TetDocs } from '@/docs-components/TetDocs';

const meta = {
title: 'Status',
component: Status,
tags: ['autodocs'],
argTypes: {
emphasis: {
control: {
type: 'select',
options: ['high', 'medium', 'low'] satisfies StatusEmphasis[],
},
},
},
args: {
appearance: 'grey',
emphasis: 'high',
},
parameters: {
docs: {
description: {
component:
'An indicator that conveys the current state or condition of a process, item, or user. Status indicators often use colors, icons, or text to communicate information, such as online presence, approval, or completion.',
},
page: () => (
<TetDocs docs="https://docs.tetrisly.com/components/in-progress/status">
<StatusDocs />
</TetDocs>
),
},
},
} satisfies Meta<typeof Status>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
appearance: 'grey',
emphasis: 'high',
label: 'status',
},
};
214 changes: 214 additions & 0 deletions src/components/Status/Status.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
import type { StatusAppearance } from './StatusAppearance.type';

import { BaseProps } from '@/types';

export type StatusConfig = {
appearance?: Partial<
Record<
StatusAppearance,
{ emphasis?: Partial<Record<'high' | 'medium' | 'low', BaseProps>> }
>
>;
dot: {
appearance: Partial<
Record<
StatusAppearance,
{ emphasis?: Partial<Record<'high' | 'medium' | 'low', BaseProps>> }
>
>;
} & BaseProps<'appearance'>;
hasLabel?: BaseProps;
innerElements: {
label?: BaseProps;
};
} & BaseProps<'appearance'>;

export const defaultConfig = {
display: 'flex',
w: 'fit-content',
h: '$size-xSmall',
gap: '$space-component-gap-small',
alignItems: 'center',
text: '$typo-body-medium',
dot: {
w: '8px',
h: '8px',
borderRadius: '$border-radius-full',
appearance: {
grey: {
emphasis: {
high: {
backgroundColor: '$color-nonSemantic-white-content-primary',
},
medium: {
backgroundColor: '$color-nonSemantic-grey-background-strong',
},
low: {
backgroundColor: '$color-nonSemantic-grey-background-strong',
},
},
},
blue: {
emphasis: {
high: {
backgroundColor: '$color-nonSemantic-white-content-primary',
},
medium: {
backgroundColor: '$color-nonSemantic-blue-background-strong',
},
low: {
backgroundColor: '$color-nonSemantic-blue-background-strong',
},
},
},
green: {
emphasis: {
high: {
backgroundColor: '$color-nonSemantic-white-content-primary',
},
medium: {
backgroundColor: '$color-nonSemantic-green-background-strong',
},
low: {
backgroundColor: '$color-nonSemantic-green-background-strong',
},
},
},
red: {
emphasis: {
high: {
backgroundColor: '$color-nonSemantic-white-content-primary',
},
medium: {
backgroundColor: '$color-nonSemantic-red-background-strong',
},
low: {
backgroundColor: '$color-nonSemantic-red-background-strong',
},
},
},
orange: {
emphasis: {
high: {
backgroundColor: '$color-nonSemantic-grey-content-primary',
},
medium: {
backgroundColor: '$color-nonSemantic-orange-background-strong',
},
low: {
backgroundColor: '$color-nonSemantic-orange-background-strong',
},
},
},
},
},
appearance: {
grey: {
emphasis: {
high: {
backgroundColor: '$color-nonSemantic-grey-background-strong',
color: '$color-nonSemantic-white-content-primary',
p: '$space-component-padding-null $space-component-padding-small',
borderRadius: '$border-radius-medium',
},
medium: {
backgroundColor: '$color-nonSemantic-grey-background-muted',
color: '$color-nonSemantic-grey-content-primary',
p: '$space-component-padding-null $space-component-padding-small',
borderRadius: '$border-radius-medium',
},
low: {
backgroundColor: '$color-transparent',
color: '$color-nonSemantic-grey-content-primary',
borderRadius: '$border-radius-medium',
},
},
},
blue: {
emphasis: {
high: {
backgroundColor: '$color-nonSemantic-blue-background-strong',
color: '$color-nonSemantic-white-content-primary',
p: '$space-component-padding-null $space-component-padding-small',
borderRadius: '$border-radius-medium',
},
medium: {
backgroundColor: '$color-nonSemantic-blue-background-muted',
color: '$color-nonSemantic-blue-content-primary',
p: '$space-component-padding-null $space-component-padding-small',
borderRadius: '$border-radius-medium',
},
low: {
backgroundColor: '$color-transparent',
color: '$color-nonSemantic-blue-content-primary',
},
},
},
green: {
emphasis: {
high: {
color: '$color-nonSemantic-white-content-primary',
backgroundColor: '$color-nonSemantic-green-background-strong',
p: '$space-component-padding-null $space-component-padding-small',
borderRadius: '$border-radius-medium',
},
medium: {
color: '$color-nonSemantic-green-content-primary',
backgroundColor: '$color-nonSemantic-green-background-muted',
p: '$space-component-padding-null $space-component-padding-small',
borderRadius: '$border-radius-medium',
},
low: {
color: '$color-nonSemantic-green-content-primary',
},
},
},
red: {
emphasis: {
high: {
color: '$color-nonSemantic-white-content-primary',
backgroundColor: '$color-nonSemantic-red-background-strong',
p: '$space-component-padding-null $space-component-padding-small',
borderRadius: '$border-radius-medium',
},
medium: {
color: '$color-nonSemantic-red-content-primary',
backgroundColor: '$color-nonSemantic-red-background-muted',
p: '$space-component-padding-null $space-component-padding-small',
borderRadius: '$border-radius-medium',
},
low: {
color: '$color-nonSemantic-red-content-primary',
backgroundColor: '$color-transparent',
},
},
},
orange: {
emphasis: {
high: {
backgroundColor: '$color-nonSemantic-orange-background-strong',
color: '$color-nonSemantic-grey-content-primary',
p: '$space-component-padding-null $space-component-padding-small',
borderRadius: '$border-radius-medium',
},
medium: {
color: '$color-nonSemantic-orange-content-primary',
backgroundColor: '$color-nonSemantic-orange-background-muted',
p: '$space-component-padding-null $space-component-padding-small',
borderRadius: '$border-radius-medium',
},
low: {
color: '$color-nonSemantic-orange-content-primary',
backgroundColor: '$color-transparent',
},
},
},
},
innerElements: {
label: {},
},
} satisfies StatusConfig;

export const statusStyles = {
defaultConfig,
};
117 changes: 117 additions & 0 deletions src/components/Status/Status.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { Status } from './Status';
import { render } from '../../tests/render';

import { customPropTester } from '@/tests/customPropTester';

const getStatus = (jsx: JSX.Element) => {
const { getByTestId } = render(jsx);
return {
status: getByTestId('status'),
dot: getByTestId('status-dot'),
};
};

describe('Status', () => {
it('should render the status', () => {
const { status } = getStatus(<Status label="label" />);
expect(status).toBeInTheDocument();
});

it('should render a correct color (grey, high)', () => {
const { status, dot } = getStatus(
<Status appearance="grey" emphasis="high" label="label" />,
);
expect(status).toHaveStyle(
'background-color: rgb(85, 95, 109); color: rgb(255, 255, 255)',
);
expect(dot).toHaveStyle('background-color: rgb(255, 255, 255)');
});

it('should render a correct color (grey, medium)', () => {
const { status, dot } = getStatus(
<Status appearance="grey" emphasis="medium" label="label" />,
);
expect(status).toHaveStyle(
'background-color: rgb(222, 227, 231); color: rgb(39, 46, 53)',
);
expect(dot).toHaveStyle('background-color: rgb(85, 95, 109)');
});

it('should render a correct color (grey, low)', () => {
const { status, dot } = getStatus(
<Status appearance="grey" emphasis="low" label="label" />,
);
expect(status).toHaveStyle(
'background-color: rgba(255, 255, 255, 0); color: rgb(39, 46, 53)',
);
expect(dot).toHaveStyle('background-color: rgb(85, 95, 109)');
});

it('should render a correct color (blue, high)', () => {
const { status, dot } = getStatus(
<Status appearance="blue" emphasis="high" label="label" />,
);
expect(status).toHaveStyle(
'background-color: rgb(48, 98, 212); color: rgb(255, 255, 255)',
);
expect(dot).toHaveStyle('background-color: rgb(255, 255, 255)');
});

it('should render a correct color (green, high)', () => {
const { status, dot } = getStatus(
<Status appearance="green" emphasis="high" label="label" />,
);
expect(status).toHaveStyle(
'background-color: rgb(29, 124, 77); color: rgb(255, 255, 255)',
);
expect(dot).toHaveStyle('background-color: rgb(255, 255, 255)');
});

it('should render a correct color (red, high)', () => {
const { status, dot } = getStatus(
<Status appearance="red" emphasis="high" label="label" />,
);
expect(status).toHaveStyle(
'background-color: rgb(197, 52, 52); color: rgb(255, 255, 255)',
);
expect(dot).toHaveStyle('background-color: rgb(255, 255, 255)');
});

it('should render a correct color (orange, high)', () => {
const { status, dot } = getStatus(
<Status appearance="orange" emphasis="high" label="label" />,
);
expect(status).toHaveStyle(
'background-color: rgb(245, 150, 56); color: rgb(39, 46, 53)',
);
expect(dot).toHaveStyle('background-color: rgb(39, 46, 53)');
});

it('should render a correct color (orange, medium)', () => {
const { status, dot } = getStatus(
<Status appearance="orange" emphasis="medium" label="label" />,
);
expect(status).toHaveStyle(
'background-color: rgb(252, 222, 192); color: rgb(122, 69, 16)',
);
expect(dot).toHaveStyle('background-color: rgb(245, 150, 56)');
});

it('should render a correct color (orange, low)', () => {
const { status, dot } = getStatus(
<Status appearance="orange" emphasis="low" label="label" />,
);
expect(status).toHaveStyle(
'background-color: rgba(255, 255, 255, 0); color: rgb(122, 69, 16)',
);
expect(dot).toHaveStyle('background-color: rgb(245, 150, 56)');
});

customPropTester(<Status label="label" />, {
containerId: 'status',
props: {
appearance: ['grey', 'blue', 'green', 'red', 'orange'],
emphasis: ['high', 'medium', 'low'],
},
});
});
Loading

0 comments on commit c81b1a6

Please sign in to comment.