Skip to content

Commit

Permalink
Merge pull request #1804 from dxc-technology/Mil4n0r/status_light-com…
Browse files Browse the repository at this point in the history
…ponent

Added new `StatusLight` component
  • Loading branch information
jsuarezgonz authored Feb 12, 2024
2 parents 1830555 + 9b392bd commit 18ade79
Show file tree
Hide file tree
Showing 9 changed files with 320 additions and 0 deletions.
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;

0 comments on commit 18ade79

Please sign in to comment.