Skip to main content

4. Add Components

Now we'll get to the meat of it... adding our first set of components based on kickstartDS. Which ones you'll utimately need, and subsequentially build, can vary wildly based on your specific Design System needs. We'll add some exemplary ones now, to illustrate the main ways on offer to do this:

  1. Adding a Button component
    based on @kickstartds/base/lib/button,
    to show the process of adapting an existing component
  2. Adding a Headline component
    based on @kickstartds/base/lib/headline,
    to show the process of customizing an existing component
  3. Adding a TeaserCard component
    based on @kickstartds/base/lib/teaser-box,
    to show the process of creating a new component
  4. Adding a Section component
    based on @kickstartds/base/lib/section,
    to show the process of extending an existing component

We'll then build our first recipe, using all of the added components to create a teaser component for articles. Recipes are like loose blueprints, that should serve as an inspiration for how components can be combined and remixed, to fit a multitude of use cases! To learn more about recipes, and different kinds of components, we recommend reading Brad Frosts excellent article on "design system components, recipes, and snowflakes".

And to bring it full circle, we will add that component to our Welcome page to tease the main pages of our Storybook, as a quick entry for users!

Feel free to change these examplary components being implemented around to something you'll actually need instead, if you happen to have something in mind already.
We'll try adding some components that are commonly needed, so it should be a good starting point either way!

If you want to take a deeper dive on finding your first component set right now, jump over to our guide around the Design System Initiative, and come back to this point later!

And if all of this feels overwhelming, or like too much work for you to do on your own or your team, feel free to also have a look at the services we offer around Design Systems and kickstartDS. They're in no way a necessity to use kickstartDS, but we're always happy to help in getting your first Design System, a Design System Initiative or internal DesignOps team off the ground!

Establish structure

Before we get into the components themselves, we need to do a last bit of setup that will be needed by all of them.

This includes setting up some React constructs like Providers, that ensure our own components get used everywhere (including when part of another component), hooking up JavaScript and CSS / SCSS integration and compilation, making sure our TypeScript types are available for users of our components, and finally creating some new scripts entries in package.json to improve our own developer experience when working on the Design System.

Add component Providers

All components in kickstartDS come with their own Provider. This enables you to switch component implementations at will. From sweeping changes like switching all Buttons for your own custom Button, including the ones that are part of other, bigger components, or surgical changes like just replacing the Button that gets used in a Teaser Box specifically.

To have that benefit for our own users, too, we'll add the same general structure to our Design System here.

Aggregate global Providers

We first create a file Providers.jsx at src/components/. This will import all of our global component providers, which are mainly the ones deep replacing kickstartDS components, and export a single member that can be used to import and integrate all providers at once, reducing the need for copy & pasted code.

And as we haven't created it before, it's now time to create src/components:


_1
mkdir -p src/components

... create the file...


_1
touch src/components/Providers.jsx

... and add the following content to it:

src/components/Providers.jsx
Copy

_5
export default (props) => {
_5
return (
_5
<div {...props} />
_5
)
_5
};

For now this will not do anything, but we'll hook it up to Storybook in the next step... and then subsequently build it up when adding components.

Update .storybook/preview.js

Integration with Storybook is done in .storybook/preview.js again, as this is related to how components are rendered / previewed. Just add the following lines to it:

Add Provider decorator to Storybook

We start by importing our (still empty) Providers that we created, and adding them to the decorators array.

Add Provider to docs pages

We also add the Providers to the docs rendering of Storybook.

Add unpack decorator to Storybook

While at it, we also add the unpack decorator to our Storybook. This decorator is provided by kickstartDS as part of @kickstartDS/core, and is used to unpack arguments provided to the component, rendered as part of a Story.

.storybook/preview.js
Copy

