Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import DxcBulletedList from "./bulleted-list/BulletedList";
import DxcGrid from "./grid/Grid";
import DxcImage from "./image/Image";
import DxcContainer from "./container/Container";
import DxcStatusLight from "./status-light/StatusLight";

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

Expand Down Expand Up @@ -93,4 +94,5 @@ export {
DxcGrid,
DxcImage,
DxcContainer,
DxcStatusLight,
};
74 changes: 74 additions & 0 deletions lib/src/status-light/StatusLight.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from "react";
import Title from "../../.storybook/components/Title";
import ExampleContainer from "../../.storybook/components/ExampleContainer";
import DxcStatusLight from "./StatusLight";

export default {
title: "Status Light",
component: DxcStatusLight,
};

export const Chromatic = () => (
<>
<ExampleContainer>
<Title title="Default light small" theme="light" level={4} />
<DxcStatusLight label="StatusLight" size="small" />
</ExampleContainer>
<ExampleContainer>
<Title title="Default light medium" theme="light" level={4} />
<DxcStatusLight label="StatusLight" />
</ExampleContainer>
<ExampleContainer>
<Title title="Default light large" theme="light" level={4} />
<DxcStatusLight label="StatusLight" size="large" />
</ExampleContainer>
<ExampleContainer>
<Title title="Info light small" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="info" size="small" />
</ExampleContainer>
<ExampleContainer>
<Title title="Info light medium" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="info" />
</ExampleContainer>
<ExampleContainer>
<Title title="Info light large" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="info" size="large" />
</ExampleContainer>
<ExampleContainer>
<Title title="Success light small" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="success" size="small" />
</ExampleContainer>
<ExampleContainer>
<Title title="Success lights medium" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="success" />
</ExampleContainer>
<ExampleContainer>
<Title title="Success lights large" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="success" size="large" />
</ExampleContainer>
<ExampleContainer>
<Title title="Warning light small" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="warning" size="small" />
</ExampleContainer>
<ExampleContainer>
<Title title="Warning light medium" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="warning" />
</ExampleContainer>
<ExampleContainer>
<Title title="Warning light large" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="warning" size="large" />
</ExampleContainer>
<ExampleContainer>
<Title title="Error light small" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="error" size="small" />
</ExampleContainer>
<ExampleContainer>
<Title title="Error lights medium" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="error" />
</ExampleContainer>
<ExampleContainer>
<Title title="Error lights large" theme="light" level={4} />
<DxcStatusLight label="StatusLight" mode="error" size="large" />
</ExampleContainer>
</>
);
18 changes: 18 additions & 0 deletions lib/src/status-light/StatusLight.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from "react";
import { render } from "@testing-library/react";
import DxcStatusLight from "./StatusLight.tsx";

describe("StatusLight component tests", () => {
test("StatusLight renders with correct label", () => {
const { getByText } = render(<DxcStatusLight label="Status Light Test"></DxcStatusLight>);
expect(getByText("Status Light Test")).toBeTruthy();
});

test("StatusLight applies accessibility attributes", () => {
const { getByTestId } = render(<DxcStatusLight label="Status Light Test" />);
const statusLightContainer = getByTestId("status_light-container");
const statusDot = getByTestId("status-dot");
expect(statusLightContainer.getAttribute("aria-label")).toBe("default: Status Light Test");
expect(statusDot.getAttribute("aria-hidden")).toBe("true");
});
});
72 changes: 72 additions & 0 deletions lib/src/status-light/StatusLight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from "react";
import styled from "styled-components";
import StatusLightPropsType from "./types";
import CoreTokens from "../common/coreTokens";

const DxcStatusLight = ({ mode = "default", label, size = "medium" }: StatusLightPropsType): JSX.Element => {
return (
<StatusLightContainer size={size} aria-label={`${mode}: ${label}`} data-testid="status_light-container">
<StatusDot mode={mode} size={size} aria-hidden="true" data-testid="status-dot" />
<StatusLabel mode={mode} size={size}>
{label}
</StatusLabel>
</StatusLightContainer>
);
};

const StatusLightContainer = styled.div<{ size: StatusLightPropsType["size"] }>`
display: inline-flex;
align-items: center;
gap: ${CoreTokens.spacing_8};
`;

const StatusDot = styled.div<{
mode: StatusLightPropsType["mode"];
size: StatusLightPropsType["size"];
}>`
width: ${({ size }) =>
(size === "small" && CoreTokens.type_scale_01) ||
(size === "medium" && CoreTokens.type_scale_02) ||
(size === "large" && CoreTokens.type_scale_03) ||
CoreTokens.type_scale_02};
height: ${({ size }) =>
(size === "small" && CoreTokens.type_scale_01) ||
(size === "medium" && CoreTokens.type_scale_02) ||
(size === "large" && CoreTokens.type_scale_03) ||
CoreTokens.type_scale_02};
border-radius: 50%;
background-color: ${({ mode }) =>
(mode === "default" && CoreTokens.color_grey_700) ||
(mode === "error" && CoreTokens.color_red_700) ||
(mode === "info" && CoreTokens.color_blue_700) ||
(mode === "success" && CoreTokens.color_green_700) ||
(mode === "warning" && CoreTokens.color_orange_700) ||
CoreTokens.color_grey_700};
`;

