1.7.91 • Published 1 year ago

@vladimirfsh/design-system v1.7.91

Weekly downloads
-
License
ISC
Repository
github
Last release
1 year ago

amboss-design-system

Latest version Dependencies React Version

📄 Browse the design system (Storyboard documentation)

Quick start

Development Make sure you use npm >= 7.0.0 before running npm install

To start the project run npm run start

To generate a new component run npm run component myComponentName

Building the package

To build the package run npm run build

Building storybook

To build storybook run npm run build-storybook

Publishing

  • Add minor, major or patch label to your PR to specify release type.
  • Add skip-release label to skip the release
  • If you want your commit to skip ci, add "skip ci" to your commit message.

Codebase Overview

1. Tech stack 2. Linting 3. Folder structure 4. Build 5. Tokens, styles and theming 6. Assets 7. Media queries

Tech stack

  • Code: typescript
  • Styles: emotion.js
  • Framework: react
  • Bundler: webpack
  • Environment: storybook
  • Tokens: style-dictionary
  • Testing: jest + react testing library

Linting

As for linting and formatting, you can configure your editor to automatically lint and format your code on save. For this purpose, we're using Prettier and ESLint. If you need to do it manually, you can run:

npm run lint

This command is also run as a pre-push hook and in the pipeline.

Folder structure

|-- .storybook
    |-- components
        |-- ColorGrid.tsx
        |-- SizeGrid.tsx
    |-- main.js
    |-- preview.js
|-- assets
    |-- fonts
        |-- Lato.woff
|-- build (autogenerated)
|-- build-tokens (autogenerated)
    |-- assets
        |-- icons.json
        |-- icons16.json
    |-- _colors.json
    |-- _sizes.json
    |-- visualConfig.ts
|-- docs
    |-- Design-principles.mdx
|-- static
    |-- image-for-storybook.png
|-- tokens
    |-- themes
        |-- dark.json
        |-- light.json
    |-- assets.json
    |-- colors.json
|-- src
    |-- index.ts
    |-- components
        |-- Button
            |-- Button.tsx
            |-- Button.stories.tsx
            |-- Button.test.tsx
    |-- shared
        -- mediaQueries.ts
    |-- types
        |-- index.ts

Build

There are 3 stages of a build.

  1. Generate variables, theme values and assets from tokens
  2. Build all exported components with babel (preset-react, preset-typescript)
  3. Bundle all built components with webpack

Generate variables, theme values and assets from tokens

In order to structure our tokens we use style-dictionary. This tool is used for creation a content of ./build-tokens folder where we keep all the scss variables and mixins.

New variables and mixins gets generated automaticaly:

  • in watch mode while npm run start is running
  • after npm install
  • before build

You can generate tokens manually using npm run tokens and npm run tokens:watch

We use tokens to control the most atomic values in styles and themes.

How does it work?

We have a set of .json files that are located in ./tokens folder, and we have a style-dictionary as a tool for converting .json in to various formats.

For example:

We have a file - ./tokens/colors.json that gets converted into part of ./build-tokens/visualConfig.ts and ./build-tokens/_colors.json.

visualConfig.ts is used later as a source for emotion.js theme.

_colors.json is imported inside ./.storybook/components/ColorGrid.tsx in order to present in storybook all the colors we currently have.

The configuration for style-dictionary is inside ./style-dictionary/style-dictionary.config.json. In this config we use some custom transforms, filters and formatters, all of them defined in ./style-dictionary/style-dictionary.build.js.

custom/format/emotion-visual-config - a formatter that generates visualConfig.ts that contains all variables and themed values.

custom/filter/emotion-build-tokens - a filter for all token categories that should go to visutal config.

custom/format/json - a formatter for generation .json files per category. This formatter also add isUsed flag to according token.

custom/format/sub-theme-types - a formatter that generates type definitions for sub-themes.

custom/assets/svg - a transformer that adds a path name to dictionary of svg icons.

More about tokens, themes and styles.

Bundle all exported components

Before publish the design system for npm we run npm run build that bundles everything that is exported from ./src/index.ts.

We use webpack + babel for bundling. For all /\.ts(x?)$/ files webpack uses a babel-loader as a rule which is implicitly using tsconfig.json and .babelrc.

