---
title: "Components Configuration"
description:
  "Configure static and dynamic component classes in Shilp CSS. Learn generation
  patterns and usage."
keywords:
  [
    "component configuration",
    "static components",
    "dynamic generation",
    "config setup",
  ]
---

# Components

Components are **ready-to-use classes** generated by Shilp CSS.

Unlike utilities (which are written inside `.css` files), components **expose
predefined class names** that you can directly use in HTML.

Example:

```html title="Component classes usage"
<div class="container">...</div>
<div class="screen-reader">...</div>
<p class="limit-lines">...</p>
```

Components can be **static** or **generated dynamically**.

---

<section>

## Why Components Exist

Intents and Mixins are great for writing styles inside CSS. But, sometimes you
need classes that should exist automatically.

Example: `.container`

A container usually depends on breakpoints. If a user changes breakpoints inside
`shilpConfig.theme.screens`, the container component should update
automatically.

Instead of manually writing media queries, Shilp CSS generates the component.
This keeps components **in sync with the theme configuration**.

These are reusable patterns that are easier to expose as classes.

</section>

<section>

## What Is a Component?

A component is simply a **regular CSS class**. It is a named collection of CSS
properties that can be used directly in HTML.

Example:

```css title="Base container class"
.container {
	width: 100%;
	margin-left: auto;
	margin-right: auto;
	padding-left: 1rem;
	padding-right: 1rem;
}
```

Shilp CSS provides:

- **Static components**: written in CSS
- **Dynamic components**: generated with JavaScript

<Alert variant="info">

`!important` flag (with `!` at end) is **not supported** at the component level.
If needed, add it per property.

</Alert>

<Alert variant="info">

You can also generate components using SCSS, but **JavaScript is recommended**
for dynamic generation.

</Alert>

</section>

<section>

## Location

There are two types of components.

### 1. Static Components

Defined in `shilpcss/styles/components.css`. These are normal CSS classes.

Example:

```css title="shilpcss/styles/components.css"
/* @import "./components/screen-reader.css"; */
.screen-reader { ... }
.screen-reader--none { ... }

/* @import "./components/limit-lines.css"; */
.limit-lines { ... }
```

To know more, read [Components](/docs/default-styles/components)

### 2. Dynamic Components

Defined in `shilpConfig.components`. Each root-level key is a **component name**
and value is a **component config**.

Example:

```js tilte="Component config example"
const shilpConfig = {
	source: "react",

	components: {
		container: { ... },
	},
};

export default shilpConfig;
```

This generates container component classes.

<Alert variant="info">

Component name and actual generated class name can be different. There are no
coupling.

</Alert>

#### Where Dynamic Components Are Inserted

During processing, generated components are appended to
`shilpcss/styles/components.css`.

Example file structure:

```css title="shilpcss/styles/components.css"
/* static components */
.screen-reader { ... }
.limit-lines { ... }

/* import("shilpcss-dynamic-components"); */
```

Shilp CSS detects this **exact comment string**
`/* import("shilpcss-dynamic-components"); */` and replaces it with generated
component classes during processing.

In other words, static and dynamic components **lives in a single file**.

<Alert variant="warning">

Dynamic components may override static component properties if they share the
same selector (same or lower specificity).

</Alert>

</section>

<section>

## Basic Shape of Components Config

```js title="Componet config"
const componentConfig = {
	disable: boolean, // optional
	// EITHER
	resolve: function, // optional if generateTree exists
	// OR
	generateTree: function, // optional if resolve exists
	mergeTree: function, // optional if resolve exists
}
```

You can use either `resolve` (`function`) or `generateTree + mergeTree` (both
are functions).

### resolve

The `resolve` function generates component classes as a **CSS string**.

```js title="Dynamically generated component string"
const shilpConfig = {
	source: "react",

	extend: {
		components: {
			ipsum: {
				resolve: (options) => {
					// custom component classes generation logic
					return `
						.any-component {
							@layout is-flex;
							max-width: theme(screens-lg);
						}
					`;
				},
			},
		},
	},
};

export default shilpConfig;
```

You can write normal CSS, intents, mixins and inline theme functions inside the
returned string.

#### Available Options

Custom component resolver `componentConfig.resolve` receives a single argument
(`object`) with following options:

| Option                    | Type     | Description                |
| ------------------------- | -------- | -------------------------- |
| `options.content`         | `string` | Raw CSS string             |
| `options.config`          | `object` | Full shilp config object   |
| `options.componentName`   | `string` | Mostly for error reporting |
| `options.componentConfig` | `object` | Full component config      |

<Alert variant="danger">

DO NOT MUTATE THESE OPTIONS.

</Alert>

#### Expected Output

The resolver must return **a string containing generated CSS classes**.

### generateTree

Instead of returning CSS as a string, you can generate a **structured tree
object**.

Unlike `resolve`, `generateTree` will let you modify the component tree
structure before it generates classes string.

