Skip to content

Commit 18ade79

Browse files
authored
Merge pull request #1804 from dxc-technology/Mil4n0r/status_light-component
Added new `StatusLight` component
2 parents 1830555 + 9b392bd commit 18ade79

File tree

9 files changed

+320
-0
lines changed

9 files changed

+320
-0
lines changed

lib/src/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import DxcBulletedList from "./bulleted-list/BulletedList";
4242
import DxcGrid from "./grid/Grid";
4343
import DxcImage from "./image/Image";
4444
import DxcContainer from "./container/Container";
45+
import DxcStatusLight from "./status-light/StatusLight";
4546

4647
import HalstackContext, { HalstackProvider, HalstackLanguageContext } from "./HalstackContext";
4748

@@ -93,4 +94,5 @@ export {
9394
DxcGrid,
9495
DxcImage,
9596
DxcContainer,
97+
DxcStatusLight,
9698
};
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import React from "react";
2+
import Title from "../../.storybook/components/Title";
3+
import ExampleContainer from "../../.storybook/components/ExampleContainer";
4+
import DxcStatusLight from "./StatusLight";
5+
6+
export default {
7+
title: "Status Light",
8+
component: DxcStatusLight,
9+
};
10+
11+
export const Chromatic = () => (
12+
<>
13+
<ExampleContainer>
14+
<Title title="Default light small" theme="light" level={4} />
15+
<DxcStatusLight label="StatusLight" size="small" />
16+
</ExampleContainer>
17+
<ExampleContainer>
18+
<Title title="Default light medium" theme="light" level={4} />
19+
<DxcStatusLight label="StatusLight" />
20+
</ExampleContainer>
21+
<ExampleContainer>
22+
<Title title="Default light large" theme="light" level={4} />
23+
<DxcStatusLight label="StatusLight" size="large" />
24+
</ExampleContainer>
25+
<ExampleContainer>
26+
<Title title="Info light small" theme="light" level={4} />
27+
<DxcStatusLight label="StatusLight" mode="info" size="small" />
28+
</ExampleContainer>
29+
<ExampleContainer>
30+
<Title title="Info light medium" theme="light" level={4} />
31+
<DxcStatusLight label="StatusLight" mode="info" />
32+
</ExampleContainer>
33+
<ExampleContainer>
34+
<Title title="Info light large" theme="light" level={4} />
35+
<DxcStatusLight label="StatusLight" mode="info" size="large" />
36+
</ExampleContainer>
37+
<ExampleContainer>
38+
<Title title="Success light small" theme="light" level={4} />
39+
<DxcStatusLight label="StatusLight" mode="success" size="small" />
40+
</ExampleContainer>
41+
<ExampleContainer>
42+
<Title title="Success lights medium" theme="light" level={4} />
43+
<DxcStatusLight label="StatusLight" mode="success" />
44+
</ExampleContainer>
45+
<ExampleContainer>
46+
<Title title="Success lights large" theme="light" level={4} />
47+
<DxcStatusLight label="StatusLight" mode="success" size="large" />
48+
</ExampleContainer>
49+
<ExampleContainer>
50+
<Title title="Warning light small" theme="light" level={4} />
51+
<DxcStatusLight label="StatusLight" mode="warning" size="small" />
52+
</ExampleContainer>
53+
<ExampleContainer>
54+
<Title title="Warning light medium" theme="light" level={4} />
55+
<DxcStatusLight label="StatusLight" mode="warning" />
56+
</ExampleContainer>
57+
<ExampleContainer>
58+
<Title title="Warning light large" theme="light" level={4} />
59+
<DxcStatusLight label="StatusLight" mode="warning" size="large" />
60+
</ExampleContainer>
61+
<ExampleContainer>
62+
<Title title="Error light small" theme="light" level={4} />
63+
<DxcStatusLight label="StatusLight" mode="error" size="small" />
64+
</ExampleContainer>
65+
<ExampleContainer>
66+
<Title title="Error lights medium" theme="light" level={4} />
67+
<DxcStatusLight label="StatusLight" mode="error" />
68+
</ExampleContainer>
69+
<ExampleContainer>
70+
<Title title="Error lights large" theme="light" level={4} />
71+
<DxcStatusLight label="StatusLight" mode="error" size="large" />
72+
</ExampleContainer>
73+
</>
74+
);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React from "react";
2+
import { render } from "@testing-library/react";
3+
import DxcStatusLight from "./StatusLight.tsx";
4+
5+
describe("StatusLight component tests", () => {
6+
test("StatusLight renders with correct label", () => {
7+
const { getByText } = render(<DxcStatusLight label="Status Light Test"></DxcStatusLight>);
8+
expect(getByText("Status Light Test")).toBeTruthy();
9+
});
10+
11+
test("StatusLight applies accessibility attributes", () => {
12+
const { getByTestId } = render(<DxcStatusLight label="Status Light Test" />);
13+
const statusLightContainer = getByTestId("status_light-container");
14+
const statusDot = getByTestId("status-dot");
15+
expect(statusLightContainer.getAttribute("aria-label")).toBe("default: Status Light Test");
16+
expect(statusDot.getAttribute("aria-hidden")).toBe("true");
17+
});
18+
});
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React from "react";
2+
import styled from "styled-components";
3+
import StatusLightPropsType from "./types";
4+
import CoreTokens from "../common/coreTokens";
5+
6+
const DxcStatusLight = ({ mode = "default", label, size = "medium" }: StatusLightPropsType): JSX.Element => {
7+
return (
8+
<StatusLightContainer size={size} aria-label={`${mode}: ${label}`} data-testid="status_light-container">
9+
<StatusDot mode={mode} size={size} aria-hidden="true" data-testid="status-dot" />
10+
<StatusLabel mode={mode} size={size}>
11+
{label}
12+
</StatusLabel>
13+
</StatusLightContainer>
14+
);
15+
};
16+
17+
const StatusLightContainer = styled.div<{ size: StatusLightPropsType["size"] }>`
18+
display: inline-flex;
19+
align-items: center;
20+
gap: ${CoreTokens.spacing_8};
21+
`;
22+
23+
const StatusDot = styled.div<{
24+
mode: StatusLightPropsType["mode"];
25+
size: StatusLightPropsType["size"];
26+
}>`
27+
width: ${({ size }) =>
28+
(size === "small" && CoreTokens.type_scale_01) ||
29+
(size === "medium" && CoreTokens.type_scale_02) ||
30+
(size === "large" && CoreTokens.type_scale_03) ||
31+
CoreTokens.type_scale_02};
32+
height: ${({ size }) =>
33+
(size === "small" && CoreTokens.type_scale_01) ||
34+
(size === "medium" && CoreTokens.type_scale_02) ||
35+
(size === "large" && CoreTokens.type_scale_03) ||
36+
CoreTokens.type_scale_02};
37+
border-radius: 50%;
38+
background-color: ${({ mode }) =>
39+
(mode === "default" && CoreTokens.color_grey_700) ||
40+
(mode === "error" && CoreTokens.color_red_700) ||
41+
(mode === "info" && CoreTokens.color_blue_700) ||
42+
(mode === "success" && CoreTokens.color_green_700) ||
43+
(mode === "warning" && CoreTokens.color_orange_700) ||
44+
CoreTokens.color_grey_700};
45+
`;
46+
47+
const StatusLabel = styled.span<{
48+
mode: StatusLightPropsType["mode"];
49+
size: StatusLightPropsType["size"];
50+
}>`
51+
font-size: ${({ size }) =>
52+
(size === "small" && CoreTokens.type_scale_01) ||
53+
(size === "medium" && CoreTokens.type_scale_02) ||
54+
(size === "large" && CoreTokens.type_scale_03) ||
55+
CoreTokens.type_scale_02};
56+
font-family: ${CoreTokens.type_sans};
57+
font-style: ${CoreTokens.type_normal};
58+
font-weight: ${CoreTokens.type_semibold};
59+
color: ${({ mode }) =>
60+
(mode === "default" && CoreTokens.color_grey_700) ||
61+
(mode === "error" && CoreTokens.color_red_700) ||
62+
(mode === "info" && CoreTokens.color_blue_700) ||
63+
(mode === "success" && CoreTokens.color_green_700) ||
64+
(mode === "warning" && CoreTokens.color_orange_700) ||
65+
CoreTokens.color_grey_700};
66+
text-align: center;
67+
text-overflow: ellipsis;
68+
overflow: hidden;
69+
white-space: nowrap;
70+
`;
71+
72+
export default DxcStatusLight;

