Skip to content

Commit 44eb309

Browse files
authored
feat: #244 add new status indicator component (#268)
* chore: add inactive in variants story * chore: to use font weight css variable
1 parent 87ede04 commit 44eb309

File tree

8 files changed

+283
-0
lines changed

8 files changed

+283
-0
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`StatusIndicator > should render as expected 1`] = `
4+
<DocumentFragment>
5+
<div
6+
class="mocked-styled-1 el-status-indicator"
7+
>
8+
<span
9+
class="mocked-styled-0 el-status-indicator-shape"
10+
data-variant="neutral"
11+
/>
12+
Neutral
13+
</div>
14+
</DocumentFragment>
15+
`;
16+
17+
exports[`StatusIndicator > should render as expected 2`] = `
18+
<DocumentFragment>
19+
<div
20+
class="mocked-styled-1 el-status-indicator"
21+
>
22+
<span
23+
class="mocked-styled-0 el-status-indicator-shape"
24+
data-variant="success"
25+
/>
26+
Success
27+
</div>
28+
</DocumentFragment>
29+
`;
30+
31+
exports[`StatusIndicator > should render as expected 3`] = `
32+
<DocumentFragment>
33+
<div
34+
class="mocked-styled-1 el-status-indicator"
35+
>
36+
<span
37+
class="mocked-styled-0 el-status-indicator-shape"
38+
data-variant="warning"
39+
/>
40+
Warning
41+
</div>
42+
</DocumentFragment>
43+
`;
44+
45+
exports[`StatusIndicator > should render as expected 4`] = `
46+
<DocumentFragment>
47+
<div
48+
class="mocked-styled-1 el-status-indicator"
49+
>
50+
<span
51+
class="mocked-styled-0 el-status-indicator-shape"
52+
data-variant="pending"
53+
/>
54+
Pending
55+
</div>
56+
</DocumentFragment>
57+
`;
58+
59+
exports[`StatusIndicator > should render as expected 5`] = `
60+
<DocumentFragment>
61+
<div
62+
class="mocked-styled-1 el-status-indicator"
63+
>
64+
<span
65+
class="mocked-styled-0 el-status-indicator-shape"
66+
data-variant="danger"
67+
/>
68+
Danger
69+
</div>
70+
</DocumentFragment>
71+
`;
72+
73+
exports[`StatusIndicator > should render as expected 6`] = `
74+
<DocumentFragment>
75+
<div
76+
class="mocked-styled-1 el-status-indicator"
77+
>
78+
<span
79+
class="mocked-styled-0 el-status-indicator-shape"
80+
data-variant="inactive"
81+
/>
82+
Inactive
83+
</div>
84+
</DocumentFragment>
85+
`;
86+
87+
exports[`StatusIndicator > should render as expected 7`] = `
88+
<DocumentFragment>
89+
<div
90+
class="mocked-styled-1 el-status-indicator"
91+
>
92+
<span
93+
class="mocked-styled-0 el-status-indicator-shape"
94+
data-variant="accent1"
95+
/>
96+
Accent 1
97+
</div>
98+
</DocumentFragment>
99+
`;
100+
101+
exports[`StatusIndicator > should render as expected 8`] = `
102+
<DocumentFragment>
103+
<div
104+
class="mocked-styled-1 el-status-indicator"
105+
>
106+
<span
107+
class="mocked-styled-0 el-status-indicator-shape"
108+
data-variant="accent2"
109+
/>
110+
Accent 2
111+
</div>
112+
</DocumentFragment>
113+
`;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { render } from '@testing-library/react'
2+
import { StatusIndicator } from '../status-indicator'
3+
4+
describe('StatusIndicator', () => {
5+
it('should render as expected', () => {
6+
expect(render(<StatusIndicator variant="neutral">Neutral</StatusIndicator>).asFragment()).toMatchSnapshot()
7+
expect(render(<StatusIndicator variant="success">Success</StatusIndicator>).asFragment()).toMatchSnapshot()
8+
expect(render(<StatusIndicator variant="warning">Warning</StatusIndicator>).asFragment()).toMatchSnapshot()
9+
expect(render(<StatusIndicator variant="pending">Pending</StatusIndicator>).asFragment()).toMatchSnapshot()
10+
expect(render(<StatusIndicator variant="danger">Danger</StatusIndicator>).asFragment()).toMatchSnapshot()
11+
expect(render(<StatusIndicator variant="inactive">Inactive</StatusIndicator>).asFragment()).toMatchSnapshot()
12+
expect(render(<StatusIndicator variant="accent1">Accent 1</StatusIndicator>).asFragment()).toMatchSnapshot()
13+
expect(render(<StatusIndicator variant="accent2">Accent 2</StatusIndicator>).asFragment()).toMatchSnapshot()
14+
})
15+
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './status-indicator'
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Meta, Canvas, Controls } from '@storybook/blocks'
2+
import { RenderHtmlMarkup } from '../../storybook/render-html-markup'
3+
import * as StatusIndicatorStories from './status-indicator.stories'
4+
5+
<Meta of={StatusIndicatorStories} />
6+
7+
# Status Indicator
8+
9+
A Status Indicator is a low-visibility component used to highlight important information.
10+
11+
<Controls />
12+
13+
## Default
14+
15+
<Canvas of={StatusIndicatorStories.Default} />
16+
17+
<RenderHtmlMarkup of={StatusIndicatorStories.Default} />
18+
19+
## Variants
20+
21+
<Canvas of={StatusIndicatorStories.Variants} />
22+
23+
<RenderHtmlMarkup of={StatusIndicatorStories.Variants} />
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Meta } from '@storybook/react'
2+
import { StatusIndicator } from './status-indicator'
3+
import { FlexContainer } from '../layout'
4+
5+
const meta = {
6+
title: 'Components/Status Indicator',
7+
component: StatusIndicator,
8+
argTypes: {
9+
variant: {
10+
control: 'select',
11+
options: ['neutral', 'success', 'pending', 'warning', 'danger', 'inactive', 'accent1', 'accent2'],
12+
description: 'Defines the status indicator style variant.',
13+
},
14+
className: {
15+
control: 'text',
16+
description: 'CSS class for additional styling',
17+
},
18+
},
19+
} satisfies Meta<typeof StatusIndicator>
20+
21+
export default meta
22+
23+
export const Default = {
24+
args: {
25+
children: 'Status Indicator',
26+
},
27+
}
28+
29+
export const Variants = {
30+
render: ({}) => (
31+
<FlexContainer style={{ gap: 'var(--spacing-7)' }}>
32+
<StatusIndicator variant="neutral">Neutral</StatusIndicator>
33+
<StatusIndicator variant="success">Success</StatusIndicator>
34+
<StatusIndicator variant="pending">Pending</StatusIndicator>
35+
<StatusIndicator variant="warning">Warning</StatusIndicator>
36+
<StatusIndicator variant="danger">Danger</StatusIndicator>
37+
<StatusIndicator variant="inactive">Neutral</StatusIndicator>
38+
<StatusIndicator variant="accent1">Accent 1</StatusIndicator>
39+
<StatusIndicator variant="accent2">Accent 2</StatusIndicator>
40+
</FlexContainer>
41+
),
42+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { FC, HTMLAttributes, ReactNode } from 'react'
2+
import { ElStatusIndicator, ElStatusIndicatorShape } from './styles'
3+
4+
export type StatusIndicatorVariant =
5+
| 'neutral'
6+
| 'success'
7+
| 'pending'
8+
| 'warning'
9+
| 'danger'
10+
| 'inactive'
11+
| 'accent1'
12+
| 'accent2'
13+
14+
export interface StatusIndicatorProps extends HTMLAttributes<HTMLSpanElement> {
15+
/**
16+
* The variant of the status indicator, used to highlight important information
17+
*
18+
* @default "neutral"
19+
*/
20+
variant?: StatusIndicatorVariant
21+
22+
/**
23+
* The related content associated with the status indicator variant
24+
*/
25+
children: ReactNode
26+
}
27+
28+
export const StatusIndicator: FC<StatusIndicatorProps> = ({ variant = 'neutral', children, ...rest }) => {
29+
return (
30+
<ElStatusIndicator {...rest}>
31+
<ElStatusIndicatorShape data-variant={variant} />
32+
{children}
33+
</ElStatusIndicator>
34+
)
35+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { styled } from '@linaria/react'
2+
3+
export const ElStatusIndicatorShape = styled.span`
4+
width: var(--size-2);
5+
height: var(--size-2);
6+
border-radius: 100%;
7+
8+
&[data-variant='neutral'] {
9+
background: var(--icon-info);
10+
}
11+
12+
&[data-variant='success'] {
13+
background: var(--icon-success);
14+
}
15+
16+
&[data-variant='pending'] {
17+
background: var(--icon-pending);
18+
}
19+
20+
&[data-variant='warning'] {
21+
background: var(--icon-warning);
22+
}
23+
24+
&[data-variant='danger'] {
25+
background: var(--icon-error);
26+
}
27+
28+
&[data-variant='inactive'] {
29+
background: var(--icon-secondary);
30+
}
31+
32+
&[data-variant='accent1'] {
33+
background: var(--icon-accent_1);
34+
}
35+
36+
&[data-variant='accent2'] {
37+
background: var(--icon-accent_2);
38+
}
39+
`
40+
41+
export const ElStatusIndicator = styled.div`
42+
display: flex;
43+
align-items: center;
44+
gap: var(--spacing-2);
45+
46+
color: var(--text-primary);
47+
font-family: var(--font-family);
48+
font-size: var(--font-size-sm);
49+
font-style: normal;
50+
font-weight: var(--font-weight-regular);
51+
line-height: var(--line-height-sm);
52+
letter-spacing: var(--letter-spacing-sm);
53+
`

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export * from './components/select'
3131
export * from './components/searchable-dropdown'
3232
export * from './components/snack'
3333
export * from './components/deprecated-status-indicator'
34+
export * from './components/status-indicator'
3435
export * from './components/steps'
3536
export * from './components/deprecated-table'
3637
export * from './components/tabs'

0 commit comments

Comments
 (0)