npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@amboss/design-system

v3.1.5

Published

the design system for AMBOSS products

Downloads

17,495

Readme

amboss-design-system

Latest version Dependencies React Version

📄 Browse the design system (Storyboard documentation)

Quick start

Development Ensure that you are using 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.

Generating mobile tokens

  1. Install Node.js and npm by following the official installation guide
  2. Install dependencies: npm install
  3. Generate the tokens:
    npm run tokens:ios
    npm run tokens:android

Generating mobile icons

  1. Install Node.js and npm by following the official installation guide
  2. Install dependencies: npm install
  3. Generate the tokens:
    npm run icons:ios
    npm run icons:android

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-icons (autogenerated)
    |-- android
        |-- ic_activity_16.xml
        |-- ic_activity_24.xml
    |-- ios
        |-- activity.imageset
            |-- activity.pdf
            |-- activity16.pdf
            |-- Contents.json
|-- build-tokens (autogenerated)
    |-- android
        |-- design_system_color.xml
    |-- ios
        |-- DesignSystemColorTokens.swift
    |-- scss
        |-- _theming.scss
        |-- _variables.scss
    |-- assets
        |-- icons.json
        |-- icons16.json
    |-- _colors.json
    |-- _sizes.json
    |-- visualConfig.ts
|-- docs
    |-- Design-principles.mdx
|-- static
    |-- image-for-storybook.png
|-- tokens
    |-- global
      |-- themes
          |-- dark.json
          |-- light.json
      |-- assets.json
      |-- colors.json
    |-- web
      |-- component
        |-- dark.json
        |-- light.json
    |-- android
      |-- opacity.json
    |-- ios
      |-- opacity.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:web 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/global/light|dark.json that gets converted into part of ./build-tokens/visualConfig.ts.

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

The configuration for style-dictionary is inside ./style-dictionary/{platformName}/{platformName}.sd.config.json. In this config we use some custom transforms, filters and formatters, all of them defined in corresponding files of platform folders.

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 publishing the design system for NPM, we run npm run build. This runs the script at ``bundles everything that is exported from.tsand.tsx files within the source.

For this, we use tsup, which runs esbuild under the hood. We also use a lenient browserslist config to ensure compatibility with older browsers.

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)
  • 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.

Atomic values are straight forward and simply converted to variables.

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.primary.default
  })
);

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

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

Components that have a "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);