Base Components

Base components serve as the basic building blocks of your UIs. They are simple components with little to no dependencies, and many dependents.

Run the following to create a basic UI component:

$bit
Copiedcopy
See command synopsis

Component API

Make your component's API available to other components by exporting it from the component's main file. Make sure to include the relevant type aliases and interfaces.

For example:

// index.ts
export { Button } from './button';
export type { ButtonProps } from './button';
CopiedCopy

Themeable

Base components need to be themeable to maintain consistency in style, across compositions.

Style your component using JS variables or CSS custom props that correspond to your theme schema. Provide each prop with a fallback value.

For example:

const Button = ({ children }) => {
  const style: React.CSSProperties = {
    backgroundColor: 'var(--primary-color-background, #568cb0)',
    padding: 'var(--button-padding-medium, 25)',
    fontWeight: 'var(--button-font-weight,  1rem)',
  };
  return <button style={style}>{children}</button>;
};
CopiedCopy

Customizable

A customizable component is component that is more likely to be used in new compositions. It allows its consumers to make adjustments via its API, which obviates the need for changes in the component implementation (changes that might force the consumer to create a new component).

Style

Your component should be able to accept style overrides. To achieve that, have an optional className prop included in its API. The className prop should always be placed last in the classnames list.

import { ReactNode } from 'react';
import cx from 'classnames';
import styles from './button.module.scss';

export type ButtonProps = {
  children?: ReactNode;
  className?: string;
};

export function Button({ children, className }: ButtonProps) {
  return <button className={cx(styles.button, className)}>{children}</button>;
}
CopiedCopy

Attributes

Include a ...rest (spread) prop in your component's API to make it extendable by additional attributes. Avoid type errors by extending your props type alias/interface with the attributes of the target HTML element.

For example:

import React, { ReactNode } from 'react';
import cx from 'classnames';
import styles from './button.module.scss';

export type ButtonProps = {
  children?: ReactNode;
} & React.HTMLAttributes<HTMLButtonElement>;

export function Button({ children, ...rest }: ButtonProps) {
  return (
    <button {...rest} className={className}>
      {children}
    </button>
  );
}
CopiedCopy

In the following example the 'Button' component is extended with an onClick event handler (although such prop has not been explicitly included in that component's API):

import { Button } from '@my-org/design.buttons.button';

const ButtonWithOnClick = () => {
  return <Button onClick={() => console.log('clicked!')}>Click me!</Button>;
};
CopiedCopy