Creating a new module

Any new module added to @bulb/design will require a new module folder with a README, a CHANGELOG, and the code for the module itself.

Once a new module is created, documentation for the module needs to be added to the website.

Here's an example of how to create a new module called MyNewModule in the @bulb/design package:

cd packages/design
mkdir src/modules/MyNewModule && cd $_
touch README.mdx index.tsx MyNewModule.tsx MyNewModule.test.tsx MyNewModule.vr-test.tsx

Then, to add documentation for the module to the website:

  1. Make your new component available to the documentation renderer by adding it to the provider in website/src/components/MDXProvider/MDXProvider.tsx
  2. Add a new menu entry for your component in website/src/hooks/useMenu.ts

Component Structure

The pattern should be exported as a named export from a file matching the pattern name in the pattern folder.

Any pattern specific styled components used in the jsx for the patterns react component should come from an adjacent <Pattern>.styled.ts file.

Sub components (react components which are not part of the patterns public api, but used as part of the main react component) should be setup under a components folder.

Patterns should be exported from their module using a "barrel file" - an index.ts file which re-exports the public elements of the pattern.

- ./Tabs
- /components
- /Tab
- Tab.tsx
- README.mdx
- index.ts
- Tabs.tsx
- Tabs.styled.ts
- Tabs.test.tsx
- Tabs.vr-test.tsx
// ./Tabs/components/Tab/Tab.tsx
import * as React from 'react';
import styled from 'styled-components';
export const StyledTabContainer = styled.div`
/* styles */
export const Tab: React.FunctionComponent = (props) => {
return <StyledTabContainer>{props.children}</StyledTabContainer>;
// ./Tabs/Tabs.styled.ts
import * as React from 'react';
import styled from 'styled-components';
export const StyledTabsContainer = styled.div`
/* styles */
// ./Tabs/Tabs.tsx
import * as React from 'react';
import { Tab } from './components/Tab.tsx';
import { StyledTabsContainer } from './styled.tsx';
interface Props {
tabTitles: string[];
export const Tabs: React.FunctionComponent<Props> = (props) => {
return (
{ => (
<Tab key={tabTitle}>{tabTitle}</Tab>
// ./Tabs/index.ts (the barrel file)
export * from './Tabs';

How to structure props

The props interface should;

  • be directly above the react component it is for,
  • should not extend other types
  • if it contains nested types used by internal child components (ie declared in a file under /components)
    • these should be declared in the main component file, above the Props interface
  • and a consumer should be able to reason about it without having to open other files.
// ./Tabs/Tabs.tsx
interface TabProps {
/** title displayed on tab button */
title: string;
interface Props {
tabs: Tab[];
export const Tabs: React.FunctionComponent<Props> = (props) => {
return (
{ => (
<Tab key={tab.title} title={tab.title} />
// ./Tabs/components/Tab/Tab.tsx
import { TabProps } from '../Tabs';
export const Tab: React.FunctionComponent<TabProps> = (props) => {
return <StyledTabContainer>{props.title}</StyledTabContainer>;

Styled Components Naming Convention

All styled-components should be prefixed with "Styled".

export const StyledTabsContainer = styled.div``;
export const StyledTabTitle = styled.span``;

Styles Guidance

Formatting and Structure

  • Add a line break between declarations
  • Grouping
    • Interactive States (e.g. hover) should be grouped and come after base theme styles
    • Breakpoints should be included after states and grouped under the breakpoint name (these should increase based on size, e.g. sm, md, lg)


The following outlines the order for writing your styled components styles in a way that will be easier for you to manage.

  1. External Styles
    • Knowing that you are inheriting a bunch of styles from somewhere else is important, and listing first means you can override the inherited set if you need to.
  2. Component Styles (includes interactive states and breakpoints)
    • Adding component styles after allows us to properly override those properties if needed (Overriding styles should be limited as much as possible)
  3. Media Queries
    • Media queries typically affect regular styles or includes so we nest them before any pseudo elements of selectors
  4. Pseudo-classes and pseudo-elements
    • Pseudo elements and pseudo classes are directly related to the element itself so, for that reason, we nest them first before other selectors.
  5. Variant Styles
    • Variant styles which are how are variants unique visual execution are achieved
  6. State Styles
    • States styles should be common across variants and should work for all variants
  7. Nested components
    • Nested selectors should be avoided where possible, if needed they should come after pseudo-classes and pseudo-elements

Additional usage guidelines


  • Should reference a pre-defined colour from ./src/styles/theme.colours.ts
  • If it doesn't exist in ./src/styles/theme.colours.ts speak with design about either
    • adjusting to use one of these colours
    • or adding a new colour

Z-indexing Management

All z-indexes must be defined in the global z-index file under ./src/styles/zIndex.ts

Absolutely no hardcoded z-indexes allowed in the codebase.

JavaScript Hooks

If needed for third parties, javascript hooks can be added as classes, they should be prefixed e.g. gtm-track, gemini-card etc

This is to ensure we don't remove classes that are used by other scripts

Styled Components class names

DO NOT rely on styled components class names in your css or js - as they are based on a hash of the styles and will change with style changes.

CSS Entities for Pseudo-elements

When declaring css entities in a style object you need write css entities slightly different

content: '\\002f', // instead of content: '/002f',

To help, here is a handy conversion table:

CSS Property Order and Grouping

[[TODO: SUPPORT WITH LINTING]] While this would be great we do not expect you to do this without linting so don't get hung up on it, no one's going to pull you up on it!

Grouping your properties will help to create consistent stylesheets.

Grouping order:

  • Positioning - Positioning comes first because it can remove an element from the normal flow of the document and override box model related styles.
  • Layout - Dictates a components dimensions and placement.
  • Typography
  • Visual

Typography and visual come last because they take place inside the component or without having an impact on positioning and box model.

/** positioning */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
/** layout */
display: block;
float: right;
width: 10rem;
height: 10rem;
padding: 1rem;
margin: 1rem;
/** text */
font-size: 1rem;
line-height: 1.5;
color: #fff;
text-align: center;
/** visual */
background-color: #fff;
border: 1px solid #000000;
border-radius: 3px;
/** misc */
opacity: 1;

Matthew James Cowlishaw, Matthew David Smith and Daniel Francis Butters, each Insolvency Practitioners of Teneo Restructuring Ltd, were appointed Joint Energy Administrators of Bulb Energy Limited on 24 November 2021. The affairs, business and property of the Company are managed by the Joint Energy Administrators. The Joint Energy Administrators act as agents of the Company and contract without personal liability.