_68
import { actions } from "@storybook/addon-actions";
_68
import { DocsContainer } from "@storybook/addon-docs";
_68
_68
import { unpackDecorator } from '@kickstartds/core/lib/storybook/helpers';
_68
_68
import '@kickstartds/base/lib/global/base.js';
_68
import '@kickstartds/base/lib/global/base.css';
_68
_68
import IconSprite from '../src/token/icons/IconSprite';
_68
import Providers from '../src/components/Providers';
_68
_68
import '../src/token/tokens.css';
_68
_68
const myActions = actions("radio");
_68
_68
window.\_ks.radio.on("\*", myActions.radio);
_68
_68
const providerDecorator = (Story, context) => (
_68
_68
<Providers>
_68
<Story {...context} />
_68
</Providers>
_68
);
_68
_68
export const parameters = {
_68
actions: { argTypesRegex: "^on[A-Z].*" },
_68
controls: {
_68
matchers: {
_68
color: /(background|color)$/i,
_68
date: /Date$/,
_68
},
_68
},
_68
options: {
_68
storySort(a, b) {
_68
// welcome page to top!
_68
if (a[0].includes("welcome")) {
_68
return -1;
_68
}
_68
_68
// alphabetically
_68
return a[1].kind === b[1].kind
_68
? 0
_68
: a[1].id.localeCompare(b[1].id, undefined, { numeric: true });
_68
},
_68
_68
},
_68
designToken: {
_68
disable: true,
_68
},
_68
docs: {
_68
container: (props) => (
_68
_68
<Providers>
_68
<IconSprite />
_68
<DocsContainer {...props} />
_68
</Providers>
_68
), }, };
_68
_68
export const decorators = [
_68
unpackDecorator,
_68
providerDecorator,
_68
(Story) => (
_68
<>
_68
<IconSprite />
_68
<Story />
_68
</>
_68
),
_68
];

code formatting bug

Attention: there's a code formatting bug with the code above. The following line window.\_ks.radio.on("\*", myActions.radio); should read window._ks.radio.on("*", myActions.radio);

We'll hopefully be able to fix this soon!

This concludes the Storybook integration!

pack, unpack, story args... huh?

kickstartDS offers helpers you can use to automatically configure your stories Storybook Controls. If used, you'll automatically get Controls and respective documentation based on your component API (JSON Schema).

Because nesting Controls isn't straight-forward, we've written those helpers (pack, unpack) that take complex JSON, and, as the name suggests, pack those into an object with flattened keys compatible with the Controls addon (much like a library like flat does it).

Add package.json scripts

Good scripts entries in your package.json help new users when learning about your Design System, while also offering way better developer experience for everyone else. Aggregated commands to quickly start everything in development / watch mode, to compile everything for production, or for generating a new release mean taking complexities away from the average developer, while granular commands, used by those aggregate commands under the hood, allow for maximal flexibility.

To aggregate some commands, we add the package npm-run-all to the project. It can be used to run multiple commands either sequentially or parallelized. We also add chokidarcli to listen for file change events, and re-trigger commands for hot reload:


_1
yarn add npm-run-all chokidar-cli --dev

We then add the following scripts entries to our package.json now:

Unchanged package.json

This is how your package.json should look like currently.

package.json
Copy

_44
{
_44
"name": "@my/design-system",
_44
"version": "1.0.0",
_44
"description": "Design System for all @MY needs",
_44
"main": "dist/index.js",
_44
"scripts": {
_44
"build-storybook": "build-storybook",
_44
"build-tokens": "kickstartDS tokens compile",
_44
"dereference-schemas": "kickstartDS schema dereference --schema-domain schema.mydesignsystem.com",
_44
"generate-props": "kickstartDS schema types --schema-domain schema.mydesignsystem.com",
_44
"init-tokens": "kickstartDS tokens init",
_44
"sass-manager": "sass --load-path=node_modules .storybook/manager.scss static/manager.css",
_44
"storybook": "start-storybook -p 6006",
_44
"test": "echo \"Error: no test specified\" && exit 1",
_44
"watch:sass-manager": "yarn sass-manager --watch"
_44
},
_44
"author": "Jonas Ulrich",
_44
"license": "MIT",
_44
"dependencies": {
_44
"@kickstartds/base": "^2.0.2",
_44
"kickstartds": "^1.0.0",
_44
"react": "^17.0.2",
_44
"react-dom": "^17.0.2"
_44
},
_44
"devDependencies": {
_44
"@babel/core": "^7.19.3",
_44
"@kickstartds/storybook-addon-component-tokens": "^0.1.6",
_44
"@kickstartds/storybook-addon-jsonschema": "^1.0.5",
_44
"@storybook/addon-actions": "^6.5.12",
_44
"@storybook/addon-essentials": "^6.5.12",
_44
"@storybook/addon-interactions": "^6.5.12",
_44
"@storybook/addon-links": "^6.5.12",
_44
"@storybook/builder-webpack4": "^6.5.12",
_44
"@storybook/manager-webpack4": "^6.5.12",
_44
"@storybook/react": "^6.5.12",
_44
"@storybook/testing-library": "^0.0.13",
_44
"@whitespace/storybook-addon-html": "git+https://github.com/lmestel/storybook-addon-html.git",
_44
"babel-loader": "^8.2.5",
_44
"chokidar-cli": "^3.0.0",
_44
"npm-run-all": "^4.1.5",
_44
"sass": "^1.55.0",
_44
"storybook-design-token": "^2.8.0"
_44
}
_44
}

