Skip to main content

Extending Genesis components

info

This approach to styling requires writing components using Genesis syntax.

Genesis components are designed to be extensible, enabling you to create custom components with configurable styles and functionality. In this example, we’ll create a MyButton component by extending the RapidButton component from the Rapid Design System.

You can do this in five steps.

Step 1: Import the dependencies

  • RapidButton for the base button component
  • buttonTemplate for reusing the existing button template
  • buttonShadowOptions for the button's Shadow DOM configuration
  • a separate custom styles file, my-button.styles.ts
import {
Button as RapidButton,
buttonTemplate as template, // Importing RapidButton's template
buttonShadowOptions as rapidButtonShadowOptions,
} from '@genesislcap/rapid-design-system';
import { myButtonStyles as styles } from './my-button.styles';

Step 2: Extend RapidButton

Create a new MyButton class that extends RapidButton. This enables you to inherit the functionality of the base button while applying your custom styles and configurations.

/**
* MyButton component, extending RapidButton with custom styles.
*/
export class MyButton extends RapidButton {}

Step 3: Compose the component

The compose method enables you to combine the base button's template, custom styles, and shadow options into a new reusable component.

/**
* Composing MyButton with custom styles while reusing the RapidButton template.
*/
export const myButton = MyButton.compose({
baseName: 'my-button', // Base name for the component
template, // Reusing the RapidButton template
styles, // Your custom styles for MyButton
shadowOptions: rapidButtonShadowOptions, // Shadow DOM configuration
});

Step 4: Define custom styles

Create a my-button.styles.ts file to define the custom styles for MyButton. Use CSS custom properties and design tokens for consistency. This simple definition specifies colour, font, border and padding (which sets the space around the button).

import { css } from '@genesislcap/web-core';

export const myButtonStyles = css`
:host {
background-color: lightgray;
color: black;
padding: 10px 20px;
border-radius: 4px;
font-family: Arial, sans-serif;
font-size: 14px;
}
`;

Step 5: Register the component

Finally, in the .ts file where you register your components, add the MyButton component`:

import * as rapidDesignSystem from '@genesislcap/rapid-design-system';
import { myButton } from './my-button';

rapidDesignSystem.provideDesignSystem()
.register(
myButton(),
rapidDesignSystem.baseComponents,
);
warning

A common error when registering your customized components is registering them after the base component has already been registered - meaning your change will not be visible.

In the code above, note that myButton() is registered before rapidDesignSystem.baseComponents. This ensures that the component with the custom styling you've created takes priority over the base implementation.

A complete example

import {
Button as RapidButton,
buttonTemplate as template,
buttonShadowOptions as rapidButtonShadowOptions,
} from '@genesislcap/rapid-design-system';
import { myButtonStyles as styles } from './my-button.styles';

/**
* MyButton component, extending RapidButton with custom styles.
*/
export class MyButton extends RapidButton {}

/**
* Composing MyButton with custom styles while reusing the RapidButton template.
*/
export const myButton = MyButton.compose({
baseName: 'my-button',
template,
styles,
shadowOptions: rapidButtonShadowOptions,
});

my-button.styles.js

import { css } from '@genesislcap/web-core';

export const myButtonStyles = css`
:host {
background-color: lightgray;
color: black;
padding: 10px 20px;
border-radius: 4px;
font-family: Arial, sans-serif;
font-size: 14px;
}
`;

Registering the component

import * as rapidDesignSystem from '@genesislcap/rapid-design-system';
import { myButton } from './my-button';

rapidDesignSystem.provideDesignSystem()
.register(
myButton(),
rapidDesignSystem.baseComponents,
);