Create a component
Creating a component differs from "just" adapting a component in that it starts out without a specific kickstartDS component already in mind.
All but the most obvious components will be implemented following this strategy. And it's the preferrable way to do it, too. You should start out with just a concept of what you actually need. Which components can help in bringing that concept to life should be something you concern yourself with second.
This works especially well in 2 cases:
- When what you need is actually just a specialized case of one of our existing components. Like when wanting to create an article teaser, you'll probably find a general purpose kickstartDS component like the
TeaserCardthat matches this signature really well
- You have a rather complex component (think something like a more advanced blog head component). Often you'll find those components to be composed of basic building bricks (like
Headlines) after all, which is where component mapping to kickstartDS comes into the picture again
When zooming in enough, everything starts to look the same
If you think about it, there's only a limited number of ways information can actually be presented. And oftentimes you'll find there's already preferred versions of doing it out there, what we'd call learned user interface (UI), or just best practices. The Hamburger menu icon would be such an example. Or how certain information is often teased in the form of structured cards.
Adhering to that expectation, and not creating unneeded artificial friction, is one big part of delivering a good user experience (UX). We're convinced we can cover a great range of those basic building blocks for you. Allowing you to concentrate on destructuring your requirements, mapping the resulting pieces to kickstartDS components. It's how bigger kickstartDS components like a
Storytelling component (using
RichText, etc) are constructed, too.
Additionally this can of course also be combined with customization for your own added properties, not part of the used kickstartDS base components (see our
Headline component example for that). Or be implemented using extension if the component should expand on some kickstartDS base component (see our
Section component example for that).
To learn more about the different processes available to you when creating a component with kickstartDS, have a look at the overview page of this section.
You should already have an idea of what you'll need from your component, or some rough image of what it should do. We start by refining those requirements into a component API, which we'll then map to existing kickstartDS base components. This will then serve as our starting point for creating the actual component.
There are three main steps in creating a component:
- Component definition,
- Component mapping, and
- Component creation
So the main way this differs from adapting a component is in adding "Component Mapping", in between "Component definition" and "Component creation". This is where we'll try to match our component API to existing components.
We'll also slightly deviate from it when defining our structure, as we can't just reduce an existing set of component properties here.
Adaptation process as a base line
If you've read our "Adapt a component" guide you probably already know this:
This guide expects you to reduce the set of props offered by kickstartDS components, when used as base components. We'll also skip over, or significantly shorten, parts already covered by that guide. If unsure about something, best cross-reference it!
Let's start with the definition!
1. Component Definition
Like the adaptation process we start by defining a component API. But unlike it, we directly write down what we need. We don't start with a blueprint this time.
We'll use the
TeaserCard component throughout this guide to illustrate concepts. This will not be an exhaustive example, though. For that have a look at our guide "Create
TeaserCard component". We also have an additional example in "Create
Interstitial component", but to actually implement that you need access to our kickstartDS content module. But following the thought process behind it can provide values nontheless.
The Content Module includes seven rich components: Hero visual, Quote, Storytelling etc. — everything you need to build beautiful content experiences or to enrich your existing Design System
When thinking about a component that should be part of your Design System, you should already have a strong sense of what that component should be, and what it should accomplish for you. If that's not the case, it probably isn't stable enough yet to be part of a Design System that should find wider adoption. You should probably take a step back first, and maybe start a Design System Initiative to narrow down on what components you'll really need.
With that in mind, let's assume that the purpose of our component (the
TeaserCard) is to tease content. It should look like a card while doing that, and have the obvious features one would assume a card based component to have. Like a cover image, a link, a headline and some text... with some of those potentially being optional. And because our Design System has an invert feature, it should also be invertible.
Before we start implementing, we'll want to define a first rough draft of our component API. Defining a name, a small description and a rough type, per property, goes a long way in keeping the focus on the core of your component.
Let's keep using the
TeaserCard as an example, with the following properties being the result of pinning down our rough idea:
|Headline for the teaser card|
|Body text for the teaser card|
|(Optional) image to display as cover|
|Show inverted version of card?|
|Target that should be linked|
Fields that should be required are marked with a
2. Component Mapping
This is the part unique to this way of implementing a component (compared, for example, to adapting a component). We'll match the component to one, or more, kickstartDS base components... and potentially make some slight adjustments.
Matching one or more components means finding components that are part of kickstartDS that can cover your use case, or one part of it. This way you create your component by composition.
- has a
topicthat can serve as our
textfor the body copy
- already includes options for a cover (
image), and even some options for it (
- can be
- and takes a
This seems to match really well!
While just matching a component can already get you pretty far, oftentimes you'll want to make some more adjustments to really make everything fit for you. And while the properties may match up really well, there's still some translation to do to make it work.
TeaserBox... we don't have to do anything for
image, as these already share a name and definition. In the case of
headline we just have to rename the prop (from
topic). And for
target we simplify the existing
link object to a single string property... hard coding the rest of the values in the process, while also renaming it.
3. Component Creation
In the third and final step we'll get to actually create our component. We'll encode the component API by creating its JSON Schema, and create a React template matching our selected properties to the kickstartDS base component.
JSON Schema definition
We establish the structure of components by creating a JSON Schema for them, defining their component API in code.
For an abridged version of that process, have a look at the
TeaserBox base component
This is the "full"
TeaserBox component API / JSON Schema. We've just reduced the property definitions.
Select from available props
Let's highlight the ones we've identified when thinking about our component structure before.
Create your component API
Subsequently we add exactly those fields to our own components component API / JSON Schema...
... and we rename props as needed, in the process.
And finally, set all the fields identified as
Finished component JSON Schema
The finished component definition in all its glory.
Using multiple components
This process can also involve using properties from multiple components. For example when building one like the
Storytelling component, using
You can either just merge properties on your root component, or group included components on their own property. Like adding a
link to something, which maps to the
Button component and some of its properties (as their own
object in your JSON Schema).
For the full version of creating the
TeaserCard have a look at our guide "Create
Now that our JSON Schema is defined, we'll automatically get matching TypeScript types for our component. We use those, combined with the types already included with the kickstartDS base component(s), to quickly hook up our set of properties to the mapped component(s). Using auto-complete, and TypeScript telling us about required properties in the mapped component(s), this is done in light speed!
To learn more about the tooling that create those types for you, and how to hook it up, see part four of our "Create your Design System" guide.
Let's continue showcasing this process using our
TeaserCard, creating the component template:
The main imports here are the kickstartDS base component(s) and our own components TypeScript types.
Add correct type to component
We need to type our React component to use our JSON Schema, while also making sure native HTML attributes are passed correctly. For the
TeaserCard this means also including
HTMLAttributes<HTMLElement> as it maps to a
<div> under the hood.
Doing this allows users of your component to enjoy having the same auto-complete and safety when working with your Design System.
Add parameters to component
Next we add all our components defined properties to its function signature. For properties having a default defined in your component API we add that default here, too.
As we also want to pass through all the props not explicitly managed by us we sponge up
Add the actual JSX
For our component JSX we can directly use the
TeaserBoxContextDefault, which is the kickstartDS base component.
Destructure additional props
Coming to our component JSX, we start by passing down (destructuring) the
props we're carrying through first. This ensures properties defined in our component API will always take precedence, because they're added after the general
Glue component API to base component 1/3
The simplest cases of connecting props to the base component is when the name of the property is taken from the base component. We can just directly pass those without much thought.
Glue component API to base component 2/3
In some cases we might have changed the name of a prop. In that instance, we just to have to wire up the renamed property to the originally named base components property.
Glue component API to base component 3/3
Finally there might be fields where we're using a set of properties of the mapped component(s), but only expose one of those in our own component API... the rest get hard coded.
That's the case with our
target property, which maps to the
link.href property of the
TeaserBox. We hard code the required
label property to Read more.
The final part of creating our React component is adding a component
Provider for it. As we've adapted a component here, we'll want to make sure that every time another component includes the base component, our own version of it gets used instead.
If you're wondering what that
Provider we've added last is all about, think about it like this:
There may be other components you've built, that themselves use the base
Button component by default. For example we might have our own
TeaserCard component, based on the kickstartDS
TeaserBox which includes a
As a means to not having to go through every combination of those component now, making sure our
Button actually gets used, you can just change the default
Button rendered by adding a single
Provider once, instead.
Learn more about
Providers and React Context in our dedicated page about them.
Or look at our "Create your Design System" guide, where we add the general setup for
Providers. That one also includes some more details on this!
Visual Studio Code component property quick-fix
Visual Studio Code has a great feature aiding in this workflow, with React components that include TypeScript types... like kickstartDS components do. When adding a "bare" component without props to your template, Visual Studio Code will offer you the option to
Add missing attributes.
This will automatically create all required options for your component. Now you just have to connect your own props to those, while hard-coding the ones you don't plan on exposing as part of your components component API.
Just hover the squiggly, red line that should be decorating your component, and choose
Quick Fix..., to get to that option (alternatively put your cursor on the component tag and hit
Technical debt added
This way of creating components adds minimal technical debt to your Design System. Not much has been changed around, we just add a small layer on top of the original kickstartDS base component(s).
Relevant underlying changes you'll have to look out for:
- changes to the base components component API
- removal of the base component(s)
You're immune to underlying changes to:
- the components template (both React, and the resulting HTML)
- the design and layout (changes to CSS, SCSS and Design & Component Token)
In the case of a changed component API, you should have a look at the corresponding
CHANGELOG.md and potential notes in our matching migration guide. You'll probably just need to add a newly added field to your React template, and potentially your own component API if you want to use it. If a field was changed, that might also necessitate some adaption of your own version. Finally a removed field you're actually using would mean adding additional customization to regain that functionality. Have a look at our
Headline example guide to see how you'd add your own, new property!
Learn more about what we mean by technical debt here on the overview page of this section.
We continuously expand our component example guides, below we've collected the ones acting as a good sample of the adaptation process.
In this example component guide we create the
TeaserCard component, mapped to the
TeaserBox component (part of the
@kickstartDS/base module), to tease content in our Design System. We greatly simplify the
Button to a single
string props, and drastically reduce the rest of the options used, and offered, in our own adaptation of the
This is what the result looks like:
In this example component guide we create the
Interstitial component, mapped to the
Storytelling component (part of the
@kickstartDS/content module), to add interstitial content elements that break the flow of content for really emphasized call-to-actions. As with all examples, we reduce the set of options greatly.
This is what the result looks like: