Theming using CSS Variables? Turn Them into VS Code Snippets for Faster, Error-Free Coding
Tags: webdev, javascript, typescript, css
Published: 2024-04-14 13:34:12

Styling using native CSS (or pre-processor languages compiled to CSS) can be great as it offers better performance than JavaScript-based solutions.

In addition, CSS is as “universal” as it gets. You won’t waste your time learning framework-specific styling solutions that might become obsolete or fall out of favor, leading to costly refactoring later on.

Having said that, some aspects of the dev experience are vastly improved when using CSS-in-JS libraries or frameworks, mainly type support and IntelliSense.

One place where CSS is lacking the most is when using CSS vars (or custom props) to theme your UI components. In this scenario, the CSS props are often not included in the CSS file used to style the components but are instead defined elsewhere. This can become problematic when working with teams or large codebases, as the lack of direct visibility of variable definitions can lead to confusion and inconsistency.

To help solve this issue, we can use various tools such as VSCode extensions, ESLint plugins, and a number of other solutions. However, I’d like to offer another tool to the mix: generating VS Code Snippets based on the design tokens or theme specifications your team uses.

These code snippets are a great way to improve our dev experience. They can list the available CSS variables and even provide instructions on how and when to use them.

Our demo solution was built using [Bit](https://bit.dev), which allows us to create shareable components, render component “previews,” generate component docs, and so on.

[Our solution consists of four Bit components](https://bit.cloud/learnbit/style-snippets):

![](https://miro.medium.com/v2/resize:fit:4800/format:webp/1*bjNwg4GDeyHC1UDAGmhlFA.png)


- [**Design tokens**](https://bit.cloud/learnbit/style-snippets/design-tokens): This component holds the list of tokens for our design system

- [**My Theme**](https://bit.cloud/learnbit/style-snippets/my-theme): The theme component "feeds" [this theme generator](https://bit.cloud/teambit/base-react/themes/theme-provider) with the design tokens and their default values

- [**My React Env**](https://bit.cloud/learnbit/style-snippets/dev/my-react-env): A reusable React development environment that will auto-generate the snippet file when a themed Bit component is created or imported into the workspace. Reusable dev environments provide the tooling for Bit components (build pipeline, compilers, test runners, linters, etc). To complement this with proper IDE support, these dev environments also auto-generate the relevant config files for the IDE to read. [I've used this feature to auto-generate the code snippets file](https://bit.cloud/learnbit/style-snippets/dev/my-react-env/~code/my-react-env.bit-env.ts#l137-139).

- [**My Button**](https://bit.cloud/learnbit/style-snippets/my-button): The themeable UI component we'll build in this blog to test our entire setup. 

## Theming a component with the entire solution in place

To create new Bit components using the reusable development environment from before, we’ll add it to the `workspace.json`:

```json
/** @filename: workspace.jsonc */

{
 "teambit.generator/generator": {
    "envs": [
       "learnbit.style-snippets/dev/my-react-env",
    ]
  },
}
```

Now we can use the component templates offered by that env:

```bash
bit create react my-button
```

A new component directory with the pre-configured files was created.

```plaintext
└── my-button
    ├── index.ts <-- component main file
    ├── my-button.composition.tsx <-- component "previews" (isolated renders)
    ├── my-button.docs.mdx <-- component documentation
    ├── my-button.module.scss <-- component styles
    ├── my-button.spec.tsx <-- component tests
    └── my-button.tsx
```

In addition to that, since our component uses the reusable dev environment, a code snippet file was auto-generated for it at the root of the workspace:

```json
/** @filename: .vscode/scss.code-snippets */

{
  "--primary-color-background": {
    "prefix": "--primary-color-background",
    "body": [
      "var(--primary-color-background, #568cb0)"
    ],
    "description": "Use this color as the background for key UI elements that need to stand out. It should be used to promote actions or areas of importance."
  },
  "--primary-color-text": {
    "prefix": "--primary-color-text",
    "body": [
      "var(--primary-color-text, #ebebeb)"
    ],
    "description": "Use this color as the text color for key UI elements that need to stand out."
  }
}
```

Now, when we create styles for our components, we’ll be able to search for the custom CSS props that we need:

![](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*vbVkshlfxF7KW_-sdywoOQ.png)

To complete our UI component, we’ll create a preview for it using our theme:

```tsx
/** @filename: my-button/my-button.composition.tsx */

import { MyTheme } from '@learnbit/style-snippets.my-theme';
import { MyButton } from './my-button.js';

export const BasicMyButton = () => {
  return (
    <MyTheme.ThemeProvider>
      <MyButton>hello world!</MyButton>
    </MyTheme.ThemeProvider>
  );
};
```

If we head over to Bit UI, we can see the button’s preview:

![](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*mqL01X-Y_IvMPtlGjK3W0g.png)

### Sharing components

To share our components, we’ll create a new version of them and export them to Bit Platorm:

```bash
bit tag -m "new version"
bit export
```

The components are built on [Ripple CI](https://bit.cloud/products/ripple-ci), the CI system for components, offered by the Bit Platform:

![](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*9x_pqQgdUS2-Hqs3_dCqvQ.png)
 
As you can see, [Ripple CI](https://bit.cloud/products/ripple-ci) builds each component indepndently. Once a Bit component is built, the CI propagates to its dependents. When Bit components are siblings (one is not dependent on the other) Ripple builds them in parallel, to optimize the build’s performance.

Once the build is over, the [Bit components are available on Bit Cloud](https://bit.cloud/learnbit/style-snippets).

![](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*k9688sffjUVWQ4yMUM0JJA.png)