lib/src/status-light/types.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
type Mode = "default" | "info" | "success" | "warning" | "error";
2+
type Size = "small" | "medium" | "large";
3+
4+
type Props = {
5+
/**
6+
* It will define the color of the light based on its semantic meaning.
7+
*/
8+
mode?: Mode;
9+
/**
10+
* An auxiliar text that will add some context to the status.
11+
*/
12+
label: string;
13+
/**
14+
* Size of the component. Should be defined based on its importance and/or available space.
15+
*/
16+
size?: Size;
17+
};
18+
19+
export default Props;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import Head from "next/head";
2+
import type { ReactElement } from "react";
3+
import StatusLightCodePage from "../../../screens/components/status-light/code/StatusLightCodePage";
4+
import StatusLightPageLayout from "../../../screens/components/status-light/StatusLightPageLayout";
5+
6+
const Index = () => {
7+
return (
8+
<>
9+
<Head>
10+
<title>Status Light — Halstack Design System</title>
11+
</Head>
12+
<StatusLightCodePage></StatusLightCodePage>
13+
</>
14+
);
15+
};
16+
17+
Index.getLayout = function getLayout(page: ReactElement) {
18+
return <StatusLightPageLayout>{page}</StatusLightPageLayout>;
19+
};
20+
21+
export default Index;

