designs/src/components
directory, each one must contain an index.(ts|tsx)
file with the React reusable component and optional files such as:types.ts
: To specify the modifiable attributes of the component using types
or interface
.styles.ts
: To create the custom-styled components and different CSS styling props.utils.ts
: To add util functions (e.g., filters, calculations, transformations).index.stories.tsx
: To add the storybook file to visualize and test the component.types.ts
file:/**
* Toggle button component props.
* @interface IToggleButtonProps
* @property {string} [defaultSelection] The option selected by default.
* @property {string[]} options The list options label.
* @property {Function} handleClick The function to handle the click event.
*/
interface IToggleButtonProps {
defaultSelection?: string;
options: string[];
handleClick: (selection: string) => void;
}
export type { IToggleButtonProps };
/** */
is mandatory and follows the structure of the JSDoc documentation generator. The rule is required by Eslint and it applies to interface
only. With the intention to keep the documentation concise, it is required to:@interface
to define the interface name.@extends
in cases where the interface inherits external props.@property
to define each property, following the structure:@property {Type} property_name Short prop description
.I<ComponentName>Props
.property_name
needs to be enclosed in square brackets when it is an optional property.@core
directory. Inside it, there are globally defined interfaces that can be used in individual components to extend and manage commonly needed properties.import type { IBorderModifiable, IDisplayModifiable, ... } from "components/@core";
/**
* Button component props.
* @interface IButtonProps
* @extends IBorderModifiable
* @extends IDisplayModifiable
* @extends IMarginModifiable
* @extends IPaddingModifiable
...
*/
@core
base in the styles.ts
file:import { BaseComponent } from "components/@core";
const StyledContainer = styled(BaseComponent)`
...
`;
forwardRef
function in the index.tsx
index.tsx file:import type { PropsWithChildren, Ref } from "react";
import { forwardRef } from "react";
import { StyledContainer } from "./styles";
import type { IContainerProps } from "./types";
const Container = forwardRef(function Container(
{
children,
...
...props
}: Readonly<PropsWithChildren<IContainerProps>>,
ref: Ref<HTMLDivElement>,
): JSX.Element {
return (
<StyledContainer
...
ref={ref}
{...props}
>
{children}
</StyledContainer>
);
});
storybook/test
that integrate the component stories with a testing environment powered using Jest. With this feature, we use the same story as a mock and can validate the components’ render and user interactions.index.stories.tsx
file create a play
function, adding the expect and user events inside it.import { expect, within } from "storybook/test";
...
Default.play = async ({ canvasElement, step }): Promise<void> => {
const canvas = within(canvasElement);
await step("should render a Button component", async (): Promise<void> => {
await expect(
canvas.getByRole("button", { name: "Button text" }),
).toBeInTheDocument();
await expect(canvas.getByTestId("arrow-right-icon")).toBeInTheDocument();
});
};
designs storybook
designs lint
designs test-storybook
localhost:6006
or any other specified port available.package.json
file in the desings
directoryversion
field following semantic versioning rules:MAJOR
version for incompatible API changesMINOR
version for backward-compatible functionality additionsPATCH
version for backward-compatible bug fixespr
suffix (e.g., 3.9.0-pr
or 3.9.1-pr.1
)node_modules
directory from designsdesigns-publish dev