Sign Up

Custom reusable components

While Doctave comes with lots of useful reusable components out of the box, you can also create your own! This is incredibly useful if you want to implement a specialised widget that Doctave doesn't provide out of the box.

Tutorial

Let's walk through creating a custom "Card" component.

All custom components live under the _components directory at the root of your project (the same directory your doctave.yaml file is in).

Creating the component

Create the following file under _components/custom-card.md:

---
attributes:
  - title: heading
    required: true
---

<Box pad="3" class="custom-card-class">
  **{ @heading }**

  <slot />
</Box>

Don't worry about the details yet - let's first learn to invoke this component.

Rendering the component

Now, in your documentation, you can render the component with the following syntax:

<Component.CustomCard title="My title">
  The content that goes _inside_ the card
</Component.CustomCard>

Next, let's walk through this example to understand how components work in detail.

Attributes

Each component can define attributes that they will receive in its frontmatter. You can use these attributes as variables inside your component template.

Attributes must be declared in order to be used.

In the example above, we're defining a single attribute: heading:

---
attributes:
  - title: heading
    required: true
---

All attributes are put under the attributes field as a list of YAML objects. The attribute must define a title field, which must be a valid identifier.

Optionally, the attribute can be marked as required, in which case the caller gets an error if a value hasn't been provided for the attribute. Attributes that aren't required will default to null if no value is given.

Slot

It's common to want to let the callers of components to "inject" Markdown content inside your components. This is where the special <Slot /> tag comes in.

Let's look at the above component again:

<Box pad="3" class="custom-card-class">
  **{ @heading }**

  <slot />
</Box>

When this component is called, the <Slot /> component will be replaced with what the caller includes between the open and close tag of the component.

Let's look at another example. I want to add some body text and a custom Button into the card:

<!-- This will get turned into... -->
<Component.CustomCard title="My title">
  The content that goes _inside_ the card

  <button href="https://www.example.com">Sign Up</button>
</Component.CustomCard>

Here, the <Slot /> tag will be replaced with everything inside the open and close tag:

<!-- <Slot /> replaced with the following: -->
The content that goes _inside_ the card

<button href="https://www.example.com">Sign Up</button>

And the final output will be rendered as:

<Box pad="3" class="custom-card-class">
  **My title** The content that goes _inside_ the card

  <button href="https://www.example.com">Sign Up</button>
</Box>

Component names

Components derive their names from their path in your project. Every custom component is always prefixed by Component in order to prevent clashes with Doctave's built-in components.

All component names will be converted to camel case.

Here are some examples of the rules:

PathName
_components/example.mdComponent.Example
_components/example-button.mdComponent.ExampleButton
_components/example_button.mdComponent.ExampleButton
_components/button/primary.mdComponent.Button.Primary

NOTE: Component names may conflict! Two different paths may map to the same component name. In this case, any of the conflicting components may be chosen randomly.

Was this page helpful?