Skip to main content

Custom blocks

You can extend Tripetto with custom blocks (question types). When you develop a custom block, there are always two parts that you need to develop:

  • The builder part;
  • The runner part.

The builder part allows editors to use your block in the builder. It instructs the builder on how to handle the block and defines the configurable properties and settings for the block.

The runner part, on the other hand, contains the rendering of the block inside the runner. It defines the UI for the block and makes the block visible in the runner. This guide shows how you can create the runner part of a custom block for the stock runners.

info

Since the runner part defines the actual UI of the block, you need an implementation for each stock runner you want to use.

tip

See the blocks documentation to learn how to create the builder part of a custom block.

📃 Basic implementation

To define a new block for a stock runner, you need to register the block to the runner using the @tripetto decorator. This allows the runner to find and use your custom block. The code below shows the basic structure of a custom block for a stock runner. The most important part is the render method (or the answer and input method in the chat runner), where you define the UI for your block. The stock runners are built using React. So you need to use React when creating custom blocks for the stock runners.

custom-block.tsx
import { tripetto, NodeBlock } from "tripetto-runner-foundation";
import { namespace, IAutoscrollRenderProps, IAutoscrollRendering } from "tripetto-runner-autoscroll";
import { ReactNode } from "react";

@tripetto({
type: "node",

// Feed the namespace of the stock runner here.
// This is important!
namespace,

// This is the unique identifier for your block
identifier: "your-custom-block",
})
export class YourCustomBlock extends NodeBlock implements IAutoscrollRendering {
// This render function is invoked when your block renders in the runner UI.
render(props: IAutoscrollRenderProps): ReactNode {
return (
<>
Welcome to your custom block!
</>
);
}
}
info

Tripetto uses decorators for registering blocks. Therefore, you should always use TypeScript for developing blocks. Make sure to enable the experimentalDecorators feature.

Using your custom block

Make sure to import your custom block in the file where you use the runner. You only have to import the file. The block will self-register and become available in the runner.

import { run } from "tripetto-runner-autoscroll";
import "custom-block";

run({
definition: /* Supply your form definition here */
});

📰 Handling markdown

Tripetto supports markdown to add basic text markup (like bold, italic, underline) and references to other blocks in the form. If your block implements properties that need markdown support, you need to run them through one if the markdown functions.

custom-block.tsx
import { tripetto, NodeBlock } from "tripetto-runner-foundation";
import { namespace, IAutoscrollRenderProps, IAutoscrollRendering } from "tripetto-runner-autoscroll";
import { ReactNode } from "react";

@tripetto({
namespace,
type: "node",
identifier: "your-custom-block",
})
export class YourCustomBlock extends NodeBlock<{
customPropWithMarkdown: string;
}> implements IAutoscrollRendering {
render(props: IAutoscrollRenderProps): ReactNode {
return (
<>
Welcome to your custom block!
{props.markdownifyToJSX(this.props.customPropWithMarkdown)}
</>
);
}
}

💅 Using Styled Components

The stock runners are built using Styled Components. You can use Styled Components in your custom blocks rendering, but you need to make sure to import the styled method from the stock runner itself (otherwise, you might end up with two copies of Styled Components in your JS bundle).

custom-block.tsx
import { tripetto, NodeBlock } from "tripetto-runner-foundation";
import { namespace, IAutoscrollRenderProps, IAutoscrollRendering } from "tripetto-runner-autoscroll";
import { ReactNode } from "react";
import { styled } from "tripetto-runner-autoscroll";

const Button = styled.button`
background: palevioletred;
border-radius: 3px;
border: none;
color: white;
`;

@tripetto({
namespace,
type: "node",
identifier: "your-custom-block",
})
export class YourCustomBlock extends NodeBlock implements IAutoscrollRendering {
render(props: IAutoscrollRenderProps): ReactNode {
return (
<>
Welcome to your custom block!
<Button />
</>
);
}
}

👔 Using fabric components

The stock runners use the input components from the Tripetto Runner Fabric package. If you want, you can use these components in your custom block. For convenience, you can import any fabric component directly from the stock runner packages. See the Runner Fabric reference for an overview of all components included.

custom-block.tsx
import { tripetto, NodeBlock } from "tripetto-runner-foundation";
import { namespace, IAutoscrollRenderProps, IAutoscrollRendering } from "tripetto-runner-autoscroll";
import { ReactNode } from "react";
import { CheckboxFabric } from "tripetto-runner-autoscroll";

@tripetto({
namespace,
type: "node",
identifier: "your-custom-block",
})
export class YourCustomBlock extends NodeBlock implements IAutoscrollRendering {
render(props: IAutoscrollRenderProps): ReactNode {
return (
<>
Welcome to your custom block!
<CheckboxFabric
styles={props.styles.checkboxes}
tabIndex={props.tabIndex}
onAutoFocus={props.autoFocus}
onFocus={props.focus}
onBlur={props.blur}
/>
</>
);
}
}

📖 Reference

Have a look at the complete autoscroll runner API reference for detailed documentation. In the examples above, the following symbols were used: