Skip to main content

Design System

mindmap design-system

Design-System package is a powerful tool that helps you setup your own custom UI library and design system for your projects. It provides the boilerplate code for your UI library, configured with a system of latest and popular tools. By effortlessly generating design system configurations, our tool ensures consistent design across your entire application, saving your valuable development time.

Aim

Creating reusable and modular components is no longer a challenge these days especially with tools like shadcn. But, the process of creating a proper industry level design system is an arduous and time consuming task. That is exactly our aim i.e. to streamline the design system setup to cater reusabilty, consistency, flexibility, modularity and scalability.

info

Reusability: A centralized component library ensures that the components are not just reusable inside 1 app but across multiple apps.

Consistency: Centralizing a piece of code always brings in consistency as long as the appropriate version is used everywhere.

Flexibility: Comes with TailwindCSS as the styling solution OOTB and due to it being a utility-first CSS framework, gives room to other styling solutions like StyledComponents, Emotion etc.

Modularity: Use/import the components as and when you need them. Each component can be used as a separate shared package inside a monorepo or can be published as a NPM package and be used as a dependency in a stanalone project. Create headless and modular components with tools like radix-ui, headless ui, base ui etc.

Scalability: Even when your projects expand and become more complex, your component library remains coherent and managable. Atomic design is what makes this possible.

Tools and Technologies

The generated design system will come with the following tools/technologies out of the box:

  • Radix UI for creating custom component library
  • TailwindCSS as the styling option
  • Storybook for design system and UI library documentation
  • Tailwind Config Viewer for token visualization
  • CVA, Tailwind Merge for writing manageable and scalable components
  • GenesisX Scripts to ease the process of running scripts
  • SVGO and SVGR for optimized svg components
  • Hygen for building components, hooks, pages etc on the fly
  • Vite and Tsup for building ui components and packages respectively

We prioritize delivering first-class documentation to our users. To facilitate easy navigation and understanding, we have organized our documentation in a clear and structured manner.

Quick Start

Install the below package in your project

npx @genesisx/design-system@latest
RECIPES

Even though you can use this tool in a monorepo, polyrepo or as a standalone project, following are the ideal way to use the tool and maximize its potential:

  1. In a Monorepo: Use the tool to get a design system with centralized configurations and a sharable UI library.
  2. As Standalone: Use the tool to create an independent design system (with the UI library), publish the UI components to NPM, install and use them in your apps.
caution

It is not recommended to use this tool or create design systems in a polyrepo simply because it defeats the purpose of using this tool. It makes no sense creating a design system for a minor/personal/singular purpose projects. In these scenarios, directly using shadcn or pre-built styled component libraries like Material UI, Chakra UI, or css based styling option like TailwindCSS, PandaCSS, StyledComponents, Emotion, or style systems like TailwindUI, DaisyUI etc in your app would be the best bet.

As the principle behind the workings of this tool is Workspaces, you can still use this tool in a polyrepo the same way you would in a monorepo.

Folder structure

Within the polyrepo app, you will find a range of project files that serve various purposes and contribute to the overall structure and functionality of your application. These files are designed to simplify development and ensure the smooth operation of your polyrepo architectures.

design-system folder structure

(Click on the image to see it in a new tab)

Storybook

You can start the Storybook development server by running the following command:

npm run storybook

Once the server is up and running, you can access Storybook by opening your web browser and navigating to http://localhost:6006.

storybook

You can build the static files for production by running the following command:

npm run build:storybook

In .storybook, you will get a theme/getTheme.ts which gives you the option to fully customize and rebrand the storybook app to make it look just like your other apps. You can make use of the CSS Variables created in tailwind.css file and pass it to the computeStyle function as follows:

colorPrimary: computeStyle("--color-primary"), // using css vars
// OR
colorSecondary: '#fff', // using hex

Visit Storybook's Theme quickstart or Theming Types for more information on the available options.

Other than the main.ts, you will also get a manager.ts file which is where you are going to provide the created theme and manage other Storybook UI layout, a preview.tsx file to control your Story layout

Template Generator

Design System comes equipped with template generator engine like Hygen to speed up your component/package generation process.Try running the below command to start execute the cli tool:

npm run generate
CLI Generator Tool

As part of this, you will get a __templates directory which contains all your templates and prompts. In __templates, you will have a plop directory which further contains 3 sub-directories, namely: template, component and package. template contains a prompt.js which is where the generate command will go to when executed. template will then take the flow to either the prompt.js file of component or package based on the input provided.

generate underneath runs the following command:

npx hygen plop template

Here, plop is the directory name inside __templates, and tempate takes it to the prompt.js in plop/template directory. If you want to add more such templates, follow the below steps:

  1. Create a new directory inside plop, let's call it newGen. So, it will be as _templates/plop/newGen.

  2. Add all the necessary template files ending with .ejs.t inside the newly created directory with appropriate path to be copied at.

    ---
    to: path/to/<%= newGen %>/index.js
    ---
    console.log('Hello World');
  3. Create a prompt.js file with the required prompts.

    module.exports = [
    {
    type: "input",
    name: "newGen",
    default: "default",
    message: "What is your newGen going to be called?",
    },
    ];
  4. Add an additional object in the choices array in _templates/plop/template/prompt.js

    choices: [
    { name: "component", message: "A new component" },
    { name: "package", message: "A new package" },
    { name: "newGen", message: "A new generator" },
    ], // add more based on your requirement

