jgroth / kompendium

Documentation generator for Stencil components https://kompendium.dev/
MIT License
9 stars 5 forks source link
documentation kompendium stencil typescript webcomponents
hero

Kompendium

CI Version semantic-release

Introduction

Kompendium is a simple, fast and elegant tool for generating documentation for components made with Stencil.

Just type everything in Markdown, from your code blocks to description texts of example components. Then enjoy a lightning fast responsive compendium of your components, with component API and live playground.

Please note

Kompendium is still in development. Consider this an early preview!

Features

Demo

You can see a live demo of Kompendium, being used by Lime Technologies to create their component library and design system docs.

kompendium-darkkompendium-light

Contributing

Please see CONTRIBUTING for details.

Credits

Documentation

Getting started

Installation

Kompendium is available as a package on NPM and is installed using the NPM CLI

npm install kompendium

Configuration

Next, we need to configure Kompendium to generate our documentation. Kompendium runs using the docs-custom target in Stencil. We also need to copy the Kompendium components to our www folder in order to use them with the Stencil dev server.

stencil.config.ts
import { Config } from '@stencil/core';
import { kompendium } from 'kompendium';

export const config: Config = {
    namespace: 'my-project',
    outputTargets: [
        {
            type: 'docs-custom',
            strict: true,
            generator: kompendium()
        },
        {
            type: 'www',
            serviceWorker: null,
            copy: [{
                src: '../node_modules/kompendium/dist/',
                dest: 'assets/kompendium/'
            }]
        }
    ]
};

To get the generated documentation up and running, simply use the kompendium-app component in your index.html file. Don't forget to also include the scripts and styles, both for your own components and the ones that we copied during the build.

index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="description" content="My Stencil components">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <base href="https://github.com/jgroth/kompendium/blob/main/">
    <title>My Project</title>
</head>

<body>
    <link href="https://github.com/jgroth/kompendium/blob/main/build/my-project.css" rel="stylesheet" />
    <script type="module" src="https://github.com/jgroth/kompendium/raw/main/build/my-project.esm.js"></script>
    <script nomodule src="https://github.com/jgroth/kompendium/raw/main/build/my-project.js"></script>

    <link href="https://github.com/jgroth/kompendium/blob/main/assets/kompendium/kompendium/kompendium.css" rel="stylesheet" />
    <script type="module" src="https://github.com/jgroth/kompendium/raw/main/assets/kompendium/kompendium/kompendium.esm.js"></script>
    <script nomodule src="https://github.com/jgroth/kompendium/raw/main/assets/kompendium/kompendium/kompendium.js"></script>

    <kompendium-app></kompendium-app>
</body>
</html>

Running the dev server

Next, we can start the dev server by running

stencil build --dev --watch --serve --docs

Writing documentation

The generated documentation is fetched from the doc blocks inside the components source files. If we would have a component like the one below, it would generate the corresponding documentation. Kompendium understands how to read Markdown, so any additional markup will automatically be parsed.

my-component.tsx
import { Component, h, Prop } from '@stencil/core';

/**
 * This is a sample component
 *
 * Kompendium will parse the doc blocks and render it using Markdown
 */
@Component({
    tag: 'my-component',
    shadow: true,
})
export class MyComponent {
    /**
     * This is a sample property
     */
    @Prop()
    public name: string;

    render() {
        return <p>Hello, {this.name}!</p>;
    }
}

Adding examples

To improve the documentation even more, you can add examples of how to use your components. An example component is just another component that displays how your component is used. The example will be displayed both live and with the source code for the example. To include an example, the custom @exampleComponent doc block decorator should be used together with the name of the component. There is no limit to the number of components you can include.

my-component.tsx
import { Component, h, Prop } from '@stencil/core';

/**
 * This is a sample component
 *
 * Kompendium will parse the doc blocks and render it using Markdown
 *
 * @exampleComponent my-component-example
 */
@Component({
    tag: 'my-component',
    shadow: true,
})
export class MyComponent {
    /**
     * This is a sample property
     */
    @Prop()
    public name: string;

    render() {
        return <p>Hello, {this.name}!</p>;
    }
}

The example component in this case is very simple

my-component-example.tsx
import { Component, h } from '@stencil/core';

/**
 * This is an example for the `my-component` component
 */
@Component({
    tag: 'my-component-example',
    shadow: true,
})
export class MyComponentExample {
    render() {
        return <my-component name="World" />;
    }
}

It's recomended to either name all the examples in a similar fashion, or to place them in an examples/ folder or similar. This way, it's very easy to exclude them from the production build by excluding them in the Stencil configuration.

Type information

Kompendium can generate documentation about any custom Typescript types that you use in your components. You might have props or events that implement a custom interface and this should be documented as well so it is easy for the consumer of your components to use them.

Configuration

All types needs to be exported from a single file. The default name of this file is ./src/types.ts, but this can be configured if needed.

stencil.config.ts
{
    type: 'docs-custom',
    strict: true,
    generator: kompendium({
        typeRoot: './src/interface.d.ts'
    })
}

Note: This file should also be exported from the index.ts file so type hints will be available when consuming the components in a code editor.

Example

my-component.tsx
import { Component, h, Prop } from '@stencil/core';
import { MyData } from './my-data.ts';

/**
 * This is a sample component
 *
 * Kompendium will parse the doc blocks and render it using Markdown
 */
@Component({
    tag: 'my-component',
    shadow: true,
})
export class MyComponent {
    /**
     * This is a sample property
     */
    @Prop()
    public data: MyData;

    render() {
        return <p>Hello, {this.data.name}!</p>;
    }
}
my-data.ts
/**
 * This is a custom interface used in `my-component`
 */
export interface MyData {
    /**
     * The name to display when the component renders
     */
    name: string;
}
interface.d.ts
export * from './my-component/my-data.ts';

Configuration options

Option Description Default value
path Path to folder where Kompendium will store the generated data `.kompendium/
publicPath The public web distribution directory used by Stencil. www
title Title to display on top of the documentation Fetched from package.json
typeRoot Entry point for type information ./src/types.ts

Inheritance of styles and overriding them

You will be using Kompendium to generate documentation for your Stencil components and show both you and your consumers a preview of these components. Web components are inherently isolated, carrying their own styles that are not easily manipulated externally. However, it's important to note that Kompendium introduces its own styles, some of which are inherited by the web components displayed on the documentation page.

In most scenarios, this style-inheritance is inconsequential. However, when developing a comprehensive component library, certain generic CSS properties require careful attention to prevent them from being inherited from Kompendium. These typically include font-related styles such as font-family, font-size, line-height, and color.

Exactly because these are inherited properties, these are usually set at the :root level in the application consuming your web components, eliminating the need to specify them individually in each web component. To maintain style consistency, you can override these properties on the documentation page.

Kompendium offers a few CSS Custom Properties which enables you to do so.

You can define these properties for your instance of Kompendium as shown below:

<!DOCTYPE html>
<html dir="ltr">
    <head>
        <!-- other stuff in the `head` section -->
        <style>
            :root {
                --kompendium-example-color: #1d1d1d;
                --kompendium-example-font-family: 'Roboto', sans-serif;
            }
        </style>
    </head>

    <body>
        <!-- other stuff in the `body` section -->
        <kompendium-app path="/kompendium.json"></kompendium-app>
    </body>
</html>