Add aggregated schema script

We add a command aggregating schema dereferencing and props generation for us in schema. run-p schema:* runs all commands prefixed with schema: in parallel.

package.json
Copy

_45
{
_45
"name": "@my/design-system",
_45
"version": "1.0.0",
_45
"description": "Design System for all @MY needs",
_45
"main": "dist/index.js",
_45
"scripts": {
_45
"build-storybook": "build-storybook",
_45
"build-tokens": "kickstartDS tokens compile",
_45
"dereference-schemas": "kickstartDS schema dereference --schema-domain schema.mydesignsystem.com",
_45
"generate-props": "kickstartDS schema types --schema-domain schema.mydesignsystem.com",
_45
"init-tokens": "kickstartDS tokens init",
_45
"sass-manager": "sass --load-path=node_modules .storybook/manager.scss static/manager.css",
_45
"schema": "run-p schema:*",
_45
"storybook": "start-storybook -p 6006",
_45
"test": "echo \"Error: no test specified\" && exit 1",
_45
"watch:sass-manager": "yarn sass-manager --watch"
_45
},
_45
"author": "Jonas Ulrich",
_45
"license": "MIT",
_45
"dependencies": {
_45
"@kickstartds/base": "^2.0.2",
_45
"kickstartds": "^1.0.0",
_45
"react": "^17.0.2",
_45
"react-dom": "^17.0.2"
_45
},
_45
"devDependencies": {
_45
"@babel/core": "^7.19.3",
_45
"@kickstartds/storybook-addon-component-tokens": "^0.1.6",
_45
"@kickstartds/storybook-addon-jsonschema": "^1.0.5",
_45
"@storybook/addon-actions": "^6.5.12",
_45
"@storybook/addon-essentials": "^6.5.12",
_45
"@storybook/addon-interactions": "^6.5.12",
_45
"@storybook/addon-links": "^6.5.12",
_45
"@storybook/builder-webpack4": "^6.5.12",
_45
"@storybook/manager-webpack4": "^6.5.12",
_45
"@storybook/react": "^6.5.12",
_45
"@storybook/testing-library": "^0.0.13",
_45
"@whitespace/storybook-addon-html": "git+https://github.com/lmestel/storybook-addon-html.git",
_45
"babel-loader": "^8.2.5",
_45
"chokidar-cli": "^3.0.0",
_45
"npm-run-all": "^4.1.5",
_45
"sass": "^1.55.0",
_45
"storybook-design-token": "^2.8.0"
_45
}
_45
}

We now move all schema related tasks to using that schema prefix.

package.json
Copy

