Design Library
The design core library creates reusable components used throughout our products (e.g., airs, integrates, Jira).
Introduction
The fluid attacks design components library is an open-source npm package written in TypeScript and built with React.
Public Oath
- The design components package is available at @fluidattacks/design.
- The design storybook library is available at design.fluidattacks.com
Contributing
Please read the contributing page first.
Design standards
As our products rapidly evolve, the user interface is constantly modified. Since the platform and website redesign in 2024, we encountered the need to create a robust and maintainable design library to hold all the basic elements used to construct digital interfaces.
For this purpose, we applied different known software standard principles:
- Atomic Design: a methodology for designing and building user interfaces by breaking them down into progressively complex components, similar to how atoms combine to form molecules in chemistry, allowing for reusable and consistent components across an application, with the core idea being to create a hierarchical structure of UI elements, starting from basic “atoms” and building up to more complex “molecules”, “organisms”, “templates”, and finally “pages”.
- KISS, “Keep It Simple, Stupid”: a software development guideline that encourages developers to keep their code and systems as simple as possible. The principle is based on the idea that the simplest solution is often the best, and unnecessary complexity should be avoided.
- DRY, “Don’t Repeat Yourself”: a software development principle that aims to reduce the amount of repetitive code and logic in a system. This can help improve code maintainability, reduce the potential for errors, and streamline the development process.
- YAGNI, “You Aren’t Gonna Need It”: a software development principle that encourages developers to only add features when they are required, rather than trying to predict future needs.
- Single Responsibility (SRP): a component should have only one specific, well-defined purpose or functionality, and should not be responsible for multiple unrelated tasks; essentially, a component should only have one reason to change, making it more modular, easier to understand, maintain, and test independently.
Getting Started
The components are stored in the common/design/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 usingtypes
orinterface
.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.
Writing a component
All design components have a prototype in Figma with the anatomy specifics, interactions, and visual animations required. When working on a new component, the first question is: Can this be a variant of an existing component or is it brand new? As mentioned before, everything that can be reused to limit duplication is always preferred.
Afterward, you need to define the component’s properties or attributes. These are everything that can change (e.g., text, icons, user events, etc).
Here’s an example of a types.ts
file:
Key aspects of the example are:
- The documentation enclosed in
/** */
is mandatory and it follows the structure of the JSDoc documentation generator. The rule is required by Eslint and it applies tointerface
only. With the intention to keep the documentation concise, it is required to:- Add a description of the interface’s purpose.
- Use
@interface
to define the interface name. - Use
@extends
in cases where the interface inherits external props. - Use @property to define each property,
following the structure:
@property {Type} property_name Short prop description.
- The name should be
I<ComponentName>Props
.
When defining a component’s properties, you should review the @core
directory. Inside it, there are globally defined interfaces that can be
use in individual components to extend and manage commonly needed properties.
For these properties to apply correctly to the component, make sure to:
-
Create the style using the
@core
base in thestyles.ts
file: -
Create the react component using
forwardRef
function in theindex.tsx
file:
Styling and Theming
The styling of components is done using both Styled Components and Tailwind.
The storybook is a workshop page to showcase the UI components. It is a public domain and is the true source for keeping all digital products in sync with the design team of Fluid Attacks.
All components can be test locally using Storybook, Eslint and Stylelint, running the following jobs:
The local storybook can run in localhost:6006 or any other specified port available.
Testing
Besides visually testing the components, Storybook also provides the packages
@storybook/test
and @storybook/addon-interactions
that integrates 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.
To create a test, inside the index.stories.tsx
file create a play
function, adding
the expect and user events inside it.
This tests are run in production and local environment directly in the component story using the interactions addon.