This is useful when integrating third-party components. Know more at
[Merge Tree](#mergetree).

```js title="Dynamically generated component tree"
const shilpConfig = {
	source: "react",

	extend: {
		components: {
			ipsum: {
				generateTree: (options) => {
					// Custom component generator logic
					return {
						".ipsum": {
							width: "100%",
							"@space": "mx-auto;",
							"padding-left": "theme(spacing|spacing-4)",
							"padding-right": "theme(spacing|spacing-4)",
						},
					};
				},
			},
		},
	},
};

export default shilpConfig;
```

Rules:

- Keys must be unique at the same level
- CSS properties name must use **kebab-case**
- Values must be `string` or `object`

#### Writing Intents

Inside tree structure:

- Key → intent name starts with `@`
- Value → utility string ending with `;`

Example:

```js
{
	"@layout": "is-flex overflow-hidden shadow-lg;"
}
```

#### Writing Mixins

Inside tree structure:

- Key → mixin name starts with `@`
- Value → object containing styles

Example:

```js
{
	"@state hover": {
		"@layout": "is-flex;"
	}
}
```

#### Writing Inline Theme Function

Inline theme works normally.

Example:

```js
{
	"max-width": "theme(screens-lg);"
}
```

#### Available Options

`componentConfig.generateTree` receives a single argument (`object`) with
following options (same as `resolve`):

| Option                    | Type     | Description                |
| ------------------------- | -------- | -------------------------- |
| `options.content`         | `string` | Raw CSS string             |
| `options.config`          | `object` | Full shilp config object   |
| `options.componentName`   | `string` | Mostly for error reporting |
| `options.componentConfig` | `object` | Full component config      |

<Alert variant="danger">

DO NOT MUTATE THESE OPTIONS.

</Alert>

#### Expected Output

Must return a **tree object representing CSS structure**.

Shilp CSS will convert it into CSS.

### mergeTree

**Used together with `generateTree` ONLY**.

It allows modifying generated component trees before converted to string.

Useful for **overriding third-party component trees**.

Example:

```js title="Modify dynamically generated component tree"
const shilpConfig = {
	source: "react",

	extend: {
		components: {
			ipsum: {
				mergeTree: (options) => {
					// modify generated component tree
					// add changes only as it will be deep merged
					return changesOnGeneratedTree;
				},
			},
		},
	},
};

export default shilpConfig;
```

Rules:

- Works like `shilpConfig.extend` (deep merge)
- Set value to `null` or `undefined` to remove it from tree

Example to remove horizontal padding:

```js title="Modify dynamically generated tree before converting to string"
const componentConfig = {
	generateTree: () => { ... },
	mergeTree: (options) => {
		return {
			".container": {
				"padding-left": null,
				"padding-right": null,
			},
		};
	}
}
```

#### Available Options

`componentConfig.mergeTree` receives a single argument (`object`) with following
options (almost same as `generateTree`):

| Option                    | Type     | Description                         |
| ------------------------- | -------- | ----------------------------------- |
| `options.content`         | `string` | Raw CSS string                      |
| `options.config`          | `object` | Full shilp config object            |
| `options.componentName`   | `string` | Mostly for error reporting          |
| `options.componentConfig` | `object` | Full component config               |
| `options.generatedTree`   | `object` | Generated components tree structure |

<Alert variant="danger">

DO NOT MUTATE THESE OPTIONS.

</Alert>

#### Expected Output

Must return a **tree object representing CSS structure**.

<Alert variant="warning">

Return only what you want to modify, as it will be deep merged and not require
full `generatedTree`.

</Alert>

Shilp CSS now generates actual classes string.

### disable

You can disable any dynamic component. This **does not affect static components
or any other css classes**.

For example, to disable `container` component:

```js title="Disable container component"
const shilpConfig = {
	source: "react",

	extend: {
		components: {
			container: {
				disable: true,
			},
		},
	},
};

export default shilpConfig;
```

This prevents Shilp CSS from generating the component entirely, and any styles
defined inside it.

This can be useful when:

- Integrating third-party component classes
- Reducing bundle size
- Restricting allowed styling patterns

</section>

<section>

## High-Level Components Processing

At the beginning of processing:

- Internal default mixins are created from `shilpConfig.components` and loaded
- Root-level components `shilpConfig.components` override them completely (if
  provided)
  - This is not recommended. Avoid this.
- `shilpConfig.extend.components` is deep merged with `shilpConfig.components`

This defines which **components** are available.

Component processing happens during build generation. There is no runtime
evaluation.

See:
[Where Dynamic Components Are Inserted](#where-dynamic-components-are-inserted)

At this stage, component processing is done.

</section>

<section>

## Available Built-in Components Dataset

All built-in components datasets are documented separately.

You can explore the [full list](/docs/components) in the **COMPONENTS** section
of the documentation.

Each dataset has its own page: `/docs/components/<component-name>`

Examples:

- `/docs/components/container`
- `/docs/components/screen-reader`
- `/docs/components/limit-lines`

Those pages show exact components dataset structure with usage example.

</section>