_49
{
_49
"name": "@my/desig"chokidar": "^3.5.3",
_49
"chokidar": "^3.5.3",
_49
"chokidar": "^3.5.3",
_49
"chokidar": "^3.5.3",
_49
"chokidar": "^3.5.3",
_49
"chokidar": "^3.5.3",
_49
"chokidar": "^3.5.3",esign System for all @MY needs",
_49
"main": "dist/index.js",
_49
"scripts": {
_49
"build-storybook": "build-storybook",
_49
"build-tokens": "kickstartDS tokens compile",
_49
"init-tokens": "kickstartDS tokens init",
_49
"sass-manager": "sass --load-path=node_modules .storybook/manager.scss static/manager.css",
_49
"schema": "run-p schema:*",
_49
"schema:dereference-schemas": "kickstartDS schema dereference --schema-domain schema.mydesignsystem.com",
_49
"schema:generate-props": "kickstartDS schema types --schema-domain schema.mydesignsystem.com",
_49
"storybook": "start-storybook -p 6006",
_49
"test": "echo \"Error: no test specified\" && exit 1",
_49
"watch:sass-manager": "yarn sass-manager --watch"
_49
},
_49
"author": "Jonas Ulrich",
_49
"license": "MIT",
_49
"dependencies": {
_49
"@kickstartds/base": "^2.0.2",
_49
"kickstartds": "^1.0.0",
_49
"react": "^17.0.2",
_49
"react-dom": "^17.0.2"
_49
},
_49
"devDependencies": {
_49
"@babel/core": "^7.19.3",
_49
"@kickstartds/storybook-addon-component-tokens": "^0.1.6",
_49
"@kickstartds/storybook-addon-jsonschema": "^1.0.5",
_49
"@storybook/addon-actions": "^6.5.12",
_49
"@storybook/addon-essentials": "^6.5.12",
_49
"@storybook/addon-interactions": "^6.5.12",
_49
"@storybook/addon-links": "^6.5.12",
_49
"@storybook/builder-webpack4": "^6.5.12",
_49
"@storybook/manager-webpack4": "^6.5.12",
_49
"@storybook/react": "^6.5.12",
_49
"@storybook/testing-library": "^0.0.13",
_49
"@whitespace/storybook-addon-html": "git+https://github.com/lmestel/storybook-addon-html.git",
_49
"babel-loader": "^8.2.5",
_49
"chokidar-cli": "^3.0.0",
_49
"npm-run-all": "^4.1.5",
_49
"sass": "^1.55.0",
_49
"storybook-design-token": "^2.8.0"
_49
}
_49
}

Add token and schema handling to build-storybook

Make sure everything is compiled, before building Storybook.

package.json
Copy

_45
{
_45
"name": "@my/design-system",
_45
"version": "1.0.0",
_45
"description": "Design System for all @MY needs",
_45
"main": "dist/index.js",
_45
"scripts": {
_45
"build-storybook": "yarn build-tokens && run-p sass-manager schema && build-storybook",
_45
"build-tokens": "kickstartDS tokens compile",
_45
"init-tokens": "kickstartDS tokens init",
_45
"sass-manager": "sass --load-path=node_modules .storybook/manager.scss static/manager.css",
_45
"schema": "run-p schema:*",
_45
"schema:dereference-schemas": "kickstartDS schema dereference --schema-domain schema.mydesignsystem.com",
_45
"schema:generate-props": "kickstartDS schema types --schema-domain schema.mydesignsystem.com",
_45
"storybook": "start-storybook -p 6006",
_45
"test": "echo \"Error: no test specified\" && exit 1",
_45
"watch:sass-manager": "yarn sass-manager --watch"
_45
},
_45
"author": "Jonas Ulrich",
_45
"license": "MIT",
_45
"dependencies": {
_45
"@kickstartds/base": "^2.0.2",
_45
"kickstartds": "^1.0.0",
_45
"react": "^17.0.2",
_45
"react-dom": "^17.0.2"
_45
},
_45
"devDependencies": {
_45
"@babel/core": "^7.19.3",
_45
"@kickstartds/storybook-addon-component-tokens": "^0.1.6",
_45
"@kickstartds/storybook-addon-jsonschema": "^1.0.5",
_45
"@storybook/addon-actions": "^6.5.12",
_45
"@storybook/addon-essentials": "^6.5.12",
_45
"@storybook/addon-interactions": "^6.5.12",
_45
"@storybook/addon-links": "^6.5.12",
_45
"@storybook/builder-webpack4": "^6.5.12",
_45
"@storybook/manager-webpack4": "^6.5.12",
_45
"@storybook/react": "^6.5.12",
_45
"@storybook/testing-library": "^0.0.13",
_45
"@whitespace/storybook-addon-html": "git+https://github.com/lmestel/storybook-addon-html.git",
_45
"babel-loader": "^8.2.5",
_45
"chokidar-cli": "^3.0.0",
_45
"npm-run-all": "^4.1.5",
_45
"sass": "^1.55.0",
_45
"storybook-design-token": "^2.8.0"
_45
}
_45
}

