Skip to content

Commit ab51f11

Browse files
feat(shape-indicator): new component (#18483)
* feat(shape-indicator): new component * fix(style): tests * fix(tests): add aria-hidden * feat: shape indicator wc * fix: fixed alignments and incomplete icon colors * fix: added overview.mdx * fix(wc): minor cleanup * fix(shape-indicator): size to text-size prop and cleanup * fix(shape-indicator): api * fix(indicator-stories): remove playground * fix(shape): avt test --------- Co-authored-by: Gururajj77 <gururajtakeshi@gmail.com>
1 parent 4ee4dc5 commit ab51f11

File tree

29 files changed

+1086
-52
lines changed

29 files changed

+1086
-52
lines changed

e2e/components/IconIndicator/IconIndicator-test.e2e.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
'use strict';
99
const { test } = require('@playwright/test');
1010
const { themes } = require('../../test-utils/env');
11-
const { snapshotStory } = require('../../test-utils/storybook');
11+
const { snapshot } = require('../../test-utils/snapshot');
12+
const { snapshotStory, visitStory } = require('../../test-utils/storybook');
1213

1314
test.describe('IconIndicator', () => {
1415
themes.forEach((theme) => {
@@ -20,6 +21,22 @@ test.describe('IconIndicator', () => {
2021
theme,
2122
});
2223
});
24+
25+
test('icon indicator size 20 @vrt', async ({ page }) => {
26+
await visitStory(page, {
27+
component: 'IconIndicator',
28+
id: 'experimental-statusindicators-unstable-iconindicator--default',
29+
theme,
30+
args: {
31+
size: '20',
32+
},
33+
});
34+
await snapshot(page, {
35+
component: 'IconIndicator',
36+
id: 'experimental-statusindicators-unstable-iconindicator--default',
37+
theme,
38+
});
39+
});
2340
});
2441
});
2542
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Copyright IBM Corp. 2016, 2023
3+
*
4+
* This source code is licensed under the Apache-2.0 license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
'use strict';
9+
import { expect, test } from '@playwright/test';
10+
import { visitStory } from '../../test-utils/storybook';
11+
12+
test.describe('@avt ShapeIndicator', () => {
13+
test('@avt-default-state', async ({ page }) => {
14+
await visitStory(page, {
15+
component: 'ShapeIndicator',
16+
id: 'experimental-statusindicators-unstable-shapeindicator--default',
17+
globals: {
18+
theme: 'white',
19+
},
20+
});
21+
await expect(page).toHaveNoACViolations('ShapeIndicator');
22+
});
23+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright IBM Corp. 2016, 2023
3+
*
4+
* This source code is licensed under the Apache-2.0 license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
'use strict';
9+
const { test } = require('@playwright/test');
10+
const { themes } = require('../../test-utils/env');
11+
const { snapshot } = require('../../test-utils/snapshot');
12+
const { snapshotStory, visitStory } = require('../../test-utils/storybook');
13+
14+
test.describe('ShapeIndicator', () => {
15+
themes.forEach((theme) => {
16+
test.describe(theme, () => {
17+
test('shape indicator @vrt', async ({ page }) => {
18+
await snapshotStory(page, {
19+
component: 'ShapeIndicator',
20+
id: 'experimental-statusindicators-unstable-shapeindicator--default',
21+
theme,
22+
});
23+
});
24+
25+
test('shape indicator text size 14 @vrt', async ({ page }) => {
26+
await visitStory(page, {
27+
component: 'ShapeIndicator',
28+
id: 'experimental-statusindicators-unstable-shapeindicator--default',
29+
theme,
30+
args: {
31+
textSize: '14',
32+
},
33+
});
34+
await snapshot(page, {
35+
component: 'ShapeIndicator',
36+
id: 'experimental-statusindicators-unstable-shapeindicator--default',
37+
theme,
38+
});
39+
});
40+
});
41+
});
42+
});

packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11078,6 +11078,47 @@ Map {
1107811078
},
1107911079
"render": [Function],
1108011080
},
11081+
"unstable__ShapeIndicator" => Object {
11082+
"$$typeof": Symbol(react.forward_ref),
11083+
"propTypes": Object {
11084+
"className": Object {
11085+
"type": "string",
11086+
},
11087+
"kind": Object {
11088+
"args": Array [
11089+
Array [
11090+
"failed",
11091+
"critical",
11092+
"high",
11093+
"medium",
11094+
"low",
11095+
"cautious",
11096+
"undefined",
11097+
"stable",
11098+
"informative",
11099+
"incomplete",
11100+
"draft",
11101+
],
11102+
],
11103+
"isRequired": true,
11104+
"type": "oneOf",
11105+
},
11106+
"label": Object {
11107+
"isRequired": true,
11108+
"type": "string",
11109+
},
11110+
"textSize": Object {
11111+
"args": Array [
11112+
Array [
11113+
12,
11114+
14,
11115+
],
11116+
],
11117+
"type": "oneOf",
11118+
},
11119+
},
11120+
"render": [Function],
11121+
},
1108111122
"unstable__Slug" => Object {
1108211123
"$$typeof": Symbol(react.forward_ref),
1108311124
"propTypes": Object {

packages/react/src/__tests__/index-test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ describe('Carbon Components React', () => {
285285
"unstable__FluidTimePickerSelect",
286286
"unstable__FluidTimePickerSkeleton",
287287
"unstable__IconIndicator",
288+
"unstable__ShapeIndicator",
288289
"unstable__Slug",
289290
"unstable__SlugActions",
290291
"unstable__SlugContent",

packages/react/src/components/IconIndicator/IconIndicator.stories.js

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,49 +20,42 @@ export default {
2020
},
2121
};
2222

23-
export const Default = () => {
23+
export const Default = (props) => {
2424
return (
2525
<div
2626
style={{
27-
display: 'grid',
28-
gridTemplateColumns: 'auto auto',
29-
columnGap: '1rem',
30-
rowGap: '0.5rem',
31-
width: 'fit-content',
27+
display: 'flex',
28+
flexFlow: 'column',
29+
rowGap: '.5rem',
3230
}}>
33-
{IconIndicatorKinds.map((type) => (
34-
<>
35-
<IconIndicator kind={type} label={type} />
36-
<IconIndicator kind={type} label={type} size={20} />
37-
</>
38-
))}
31+
<IconIndicator kind="failed" label="Failed" {...props} />
32+
<IconIndicator kind="caution-major" label="Caution major" {...props} />
33+
<IconIndicator kind="caution-minor" label="Caution minor" {...props} />
34+
<IconIndicator kind="undefined" label="Undefined" {...props} />
35+
<IconIndicator kind="succeeded" label="Succeeded" {...props} />
36+
<IconIndicator kind="normal" label="Normal" {...props} />
37+
<IconIndicator kind="in-progress" label="In progress" {...props} />
38+
<IconIndicator kind="incomplete" label="Incomplete" {...props} />
39+
<IconIndicator kind="not-started" label="Not started" {...props} />
40+
<IconIndicator kind="pending" label="Pending" {...props} />
41+
<IconIndicator kind="unknown" label="Unknown" {...props} />
42+
<IconIndicator kind="informative" label="Informative" {...props} />
3943
</div>
4044
);
4145
};
4246

43-
const PlaygroundStory = (props) => {
44-
return <IconIndicator {...props} />;
45-
};
46-
47-
export const Playground = PlaygroundStory.bind({});
48-
49-
Playground.args = {
50-
label: 'Custom label',
51-
kind: 'failed',
47+
Default.args = {
5248
size: 16,
5349
};
5450

55-
Playground.argTypes = {
51+
Default.argTypes = {
5652
label: {
5753
control: {
5854
type: 'text',
5955
},
6056
},
6157
kind: {
62-
control: {
63-
type: 'select',
64-
},
65-
options: IconIndicatorKinds,
58+
control: false,
6659
},
6760
size: {
6861
control: {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { ArgTypes, Meta } from '@storybook/blocks';
2+
3+
<Meta isTemplate />
4+
5+
# ShapeIndicator
6+
7+
[Source code](https://github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/ShapeIndicator)
8+
&nbsp;
9+
10+
{/* <!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> */}
11+
12+
## Table of Contents
13+
14+
- [Overview](#overview)
15+
- [Component API](#component-api)
16+
- [Feedback](#feedback)
17+
18+
{/* <!-- END doctoc generated TOC please keep comment here to allow auto update --> */}
19+
20+
## Overview
21+
22+
`ShapeIndicator`
23+
24+
```jsx
25+
import { ShapeIndicator as unstable__ShapeIndicator } from '@carbon/react';
26+
27+
function ExampleComponent() {
28+
return (
29+
<ShapeIndicator kind="failed" label="Failed">
30+
);
31+
}
32+
```
33+
34+
## Kind
35+
36+
Shape indicators can take the form of failed, critical, high, medium, low, cautious, undefined, stable, informative, incomplete, and draft.
37+
38+
## Text Size
39+
40+
Shape indicators have two text size options 12 and 14. The default is 12.
41+
42+
## Customizing the label
43+
44+
You can set a string to customize the label of the Shape indicator.
45+
46+
## Component API
47+
48+
<ArgTypes />
49+
50+
## Feedback
51+
52+
Help us improve this component by providing feedback, asking questions on Slack,
53+
or updating this file on
54+
[GitHub](https://github.com/carbon-design-system/carbon/edit/main/packages/react/src/components/ShapeIndicator/ShapeIndicator.mdx).
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* Copyright IBM Corp. 2025, 2025
3+
*
4+
* This source code is licensed under the Apache-2.0 license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import React from 'react';
9+
import ShapeIndicator from '.';
10+
import mdx from './ShapeIndicator.mdx';
11+
12+
export default {
13+
title: 'Experimental/StatusIndicators/unstable__ShapeIndicator',
14+
component: ShapeIndicator,
15+
parameters: {
16+
docs: {
17+
page: mdx,
18+
},
19+
},
20+
};
21+
22+
export const Default = (props) => {
23+
return (
24+
<div
25+
style={{
26+
display: 'flex',
27+
flexFlow: 'column',
28+
rowGap: '.5rem',
29+
}}>
30+
<ShapeIndicator kind="failed" label="Failed" {...props} />
31+
<ShapeIndicator kind="critical" label="Critical" {...props} />
32+
<ShapeIndicator kind="high" label="High" {...props} />
33+
<ShapeIndicator kind="medium" label="Medium" {...props} />
34+
<ShapeIndicator kind="low" label="Low" {...props} />
35+
<ShapeIndicator kind="cautious" label="Cautious" {...props} />
36+
<ShapeIndicator kind="undefined" label="Undefined" {...props} />
37+
<ShapeIndicator kind="stable" label="Stable" {...props} />
38+
<ShapeIndicator kind="informative" label="Informative" {...props} />
39+
<ShapeIndicator kind="incomplete" label="Incomplete" {...props} />
40+
<ShapeIndicator kind="draft" label="Draft" {...props} />
41+
</div>
42+
);
43+
};
44+
45+
Default.args = {
46+
textSize: 12,
47+
};
48+
49+
Default.argTypes = {
50+
label: {
51+
control: {
52+
type: 'text',
53+
},
54+
},
55+
kind: {
56+
control: false,
57+
},
58+
textSize: {
59+
control: {
60+
type: 'select',
61+
},
62+
options: [12, 14],
63+
},
64+
};
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Copyright IBM Corp. 2025, 2025
3+
*
4+
* This source code is licensed under the Apache-2.0 license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import { render, screen } from '@testing-library/react';
9+
import React from 'react';
10+
import ShapeIndicator from '../index';
11+
12+
describe('ShapeIndicator', () => {
13+
it('should use a custom label', () => {
14+
render(<ShapeIndicator kind="failed" label="label" />);
15+
expect(screen.getByText('label')).toBeInTheDocument();
16+
});
17+
18+
it('should update with textSize prop', () => {
19+
render(<ShapeIndicator kind="failed" label="label" textSize={14} />);
20+
expect(screen.getByText('label')).toHaveClass('cds--shape-indicator--14');
21+
});
22+
23+
it('should update with kind prop', () => {
24+
render(<ShapeIndicator kind="critical" label="label" size={14} />);
25+
expect(document.querySelector('svg')).toHaveClass(
26+
'cds--shape-indicator--critical'
27+
);
28+
});
29+
30+
it('should support a custom class name on the outermost element', () => {
31+
const { container } = render(
32+
<ShapeIndicator kind="failed" label="label" className="custom-class" />
33+
);
34+
expect(container.firstChild).toHaveClass('custom-class');
35+
});
36+
37+
it('should support a ref on the outermost element', () => {
38+
const ref = jest.fn();
39+
const { container } = render(
40+
<ShapeIndicator kind="failed" label="label" ref={ref} />
41+
);
42+
expect(ref).toHaveBeenCalledWith(container.firstChild);
43+
});
44+
});

0 commit comments

Comments
 (0)