Skip to content

Commit 76ac44b

Browse files
feat(TMC-2505/webapp): implement status bubble component (#5436)
* feat(TMC-2505): implement status bubble component * feat(TMC-2505): implement status bubble component * feat(TMC-2505): implement status bubble component * fix tests in forms package
1 parent 555b9f5 commit 76ac44b

16 files changed

+269
-3
lines changed

.changeset/purple-mails-run.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@talend/design-system': minor
3+
---
4+
5+
feat(TMC-2505/webapp): implement status bubble component
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
@use '@talend/design-tokens/lib/tokens' as tokens;
2+
3+
.statusBubble {
4+
display: block;
5+
width: tokens.$coral-spacing-xs;
6+
height: tokens.$coral-spacing-xs;
7+
border-radius: 50%;
8+
9+
&.beta {
10+
background-color: tokens.$coral-color-beta-icon;
11+
}
12+
13+
&.error {
14+
background-color: tokens.$coral-color-danger-icon;
15+
}
16+
17+
&.information {
18+
background-color: tokens.$coral-color-info-icon;
19+
}
20+
21+
&.success {
22+
background-color: tokens.$coral-color-success-icon;
23+
}
24+
25+
&.warning {
26+
background-color: tokens.$coral-color-warning-icon;
27+
}
28+
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { describe, expect, it } from '@jest/globals';
2+
import { render, screen } from '@testing-library/react';
3+
4+
import StatusBubble, { variants } from './StatusBubblePrimitive';
5+
6+
describe('StatusBubble', (): void => {
7+
it('Should render', (): void => {
8+
render(<StatusBubble variant={variants.success} data-testid="my-status-bubble-component" />);
9+
10+
expect(screen.getByTestId('my-status-bubble-component')).toBeVisible();
11+
});
12+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { forwardRef, Ref } from 'react';
2+
3+
import classnames from 'classnames';
4+
5+
import { DataAttributes } from '../../../types';
6+
7+
import styles from './StatusBubblePrimitive.module.scss';
8+
9+
export const variants = {
10+
beta: 'beta',
11+
error: 'error',
12+
information: 'information',
13+
success: 'success',
14+
warning: 'warning',
15+
};
16+
17+
export type StatusBubbleProps = {
18+
variant: string;
19+
} & DataAttributes;
20+
21+
const StatusBubblePrimitive = forwardRef(
22+
({ variant, ...rest }: StatusBubbleProps, ref: Ref<HTMLSpanElement>) => {
23+
return (
24+
<span className={classnames(styles.statusBubble, styles[variant])} ref={ref} {...rest} />
25+
);
26+
},
27+
);
28+
29+
StatusBubblePrimitive.displayName = 'StatusBubblePrimitive';
30+
31+
export default StatusBubblePrimitive;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { forwardRef, Ref } from 'react';
2+
3+
import { StatusBubbleProps, variants } from './Primitive/StatusBubblePrimitive';
4+
import StatusBubbleBeta from './variations/StatusBubbleBeta';
5+
import StatusBubbleError from './variations/StatusBubbleError';
6+
import StatusBubbleInformation from './variations/StatusBubbleInformation';
7+
import StatusBubbleSuccess from './variations/StatusBubbleSuccess';
8+
import StatusBubbleWarning from './variations/StatusBubbleWarning';
9+
10+
const StatusBubble = forwardRef((props: StatusBubbleProps, ref: Ref<HTMLSpanElement>) => {
11+
switch (props.variant) {
12+
case variants.beta:
13+
return <StatusBubbleBeta {...props} ref={ref} />;
14+
case variants.error:
15+
return <StatusBubbleError {...props} ref={ref} />;
16+
case variants.information:
17+
return <StatusBubbleInformation {...props} ref={ref} />;
18+
case variants.success:
19+
return <StatusBubbleSuccess {...props} ref={ref} />;
20+
case variants.warning:
21+
return <StatusBubbleWarning {...props} ref={ref} />;
22+
default:
23+
return null;
24+
}
25+
});
26+
27+
export default StatusBubble;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import StatusBubble from './StatusBubble';
2+
import StatusBubbleBeta from './variations/StatusBubbleBeta';
3+
import StatusBubbleError from './variations/StatusBubbleError';
4+
import StatusBubbleInformation from './variations/StatusBubbleInformation';
5+
import StatusBubbleSuccess from './variations/StatusBubbleSuccess';
6+
import StatusBubbleWarning from './variations/StatusBubbleWarning';
7+
8+
export {
9+
StatusBubble,
10+
StatusBubbleBeta,
11+
StatusBubbleError,
12+
StatusBubbleInformation,
13+
StatusBubbleSuccess,
14+
StatusBubbleWarning,
15+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { forwardRef, Ref } from 'react';
2+
3+
import StatusBubblePrimitive, {
4+
StatusBubbleProps,
5+
variants,
6+
} from '../Primitive/StatusBubblePrimitive';
7+
8+
export type StatusBubbleBetaProps = Omit<StatusBubbleProps, 'variant'>;
9+
10+
const StatusBubbleBeta = forwardRef((props: StatusBubbleBetaProps, ref: Ref<HTMLSpanElement>) => {
11+
return <StatusBubblePrimitive variant={variants.beta} ref={ref} {...props} />;
12+
});
13+
14+
StatusBubbleBeta.displayName = 'StatusBubbleBeta';
15+
16+
export default StatusBubbleBeta;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { forwardRef, Ref } from 'react';
2+
3+
import StatusBubblePrimitive, {
4+
StatusBubbleProps,
5+
variants,
6+
} from '../Primitive/StatusBubblePrimitive';
7+
8+
export type StatusBubbleErrorProps = Omit<StatusBubbleProps, 'variant'>;
9+
10+
const StatusBubbleError = forwardRef((props: StatusBubbleErrorProps, ref: Ref<HTMLSpanElement>) => {
11+
return <StatusBubblePrimitive variant={variants.error} ref={ref} {...props} />;
12+
});
13+
14+
StatusBubbleError.displayName = 'StatusBubbleError';
15+
16+
export default StatusBubbleError;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { forwardRef, Ref } from 'react';
2+
3+
import StatusBubblePrimitive, {
4+
StatusBubbleProps,
5+
variants,
6+
} from '../Primitive/StatusBubblePrimitive';
7+
8+
export type StatusBubbleInformationProps = Omit<StatusBubbleProps, 'variant'>;
9+
10+
const StatusBubbleInformation = forwardRef(
11+
(props: StatusBubbleInformationProps, ref: Ref<HTMLSpanElement>) => {
12+
return <StatusBubblePrimitive variant={variants.information} ref={ref} {...props} />;
13+
},
14+
);
15+
16+
StatusBubbleInformation.displayName = 'StatusBubbleInformation';
17+
18+
export default StatusBubbleInformation;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { forwardRef, Ref } from 'react';
2+
3+
import StatusBubblePrimitive, {
4+
StatusBubbleProps,
5+
variants,
6+
} from '../Primitive/StatusBubblePrimitive';
7+
8+
export type StatusBubbleSuccessProps = Omit<StatusBubbleProps, 'variant'>;
9+
10+
const StatusBubbleSuccess = forwardRef(
11+
(props: StatusBubbleSuccessProps, ref: Ref<HTMLSpanElement>) => {
12+
return <StatusBubblePrimitive variant={variants.success} ref={ref} {...props} />;
13+
},
14+
);
15+
16+
StatusBubbleSuccess.displayName = 'StatusBubbleSuccess';
17+
18+
export default StatusBubbleSuccess;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { forwardRef, Ref } from 'react';
2+
3+
import StatusBubblePrimitive, {
4+
StatusBubbleProps,
5+
variants,
6+
} from '../Primitive/StatusBubblePrimitive';
7+
8+
export type StatusBubbleWarningProps = Omit<StatusBubbleProps, 'variant'>;
9+
10+
const StatusBubbleWarning = forwardRef(
11+
(props: StatusBubbleWarningProps, ref: Ref<HTMLSpanElement>) => {
12+
return <StatusBubblePrimitive variant={variants.warning} ref={ref} {...props} />;
13+
},
14+
);
15+
16+
StatusBubbleWarning.displayName = 'StatusBubbleWarning';
17+
18+
export default StatusBubbleWarning;

packages/design-system/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export * from './components/RatioBar';
2727
export * from './components/RichRadioButton';
2828
export * from './components/Skeleton';
2929
export * from './components/Status';
30+
export * from './components/StatusBubble';
3031
export * from './components/Stepper';
3132
export * from './components/Switch';
3233
export * from './components/Tabs';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Canvas, Controls, Meta } from '@storybook/blocks';
2+
3+
import { FigmaImage } from '@talend/storybook-docs';
4+
5+
import * as Stories from './StatusBubble.stories';
6+
import { Status } from '../Status.block';
7+
8+
<Meta of={Stories} />
9+
<Status id="status" />
10+
11+
# StatusBubble
12+
13+
The status bubble component displays state information using circle shape with semantic colors
14+
15+
### Variations
16+
17+
<Canvas of={Stories.Beta} />
18+
<Canvas of={Stories.Error} />
19+
<Canvas of={Stories.Information} />
20+
<Canvas of={Stories.Success} />
21+
<Canvas of={Stories.Warning} />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {
2+
StatusBubble,
3+
StatusBubbleBeta,
4+
StatusBubbleError,
5+
StatusBubbleInformation,
6+
StatusBubbleSuccess,
7+
StatusBubbleWarning,
8+
} from '../../';
9+
import {
10+
StatusBubbleProps,
11+
variants,
12+
} from '../../components/StatusBubble/Primitive/StatusBubblePrimitive';
13+
14+
export const Beta = () => <StatusBubbleBeta />;
15+
export const Error = () => <StatusBubbleError />;
16+
export const Information = () => <StatusBubbleInformation />;
17+
export const Success = () => <StatusBubbleSuccess />;
18+
export const Warning = () => <StatusBubbleWarning />;
19+
20+
export const Usage = (props: StatusBubbleProps) => <StatusBubble {...props} />;
21+
22+
Usage.args = {
23+
variant: variants.beta,
24+
};
25+
26+
Usage.argTypes = {
27+
variant: {
28+
description: 'StatusBubble variation',
29+
options: Object.values(variants),
30+
control: {
31+
type: 'select',
32+
},
33+
},
34+
};
35+
36+
export default {
37+
title: 'Feedback/StatusBubble',
38+
component: StatusBubble,
39+
};

packages/forms/src/UIForm/fields/Date/DateTime.component.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ describe('DateTime widget', () => {
122122

123123
expect(props.onChange.mock.calls[1][1]).toMatchObject({
124124
schema: timestampSchema,
125-
value: new Date(2015, 8, 21, 0, 30, 0).getTime(),
125+
value: new Date(2015, 8, 21, 1, 30, 0).getTime(),
126126
});
127127
});
128128

packages/forms/src/UIForm/fields/TimezoneList/TimezoneList.utils.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ describe('getTimezones', () => {
9595
value: 'Africa/Freetown',
9696
},
9797
{
98-
name: '(UTC +02:00) Europe/Berlin',
99-
offset: 120,
98+
name: '(UTC +01:00) Europe/Berlin',
99+
offset: 60,
100100
timezoneName: 'Europe/Berlin',
101101
value: 'Europe/Berlin',
102102
},

0 commit comments

Comments
 (0)