const StatusLabel = styled.span<{
mode: StatusLightPropsType["mode"];
size: StatusLightPropsType["size"];
}>`
font-size: ${({ size }) =>
(size === "small" && CoreTokens.type_scale_01) ||
(size === "medium" && CoreTokens.type_scale_02) ||
(size === "large" && CoreTokens.type_scale_03) ||
CoreTokens.type_scale_02};
font-family: ${CoreTokens.type_sans};
font-style: ${CoreTokens.type_normal};
font-weight: ${CoreTokens.type_semibold};
color: ${({ mode }) =>
(mode === "default" && CoreTokens.color_grey_700) ||
(mode === "error" && CoreTokens.color_red_700) ||
(mode === "info" && CoreTokens.color_blue_700) ||
(mode === "success" && CoreTokens.color_green_700) ||
(mode === "warning" && CoreTokens.color_orange_700) ||
CoreTokens.color_grey_700};
text-align: center;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
`;

export default DxcStatusLight;
19 changes: 19 additions & 0 deletions lib/src/status-light/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
type Mode = "default" | "info" | "success" | "warning" | "error";
type Size = "small" | "medium" | "large";

type Props = {
/**
* It will define the color of the light based on its semantic meaning.
*/
mode?: Mode;
/**
* An auxiliar text that will add some context to the status.
*/
label: string;
/**
* Size of the component. Should be defined based on its importance and/or available space.
*/
size?: Size;
};

export default Props;
21 changes: 21 additions & 0 deletions website/pages/components/status-light/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Head from "next/head";
import type { ReactElement } from "react";
import StatusLightCodePage from "../../../screens/components/status-light/code/StatusLightCodePage";
import StatusLightPageLayout from "../../../screens/components/status-light/StatusLightPageLayout";

const Index = () => {
return (
<>
<Head>
<title>Status Light — Halstack Design System</title>
</Head>
<StatusLightCodePage></StatusLightCodePage>
</>
);
};

Index.getLayout = function getLayout(page: ReactElement) {
return <StatusLightPageLayout>{page}</StatusLightPageLayout>;
};

export default Index;
1 change: 1 addition & 0 deletions website/screens/common/componentList.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ exports.componentsList = [
{ label: "Sidenav", path: "/components/sidenav", status: "Ready" },
{ label: "Slider", path: "/components/slider", status: "Ready" },
{ label: "Spinner", path: "/components/spinner", status: "Ready" },
{ label: "Status Light", path: "/components/status-light", status: "Experimental" },
{ label: "Switch", path: "/components/switch", status: "Ready" },
{ label: "Table", path: "/components/table", status: "Ready" },
{ label: "Tabs", path: "/components/tabs", status: "Ready" },
Expand Down
27 changes: 27 additions & 0 deletions website/screens/components/status-light/StatusLightPageLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { DxcParagraph, DxcFlex } from "@dxc-technology/halstack-react";
import PageHeading from "@/common/PageHeading";
import TabsPageHeading from "@/common/TabsPageLayout";
import ComponentHeading from "@/common/ComponentHeading";

const StatusLightPageHeading = ({ children }: { children: React.ReactNode }) => {
const tabs = [
{ label: "Code", path: "/components/status-light" },
];

return (
<DxcFlex direction="column" gap="3rem">
<PageHeading>
<DxcFlex direction="column" gap="2rem">
<ComponentHeading name="Status Light" />
<DxcParagraph>
Status Lights, as semantic elements, allow the user to display the completion status of tasks, processes and more.
</DxcParagraph>
<TabsPageHeading tabs={tabs}></TabsPageHeading>
</DxcFlex>
</PageHeading>
{children}
</DxcFlex>
);
};

export default StatusLightPageHeading;
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { DxcFlex, DxcTable } from "@dxc-technology/halstack-react";
import QuickNavContainer from "@/common/QuickNavContainer";
import QuickNavContainerLayout from "@/common/QuickNavContainerLayout";
import DocFooter from "@/common/DocFooter";
import TableCode from "@/common/TableCode";

const sections = [
{
title: "Props",
content: (
<DxcTable>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td>mode</td>
<td>
<TableCode>
'default' | 'info' | 'success' | 'warning' | 'error'
</TableCode>
</td>
<td>
It will define the color of the light based on its semantic
meaning.
</td>
<td>
<TableCode>'default'</TableCode>
</td>
</tr>
<tr>
<td>label</td>
<td>
<TableCode>string</TableCode>
</td>
<td>
An auxiliar text that will add some context to the status.
</td>
<td>-</td>
</tr>
<tr>
<td>size</td>
<td>
<TableCode>'small' | 'medium' | 'large'</TableCode>
</td>
<td>
Size of the component. Should be defined based on its importance
and/or available space.
</td>
<td><TableCode>'medium'</TableCode></td>
</tr>
</tbody>
</DxcTable>
),
},
{
title: "Examples",
subSections: [
{
title: "Basic Usage",
content: <p>Examples are not available yet, they will be added soon.</p>
},
],
},
];

const StatusLightCodePage = () => {
return (
<DxcFlex direction="column" gap="4rem">
<QuickNavContainerLayout>
<QuickNavContainer
sections={sections}
startHeadingLevel={2}
></QuickNavContainer>
</QuickNavContainerLayout>
<DocFooter githubLink="https://github.com/dxc-technology/halstack-react/blob/master/website/screens/components/status-light/code/StatusLightCodePage.tsx" />
</DxcFlex>
);
};

export default StatusLightCodePage;