Extend Section
component
This guided example shows how you'd add components to your Design System that use a kickstartDS base component pretty directly. But unlike just adapting a component, extending a component also involves adding something to it, or changing the way certain things work under the hood, by composing multiple kickstartDS base components (whereas customizing a component does that by adding changes to the customized components React template). This expands possible applications of existing kickstartDS components greatly.
Even while using the component rather directly from kickstartDS, you'll want to find the correct set of properties for your own use case. Components in kickstartDS come equipped with properties for a wide range of possible use cases, so it makes sense to reduce those to the ones you really need... to make components easier to understand, use and reason about!
We call this type of workflow Extension. Learn more about it in our dedicated guide about it. If you're unsure about something, have a look over there. We go into more background detail there about what we're doing here.
Not touching the actual markup generated by components let's us get by without adding any custom styling (CSS / SCSS) to it. We simply reuse the already existing Design Token and component structure.
Overview
This is how the result of this guide will look like:
It will only need two simple steps for that:
- Component Definition, and
- Component Creation
For more details about those steps, have a look at the guide about different component processes and their shared structure.
Requirements
This guide assumes that you already have a working Design System, that is based on kickstartDS, running.
If that's not the case, follow our Create your Design System guide.
1. Component Definition
Purpose
We've found that we'd love to use the existing kickstartDS Section
, but it's not quite flexible enough for our taste. We'd like to add more call-to-actions to our page, which mostly consists of such Section
s, and don't need as much flexibility for the included headline.
We take width
, gutter
, mode
, content
, spaceBefore
, spaceAfter
and inverted
directly from the Section
, and rename background
to style
for our version of it. And crucially we add our own property ctas
, to hold call-to-actions, into the mix, while reducing the complexity of headline
significantly... from mapping to all of the Headline
properties, to just a single string
type prop setting its content.
We also keep the name Section
, as it fits our use case well enough already.
Structure
Defining the structure of a component means finding the component API for it:
Property | Type | Description |
---|---|---|
headline | string | Headline for the section |
width | enum | Width of section to use |
gutter | enum | Size of gutter to use |
mode | enum | Layout mode used for section contents |
content | array | Allowed content for the section |
style | enum | Style of section, influences background |
spaceBefore | enum | Amount of spacing before the section |
spaceAfter | enum | Amount of spacing after the section |
inverted | boolean | Whether to invert the section |
ctas | array | Call-to-actions to show |
ctas[].label * | string | Label for the Call to action |
ctas[].target * | string | Target for the Call to action |
Fields that should be required are marked with a *
.
While directly helping us get a better grasp on our new component, these will also be used to write our JSON Schema
later!
2. Component Creation
We like to colocate components. This means to have all involved files next to each other in the same folder; the template (.jsx
/ .tsx
), potential CSS / SASS (.css
/ .scss
), JavaScript (.js
/ .ts
), our JSON Schema component definition (.schema.json
), and so on.
So we start by creating the directory src/components/section
, from our Design System repository root:
This is the folder we'll add new files to in the coming few paragraphs.
JSON Schema definition
First file we'll create is the JSON Schema
definition, encoding the structure we've defined for our component before:
Finished JSON Schema
We'll work our way up to this JSON Schema definition.
Start with just the boilerplate for a component definition
This includes all necessarily required values for a valid component definition in kickstartDS.
Add basic info describing component
We start by adding a title
, description
and $id
attribute. The correct $id
depends on your Design System configuration. We'll assume you've created components before, living under the schema prefix http://schema.mydesignsystem.com
.
Create headline
field
The headline
field is a straight-forward string
type properties, so we just document it a bit!
We do mark it by setting format
to markdown
, though, to enable some light RTE-like formatting options of the rendered text later on.
Add allowed width
s 1/2
We add a width
property of type string
...
Add allowed width
s 2/2
... and make it an enum
, defining its available options explicitly. We also set a default
.
Add allowed gutter
s 1/2
We add a gutter
property of type string
...
Add allowed gutter
s 2/2
... and make it an enum
, defining its available options explicitly. We also set a default
.
Add allowed mode
s 1/2
We add a mode
property of type string
...
Add allowed mode
s 2/2
... and make it an enum
, defining its available options explicitly. We also set a default
.
Add allowed content
s
We add a field content
of type array´. Let's assume we have three components that can be used as content for the section. We reference each one using
anyOfand
$ref`.
Add allowed style
s 1/2
We add a style
property of type string
...
Add allowed style
s 2/2
... and make it an enum
, defining its available options explicitly. We also set a default
.
Add allowed spaceBefore
s 1/2
We add a spaceBefore
property of type string
...
Add allowed spaceBefore
s 2/2
... and make it an enum
, defining its available options explicitly. We also set a default
.
Add allowed spaceAfter
s 1/2
We add a spaceAfter
property of type string
...
Add allowed spaceAfter
s 2/2
... and make it an enum
, defining its available options explicitly. We also set a default
.
Add inverted
property
We add a property inverted
, as a boolean
.
Add ctas
property 1/2
We add the ctas
property of type array
, this will hold our call-to-action related properties label
and target
.
Add ctas
property 2/2
We specify the array items
type, adding an object
with properties label
and target
to it, both of simple string
types (with target
having format
set to uri
to enable resource-like behaviour).
Finished JSON Schema
Let's have a look at our completed JSON Schema definition.
This concludes creating the JSON Schema
. When running the schema generation in our Design System again, we should now automatically end up with a corresponding type definition to be used in creation of the template in the next step:
How your schema generation is started might change depending on your setup. If you've followed our "Create your Design System" guide before, or want to add it like we do, follow this section of it closely.
React template
As the final step for this example, we'll add the template. This will be a purely functional React
component, mapping our component structure (as defined in the JSON Schema
) to the original component we're basing our work off of; the kickstartDS Storytelling
component.
Finished React template
We'll work our way up to this React template.
Start with a boilerplate
Again we'll start with a very basic skeleton for our React component. We're using TypeScript here (.tsx
), but it works the same with plain JSX (.jsx
).
Add correct typings
Import and add generated props from SectionProps.ts
. Generated by our JSON Schema, these guarantee you're matching your expected component structure while implementing. In combination with TypeScript this enables auto-complete and auto-fix for even better DX! (see here, at the very end of that section, for more details)
We also add HTMLAttributes<HTMLElement>
to the type signature for the props
that we'll pass through to the native HTML element underneath.
Destructure props
We also need to add our own properties, so we'll destructure props
. We add our default
values here, too. We'll just pass through everything HTMLAttributes
related!
Add Section
component 1/7
Now we'll import and add the kickstartDS Section
component. To start, we'll use the hard-coded properties of the Content Boxes Section
variant from our kickstartDS Design System.
We'll omit the child components added there (ContentBox
es), as they only exist for illustrative purposes inside that Storybook. We will just pass children
through to the original Section
, later.
Add Section
component 2/7
We remove all of the unneeded stuff, as there are a bunch of properties that are completely optional, mainly those having their values undefined
or null
in the copied JSX, or ones which just state the default
value of that property anyway. Those can be freely removed.
Add Section
component 3/7
We now import the component we want to use to display the call-to-actions, in this case a Button
included in our own Design System. We also add a second Section
(losing its headline
) to hold our Button
s, and connect those to cta.label
. We choose the variant of Button
by index, first equals primary
, second means secondary
and all others are tertiary
.
Add Section
component 4/7
We then connect the props as defined in our component API that are directly taken from the underlying kickstartDS base component by just passing them through. We also destructure props
first, so our own properties take precedence when set. We add it to the first Section
, that will always be rendered.
Add Section
component 5/7
We renamed background
to style
in our component API, so we add that in its renamed form... to both Section
s.
Add Section
component 6/7
We connect our property headline
to the first Section
s headline.content
.
Add Section
component 7/7
As a final step, we make sure the spacing between the two Section
s is optimized, so it will look seamless later on. We also hard code some options of the second Section
.
Add component Provider
We want our Section
to replace all default kickstartDS base Section
s, no matter where they appear. We add a Provider
for that purpose now!
Finished React template
Let's have a look at our completed React template.
To complete the template we add the SectionProvider
to our src/components/Providers.jsx
:
This concludes the creation of our new Section
component. It's now ready to be used inside your Design System, and available to your down stream consumers... hopefully efficiently closing a gap for them!
Use of Storybook
If you're using Storybook, you can follow this part of the example to get all the integration goodness possible with kickstartDS!
Storybook setup
This guide assumes you're using a set up like described in our Create your Design System guide! Be sure to adapt commands and configuration to your use accordingly, when following this part!
Add the following file to your src/components/section
folder:
Import re-usable Section
Stories
Import Section
component and add it to the Template
that we'll bind Stories to.
Import re-usable TeaserCard
Stories
Import TeaserCard
Stories as demo content for our Section
Story. Add them to the Template
, too.
Import Storybook Controls helpers
Import dereferenced component JSON Schema and getArgsShared
helper to generate Storybook Controls, and parameterize Storybook JSON Schema Addon.
Overwrite Story values where needed
We set all the Story defaults specific to our component.
Convert args to flat keys
We use pack
to convert all deep JSON args to flat (.
delimited) keys and values. This is the format your Storybook Controls get generated off.
Create Section
variants
We do this by binding to our Template
, and use pack
to convert all deep JSON args to flat (.
delimited) keys and values. This is the format your Storybook Controls get generated off.
If you reopen your Storybook now, or if you kept it running while following along, you should now see your new Section
in all its glory!
Finished Code Sandbox
You can also have a look at the completed component in the following Code Sandbox:
Toggle the file browser with the hamburger icon at the top left, or open it directly in your browser.