Docs App

As part of your design system, you will get a MDX powered docs app, inside the apps directory. This can be used to document your design system, ui components, visualize design tokens, add best practices, guidelines etc. The docs app comes with 2 helper components OOTB: Callout and Card. You can add more such helpers to make your documentation more appealing. The documentation added in the docs app will be picked up Storybook when storybook is spun up.

caution

By default, the ui library and packages are setup to be build and published to npm i.e. when design system is initialized, build for all the ui components and the packages are created OOTB. This is helpful if you want to keep design system and your apps in separate repositories.

But, if you want to keep the design system and your apps in the same monorepo, then you do not need to build and publish the packages to use them in the same repo. So, to leverage the benefits of workspaces, you will have to delete the dist folder and adjust the main and/or module properties in package.json to the actual .ts file instead of dist/*.js.

Component library

In libs/ui-lib, you will find a starter ui kit with some sample components OOTB. This library follows the ATOMIC design principle to segregate and organize the ui components.

New Component

Generate

To generate a new component, run:

npm run generate

Select A new component, provide the component name and the directory (atoms, molecules, organisms, templates) where you want it to be added.

generator tools

Build

To build all the components simultaneously, run:

npm run build:ui-lib

To build specific component/s, provide the component names separated by a space as arguments to the build script as follows:

npm run build:ui-lib <component-name-1> <component-name-2>

For example, to build the Button, Dropdown and SearchBox components, you can run the following command:

npm run build:ui-lib Button Dropdown SearchBox

Publish

To publish a specific component, provide the component name as the argument to the publish script as follows:

npm run publish:ui-lib <component-name>

For example, to build the Button component, you can run the following command:

npm run build:ui-lib Button

Packages

In your packages directory, you will be provided tailwind and svg package.

Tailwind

This package contains 4 sub-directories, namely: config, styles, themes and utilities.

  1. config - contains the base tailwind and postcss config files. You can put all the necessary tailwind configuration here which you would need across all your apps.
  2. styles - comes with normalize.css and tailwind.css files. normalize.css is the css reseter while tailwind.css contains the standard tailwind imports and your other design variables.
  3. utilities - place where you will create your tailwind utilites.

To build your tailwind package, run:

npm run build:tw

To publish your tailwind package, run:

npm run publish:tw

SVG

This package provides support to convert the SVG files into react component. It uses svgo to optimize the sbg files and svgr to convert the optimized svg into a react component. The react components can be imported in other apps through named import. Tree shaking is enabled in this package.

To use the svg package follow the below steps:

  1. Add the svg files inside the assset folder (one sample svg is added for demo).

  2. To convert SVGs into optimzed react component, run:

    npm run convert
  3. To build the package, run:

    npm run build
RECIPES
  • The recommended way of using small and medium size SVG is to optimize the svg and convert them into a react component.

  • But in case you are working with large number of SVG files or massive SVG files, it is recommended to host the optimized SVG files on some object store or CDN. To use the SVG hosted on CDN, we can fetch the url of the svg on CDN and then use it inside our react component. One such example is shown here https://github.com/Paul-Ayanava/cdn-svg-react-example .

New package

Generate

To create a new package, run:

npm run generate

Select A new package and provide the package name.

generator tools

Build

To run build for your newly created package:

  1. Add the following script in the root package.json:

    "build:my-newpack": "genesisx build <packageName>",
  2. Run the newly added command:

    npm run build:my-newpack

Publish

To run build for your newly created package:

  1. Add the following script in the root package.json:

    "publish:my-newpack": "genesisx pub <packageName>",
  2. Run the newly added command:

    npm run publish:my-newpack
info

You can find the packageName under the "name" property in packages/<newpack>/package.json

Tailwind Config Viewer

You can start the tailwind-config-viewer server by running the following command:

npm run tcv
tailwind-config-viewer

You can build the static files for production by running the following command:

npm run build:tcv

Tailwind and PostCSS setup

To use tailwind in your apps, follow the below steps:

  1. Install your published package or add <tailwind-package-name> in your app's devDependencies manually:

    {
    "devDependencies": {
    '<tailwind-package-name>': "*", // only if your design system is in the same repo
    }
    }
  2. You will have to have to create tailwind.config.js and postcss.config.js files in your app where you want to use tailwind.

  3. In tailwind.config.js, add the following snipper:

    const { tailwindConfig } = require('<tailwind-package-name>/config');
    module.exports = {
    presets: [tailwindConfig],
    content: [
    ...tailwindConfig.content,
    '../../node_modules/<scopeName>/**/**/es/index.js' // add this only if you are installing your ui component rather than using the symlinked version
    ],
    };
  4. Similarly, in your postcss.config.js, add the following snippet:

  5. In tailwind.config.js, add the following snipper:

    const { postcssConfig } = require('<tailwind-package-name>/config');
    module.exports = postcssConfig;
  6. Import tailwind.css in your app root (main.tsx or _app.tsx etc):

    import '<tailwind-package-name>/styles/tailwind.css';

    // ...

Now, you should be able to use tailwind classes in your apps.

info

Make sure you are setting up tailwind at the same level of your build setup (vite.config/next.config/webpack.config etc)

More details & Troubleshooting

Visit the troubleshooting guide for common issues.