Add additional watch tasks

We now add watch tasks for schema and dictionary, using chokidar.

  • schema: regenerates component API and TypeScript types on schema change
  • dictionary: regenerates your CSS Custom Properties on Style Dictionary change
package.json
Copy

_47
{
_47
"name": "@my/design-system",
_47
"version": "1.0.0",
_47
"description": "Design System for all @MY needs",
_47
"main": "dist/index.js",
_47
"scripts": {
_47
"build-storybook": "yarn build-tokens && run-p sass-manager schema && build-storybook",
_47
"build-tokens": "kickstartDS tokens compile",
_47
"init-tokens": "kickstartDS tokens init",
_47
"sass-manager": "sass --load-path=node_modules .storybook/manager.scss static/manager.css",
_47
"schema": "run-p schema:*",
_47
"schema:dereference-schemas": "kickstartDS schema dereference --schema-domain schema.mydesignsystem.com",
_47
"schema:generate-props": "kickstartDS schema types --schema-domain schema.mydesignsystem.com",
_47
"storybook": "start-storybook -p 6006",
_47
"test": "echo \"Error: no test specified\" && exit 1",
_47
"watch:sass-manager": "yarn sass-manager --watch",
_47
"watch:schema": "yarn schema && chokidar \"src/**/*.schema.json\" -c \"yarn schema\"",
_47
"watch:dictionary": "chokidar \"src/token/dictionary/*.json\" -c \"yarn build-tokens\""
_47
},
_47
"author": "Jonas Ulrich",
_47
"license": "MIT",
_47
"dependencies": {
_47
"@kickstartds/base": "^2.0.2",
_47
"kickstartds": "^1.0.0",
_47
"react": "^17.0.2",
_47
"react-dom": "^17.0.2"
_47
},
_47
"devDependencies": {
_47
"@babel/core": "^7.19.3",
_47
"@kickstartds/storybook-addon-component-tokens": "^0.1.6",
_47
"@kickstartds/storybook-addon-jsonschema": "^1.0.5",
_47
"@storybook/addon-actions": "^6.5.12",
_47
"@storybook/addon-essentials": "^6.5.12",
_47
"@storybook/addon-interactions": "^6.5.12",
_47
"@storybook/addon-links": "^6.5.12",
_47
"@storybook/builder-webpack4": "^6.5.12",
_47
"@storybook/manager-webpack4": "^6.5.12",
_47
"@storybook/react": "^6.5.12",
_47
"@storybook/testing-library": "^0.0.13",
_47
"@whitespace/storybook-addon-html": "git+https://github.com/lmestel/storybook-addon-html.git",
_47
"babel-loader": "^8.2.5",
_47
"chokidar-cli": "^3.0.0",
_47
"npm-run-all": "^4.1.5",
_47
"sass": "^1.55.0",
_47
"storybook-design-token": "^2.8.0"
_47
}
_47
}

Add start command

We can use that in development, to start everything with hot reload because of the watchers we've added.

package.json
Copy