For styles we use emotion.js.

What in the bundle?

  • JS code that is compiled from .tsx files (includes common components and emotion.js styled components)
  • I svg icons that are inlined

fonts that are base64-ed currently taken off the build

Tokens, styles and theming

Currently, we have 4 types of tokens:

  • atomic values, like colors, sizes, shadows.
  • font assets, that are basically base64 of font files. (not used in production)
  • theme values, that are referencing atomic different atomic values
  • svg icon assets, that are inlined to a json file

As we use Emotion.js all tokenized values are accessible via theme provider.

Basically during the build phase we generate big objects of variables and themed values for each theme (currently light and dark).

We call this object ambossVisualConfiguration.

Particular themes from ambossVisualConfiguration has to be imported and passed to the theme provider at the consumer side.

After build all atomic values are passed to theme.variables by emotion.

Example:

const StyledContainer - styled.div(
  ({ theme }) => ({
    marginTop: theme.variables.size.spacing.s
  })
);

Theme tokens are little more complex. We generate separate VisualConfig for each theme, but together with that we generate type definition that describe any of the themes. This enables developers not care about current theme and how many themes are there.

After build all themes values are passed to theme.values by emotion.

Example:

const StyledContainer - styled.div(
  ({ theme }) => ({
    backgroundColor: theme.values.color.background.layer_2
  })
);

Sub-themes are folowing the same concept as themes. Developer can fully rely on theme.values object. As long as component in runtime is wrapped in SubThemeProvider and it's tokens listed in "tokens/themes/sub-themes/...", all values will be set correctly and automaticaly.

Note that not all tokens are enabled in sub-themes. Make sure to add missing ones to "tokens/themes/sub-themes/...".

Components that has "Sub-themed" badge are already in.

Assets

  • assets are defined in tokens/assets.json
  • with the help from style-dictionary we create a json file with tokens (/build-tokens/assets/)
  • those json files supposed to be imported in the ts module (see Icons.tsx)
  • in order to secure d.ts filed in the build we "manually" copy asset jsons on the postbuild phase (see package.json)

Media queries

There is an API for media-query related props: an array of 3 elements small, medium, large, for respective screen sizes.

For example <Box space=["xs", "xl", "xxl"] /> will set xs for small screens, xl for medium screens and xxl for large.

Basically, if you see a type of MQ<Whatever> you can provide an array of 3 Whatevers.

In order to add a media query support to your components:

import React from "react";

import styled from "@emotion/styled";
import { mq } from "../../shared/mediaQueries";

type TextAlignment = "left" | "center" | "right";

type BoxProps = {
  alignText: TextAlignment | MQ<TextAlignment>;
};

export const Box = styled.div<BoxProps>(
  ({ alignText = "left" }) =>
    mq({
      textAlign: [
        alignText,
        { left: "left", right: "right", center: "center" },
      ],
    })
);

Shadow-DOM

In order to use emotion-enabled DS components in the shadow-dom, you need to take some steps to 'link' the styles in the light-dom (these are added by emotion using CSSStyleSheet.insertRule() which is why appears empty in the DOM).

emotion-js/emotion#1366 https://emotion.sh/docs/cache-provider https://stackblitz.com/edit/emotion-shadow-dom-example?file=ShadowDomContainer.js https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule

import { ThemeProvider, light, Card, H1, CacheProvider, createCache } from '@amboss/design-system';
class SuchShadow extends HTMLElement {
  connectedCallback() {
    const root = document.createElement('div');
    this.attachShadow({ mode: 'open' });
    this.emotionCache = createCache({ container: this.shadowRoot });
    render(
      <ThemeProvider theme={light}>
        <CacheProvider value={this.emotionCache}>
          <Card>
            <H1>I love you shadow unicorn!!!</H1>
          </Card>
        </CacheProvider>
      </ThemeProvider>,
      root
    );
  }
}

customElements.define('shadow-element', SuchShadow);
1.7.91

1 year ago

1.7.9

1 year ago

1.7.8

1 year ago

1.7.7

1 year ago

1.7.6

1 year ago

1.7.5

1 year ago

1.7.4

1 year ago

1.7.2

1 year ago

1.7.3

1 year ago

1.7.1

1 year ago

1.7.0

1 year ago