website/screens/common/componentList.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ exports.componentsList = [
5151
{ label: "Sidenav", path: "/components/sidenav", status: "Ready" },
5252
{ label: "Slider", path: "/components/slider", status: "Ready" },
5353
{ label: "Spinner", path: "/components/spinner", status: "Ready" },
54+
{ label: "Status Light", path: "/components/status-light", status: "Experimental" },
5455
{ label: "Switch", path: "/components/switch", status: "Ready" },
5556
{ label: "Table", path: "/components/table", status: "Ready" },
5657
{ label: "Tabs", path: "/components/tabs", status: "Ready" },
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { DxcParagraph, DxcFlex } from "@dxc-technology/halstack-react";
2+
import PageHeading from "@/common/PageHeading";
3+
import TabsPageHeading from "@/common/TabsPageLayout";
4+
import ComponentHeading from "@/common/ComponentHeading";
5+
6+
const StatusLightPageHeading = ({ children }: { children: React.ReactNode }) => {
7+
const tabs = [
8+
{ label: "Code", path: "/components/status-light" },
9+
];
10+
11+
return (
12+
<DxcFlex direction="column" gap="3rem">
13+
<PageHeading>
14+
<DxcFlex direction="column" gap="2rem">
15+
<ComponentHeading name="Status Light" />
16+
<DxcParagraph>
17+
Status Lights, as semantic elements, allow the user to display the completion status of tasks, processes and more.
18+
</DxcParagraph>
19+
<TabsPageHeading tabs={tabs}></TabsPageHeading>
20+
</DxcFlex>
21+
</PageHeading>
22+
{children}
23+
</DxcFlex>
24+
);
25+
};
26+
27+
export default StatusLightPageHeading;
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { DxcFlex, DxcTable } from "@dxc-technology/halstack-react";
2+
import QuickNavContainer from "@/common/QuickNavContainer";
3+
import QuickNavContainerLayout from "@/common/QuickNavContainerLayout";
4+
import DocFooter from "@/common/DocFooter";
5+
import TableCode from "@/common/TableCode";
6+
7+
const sections = [
8+
{
9+
title: "Props",
10+
content: (
11+
<DxcTable>
12+
<thead>
13+
<tr>
14+
<th>Name</th>
15+
<th>Type</th>
16+
<th>Description</th>
17+
<th>Default</th>
18+
</tr>
19+
</thead>
20+
<tbody>
21+
<tr>
22+
<td>mode</td>
23+
<td>
24+
<TableCode>
25+
'default' | 'info' | 'success' | 'warning' | 'error'
26+
</TableCode>
27+
</td>
28+
<td>
29+
It will define the color of the light based on its semantic
30+
meaning.
31+
</td>
32+
<td>
33+
<TableCode>'default'</TableCode>
34+
</td>
35+
</tr>
36+
<tr>
37+
<td>label</td>
38+
<td>
39+
<TableCode>string</TableCode>
40+
</td>
41+
<td>
42+
An auxiliar text that will add some context to the status.
43+
</td>
44+
<td>-</td>
45+
</tr>
46+
<tr>
47+
<td>size</td>
48+
<td>
49+
<TableCode>'small' | 'medium' | 'large'</TableCode>
50+
</td>
51+
<td>
52+
Size of the component. Should be defined based on its importance
53+
and/or available space.
54+
</td>
55+
<td><TableCode>'medium'</TableCode></td>
56+
</tr>
57+
</tbody>
58+
</DxcTable>
59+
),
60+
},
61+
{
62+
title: "Examples",
63+
subSections: [
64+
{
65+
title: "Basic Usage",
66+
content: <p>Examples are not available yet, they will be added soon.</p>
67+
},
68+
],
69+
},
70+
];
71+
72+
const StatusLightCodePage = () => {
73+
return (
74+
<DxcFlex direction="column" gap="4rem">
75+
<QuickNavContainerLayout>
76+
<QuickNavContainer
77+
sections={sections}
78+
startHeadingLevel={2}
79+
></QuickNavContainer>
80+
</QuickNavContainerLayout>
81+
<DocFooter githubLink="https://github.com/dxc-technology/halstack-react/blob/master/website/screens/components/status-light/code/StatusLightCodePage.tsx" />
82+
</DxcFlex>
83+
);
84+
};
85+
86+
export default StatusLightCodePage;

0 commit comments

Comments
 (0)