_48
{
_48
"name": "@my/design-system",
_48
"version": "1.0.0",
_48
"description": "Design System for all @MY needs",
_48
"main": "dist/index.js",
_48
"scripts": {
_48
"build-storybook": "yarn build-tokens && run-p sass-manager schema && build-storybook",
_48
"build-tokens": "kickstartDS tokens compile",
_48
"init-tokens": "kickstartDS tokens init",
_48
"sass-manager": "sass --load-path=node_modules .storybook/manager.scss static/manager.css",
_48
"schema": "run-p schema:*",
_48
"schema:dereference-schemas": "kickstartDS schema dereference --schema-domain schema.mydesignsystem.com",
_48
"schema:generate-props": "kickstartDS schema types --schema-domain schema.mydesignsystem.com",
_48
"start": "run-p watch:* storybook",
_48
"storybook": "start-storybook -p 6006",
_48
"test": "echo \"Error: no test specified\" && exit 1",
_48
"watch:sass-manager": "yarn sass-manager --watch",
_48
"watch:schema": "yarn schema && chokidar \"src/**/*.schema.json\" -c \"yarn schema\"",
_48
"watch:dictionary": "chokidar \"src/token/dictionary/*.json\" -c \"yarn build-tokens\""
_48
},
_48
"author": "Jonas Ulrich",
_48
"license": "MIT",
_48
"dependencies": {
_48
"@kickstartds/base": "^2.0.2",
_48
"kickstartds": "^1.0.0",
_48
"react": "^17.0.2",
_48
"react-dom": "^17.0.2"
_48
},
_48
"devDependencies": {
_48
"@babel/core": "^7.19.3",
_48
"@kickstartds/storybook-addon-component-tokens": "^0.1.6",
_48
"@kickstartds/storybook-addon-jsonschema": "^1.0.5",
_48
"@storybook/addon-actions": "^6.5.12",
_48
"@storybook/addon-essentials": "^6.5.12",
_48
"@storybook/addon-interactions": "^6.5.12",
_48
"@storybook/addon-links": "^6.5.12",
_48
"@storybook/builder-webpack4": "^6.5.12",
_48
"@storybook/manager-webpack4": "^6.5.12",
_48
"@storybook/react": "^6.5.12",
_48
"@storybook/testing-library": "^0.0.13",
_48
"@whitespace/storybook-addon-html": "git+https://github.com/lmestel/storybook-addon-html.git",
_48
"babel-loader": "^8.2.5",
_48
"chokidar-cli": "^3.0.0",
_48
"npm-run-all": "^4.1.5",
_48
"sass": "^1.55.0",
_48
"storybook-design-token": "^2.8.0"
_48
}
_48
}

Finished package.json

Your package.json should look like this now!

package.json
Copy

_48
{
_48
"name": "@my/design-system",
_48
"version": "1.0.0",
_48
"description": "Design System for all @MY needs",
_48
"main": "dist/index.js",
_48
"scripts": {
_48
"build-storybook": "yarn build-tokens && run-p sass-manager schema && build-storybook",
_48
"build-tokens": "kickstartDS tokens compile",
_48
"init-tokens": "kickstartDS tokens init",
_48
"sass-manager": "sass --load-path=node_modules .storybook/manager.scss static/manager.css",
_48
"schema": "run-p schema:*",
_48
"schema:dereference-schemas": "kickstartDS schema dereference --schema-domain schema.mydesignsystem.com",
_48
"schema:generate-props": "kickstartDS schema types --schema-domain schema.mydesignsystem.com",
_48
"start": "run-p watch:* storybook",
_48
"storybook": "start-storybook -p 6006",
_48
"test": "echo \"Error: no test specified\" && exit 1",
_48
"watch:sass-manager": "yarn sass-manager --watch",
_48
"watch:schema": "yarn schema && chokidar \"src/**/*.schema.json\" -c \"yarn schema\"",
_48
"watch:dictionary": "chokidar \"src/token/dictionary/*.json\" -c \"yarn build-tokens\""
_48
},
_48
"author": "Jonas Ulrich",
_48
"license": "MIT",
_48
"dependencies": {
_48
"@kickstartds/base": "^2.0.2",
_48
"kickstartds": "^1.0.0",
_48
"react": "^17.0.2",
_48
"react-dom": "^17.0.2"
_48
},
_48
"devDependencies": {
_48
"@babel/core": "^7.19.3",
_48
"@kickstartds/storybook-addon-component-tokens": "^0.1.6",
_48
"@kickstartds/storybook-addon-jsonschema": "^1.0.5",
_48
"@storybook/addon-actions": "^6.5.12",
_48
"@storybook/addon-essentials": "^6.5.12",
_48
"@storybook/addon-interactions": "^6.5.12",
_48
"@storybook/addon-links": "^6.5.12",
_48
"@storybook/builder-webpack4": "^6.5.12",
_48
"@storybook/manager-webpack4": "^6.5.12",
_48
"@storybook/react": "^6.5.12",
_48
"@storybook/testing-library": "^0.0.13",
_48
"@whitespace/storybook-addon-html": "git+https://github.com/lmestel/storybook-addon-html.git",
_48
"babel-loader": "^8.2.5",
_48
"chokidar-cli": "^3.0.0",
_48
"npm-run-all": "^4.1.5",
_48
"sass": "^1.55.0",
_48
"storybook-design-token": "^2.8.0"
_48
}
_48
}

Unchanged package.json

This is how your package.json should look like currently.

Add aggregated schema script

We add a command aggregating schema dereferencing and props generation for us in schema. run-p schema:* runs all commands prefixed with schema: in parallel.

We now move all schema related tasks to using that schema prefix.

Add token and schema handling to build-storybook

Make sure everything is compiled, before building Storybook.

Add additional watch tasks

We now add watch tasks for schema and dictionary, using chokidar.

  • schema: regenerates component API and TypeScript types on schema change
  • dictionary: regenerates your CSS Custom Properties on Style Dictionary change

Add start command

We can use that in development, to start everything with hot reload because of the watchers we've added.

Finished package.json

Your package.json should look like this now!

package.json
CopyExpandClose

_44
{
_44
"name": "@my/design-system",
_44
"version": "1.0.0",
_44
"description": "Design System for all @MY needs",
_44
"main": "dist/index.js",
_44
"scripts": {
_44
"build-storybook": "build-storybook",
_44
"build-tokens": "kickstartDS tokens compile",
_44
"dereference-schemas": "kickstartDS schema dereference --schema-domain schema.mydesignsystem.com",
_44
"generate-props": "kickstartDS schema types --schema-domain schema.mydesignsystem.com",
_44
"init-tokens": "kickstartDS tokens init",
_44
"sass-manager": "sass --load-path=node_modules .storybook/manager.scss static/manager.css",
_44
"storybook": "start-storybook -p 6006",
_44
"test": "echo \"Error: no test specified\" && exit 1",
_44
"watch:sass-manager": "yarn sass-manager --watch"
_44
},
_44
"author": "Jonas Ulrich",
_44
"license": "MIT",
_44
"dependencies": {
_44
"@kickstartds/base": "^2.0.2",
_44
"kickstartds": "^1.0.0",
_44
"react": "^17.0.2",
_44
"react-dom": "^17.0.2"
_44
},
_44
"devDependencies": {
_44
"@babel/core": "^7.19.3",
_44
"@kickstartds/storybook-addon-component-tokens": "^0.1.6",
_44
"@kickstartds/storybook-addon-jsonschema": "^1.0.5",
_44
"@storybook/addon-actions": "^6.5.12",
_44
"@storybook/addon-essentials": "^6.5.12",
_44
"@storybook/addon-interactions": "^6.5.12",
_44
"@storybook/addon-links": "^6.5.12",
_44
"@storybook/builder-webpack4": "^6.5.12",
_44
"@storybook/manager-webpack4": "^6.5.12",
_44
"@storybook/react": "^6.5.12",
_44
"@storybook/testing-library": "^0.0.13",
_44
"@whitespace/storybook-addon-html": "git+https://github.com/lmestel/storybook-addon-html.git",
_44
"babel-loader": "^8.2.5",
_44
"chokidar-cli": "^3.0.0",
_44
"npm-run-all": "^4.1.5",
_44
"sass": "^1.55.0",
_44
"storybook-design-token": "^2.8.0"
_44
}
_44
}

Feel free to start your Storybook now by just calling the start command:


_1
yarn start

Isn't that convenient? 😅 Now everything is set up to start the fun part: adding components!

Component implementation

We roughly see four different ways of adding a component to your Design System, in the context of kickstartDS. Those are most definitely not exhausting, but they serve as a good introduction:

  1. Adapt a component (Button)
  2. Create a component (Headline)
  3. Customize a component (TeaserCard)
  4. Extend a component (Section)

We'll follow one guide for each of those general workflows, resulting in the four planned components being added to our Design System. In the real world the truth is not that clear cut, at least most of the time. Typically you'd probably have a mix of those scenarios.

Feel free to just add the components as shown in the guides for now, every if you'll change those later for real use. You can always adapt them further at a later point! You can also skip the exhaustive component example guides, if you just want to copy & paste along. We'll always include the respective code snapshots to do that!

To learn about finding components to implement, have a look at the Design System Initiative guide.

1. Adding our own Button component

To demonstrate the first, and easiest, way of adding a component to your own Design System we will adapt a Button component.

This also serves as an example for adapting a component, where we mostly take a component directly from kickstartDS, while still finding our own, often more restrictive, component API for it.

The result will look like this:

Choose your own adventure:

PathLink
Follow the Component example guideAdapt Button component
Read the process descriptionAdapt a component
Look at the Code Sandboxsee below

See the completed example in a Code Sandbox below:

Toggle the file browser with the hamburger icon at the top left, or open it directly in your browser.

2. Adding our own Headline component

The second way of adding a component involves much of the same steps we've seen for the Button already. That's not a coincidence, as every process should involve following the steps outlined by the adaptation process. It's like a base process that gets inherited, because reducing the offered properties into your own component API is essential!

In addition to that process we customize the component with this one. We add our own property switchOrder to switch the order of headline and subheadline. Not a feature of the kickstartDS base Headline normally. This results in us having to change the React template, which makes this customizing, compared to example to extension. We also add RTE-like rendering capabilities to the content fields.

We have a dedicated guide for customization, too, explaining the concepts a bit more in-depth.

The result will look like this:

Choose your own adventure:

PathLink
Follow the Component example guideCustomize Headline component
Read the process descriptionCustomize a component
Look at the Code Sandboxsee below

See the completed example in a Code Sandbox below:

Toggle the file browser with the hamburger icon at the top left, or open it directly in your browser.

3. Adding our own TeaserCard component

For the third way of adding a component we add a TeaserCard to our Design System. This is not a component we will build while having a kickstartDS base component in mind, yet. Instead, we'll start with "just" the requirements (this really is the most common scenario, btw., it just builds nicely on the two before). We'll then map those to a component second, and proceed like for the others!

This serves as a great example of the creation process. We create something new, but still benefit from all the underlying Design System goodness.

The result will look like this:

Choose your own adventure:

PathLink
Follow the Component example guideCreate TeaserCard component
Read the process descriptionCustomize a component
Look at the Code Sandboxsee below

See the completed example in a Code Sandbox below:

Toggle the file browser with the hamburger icon at the top left, or open it directly in your browser.

4. Adding our own Section component

For the last component, we'll add a Section that can be used to combine all of the components we've added before to create our first composable use cases! We take it from the kickstartDS base component pretty much verbatim. But we expand upon its capabilities by adding the option to every Section to add as many call-to-actions to it that get displayed at the end of the Section. Also not a feature currently offered by kickstartDS Sections.

This showcases our last way of adding components nicely, namely extending a component. We take existing components and just combine and re-mix them to cover new use cases. This can be done completely without changing any markup... with just composition!

The result will look like this:

Choose your own adventure:

PathLink
Follow the Component example guideExtend Section component
Read the process descriptionCustomize a component
Look at the Code Sandboxsee below

See the completed example in a Code Sandbox below:

Toggle the file browser with the hamburger icon at the top left, or open it directly in your browser.

Adding an article teaser recipe

We're currently still working on this guide, it will follow soon! We will combine all of the added components into a recipe here. A recipe is not quite a component (it doesn't have its own component API for example), but more of inspiration to your Design Systems users. They show how more complex, but slightly one-off, components can be built by just combining existing stuff in smart ways!

Result

Following those examples is mostly meant as an illustration of the basic building blocks of adding a component. They can be combined, mixed and scaled freely! We'll start adding more advanced component example guides for that, too!

This concludes adding components to our Design System. It's also the last of the 5 parts currently documented. We're in the process of finishing the fifth section about publishing your Design System. So stay tuned for that!

Next step

Start adding more components, try to re-mix those processes... and let us know how it went!

Code Sandbox

See the result of this step in the Code Sandbox below. It's showing specifically the result after this step. You can also view this on Github directly in the ds-guide repository, there's a branch for every step... and we're currently on the branch step/4 in the guide:

Toggle the file browser with the hamburger icon at the top left, or open it directly in your browser.