# Agent Instructions
This repository is a monorepo managed with **pnpm** and **Nx**. It contains multiple packages under `packages/` such as web components, themes, adapters, samples and tooling.
## Handling hints
We have a monorepo structure with multiple packages, each with its own `package.json`. The root `package.json` contains shared dependencies and scripts. Use `pnpm` commands to manage dependencies and run scripts across packages.
- To install dependencies, use `pnpm i` at the root level. This will install all dependencies for all packages.
- If you change a dependency in a package:
- Use only exact version numbers in `package.json`. Other peers will not be able to use the package if you can use a range version.
- You need to run `pnpm i` at the root level. This updates the lockfile and ensures all packages are using the correct versions.
- Never add a `packageManager` field to any `package.json` file.
- Avoid that branch name may contain hidden characters.
- If something does not work, check in the event of an error whether all dependent submodules have been built.
- To build a single package faster, run commands with downstream dependents using `pnpm --filter ...<package>` (e.g., `pnpm --filter ...@public-ui/sample-react build`).
## 🚨 Format-first rule
> **Stop before you commit:** run the formatter so CI never rejects your patch for style drift.
1. Run `pnpm format` from the repo root whenever you change code, docs or configs.
2. If you only touched one package, you may instead run `pnpm --filter <package> format` for a quicker pass.
3. Re-stage the affected files (`git add -u`) so the formatted result is what lands in the commit.
No package scripts in this repo need extra flags such as `-- --write`; the scripts already know when to write changes versus just check.
## Semantic Versioning
This repository follows **Semantic Versioning** (SemVer) for all packages. Each package version is defined in its own `package.json` file. The versioning scheme is as follows:
- **Major version**: Incremented for incompatible API changes.
- **Minor version**: Incremented for adding functionality in a backwards-compatible manner.
- **Patch version**: Incremented for backwards-compatible bug fixes.
If we deprecate a feature, we will mark it as deprecated in the code and documentation, but we will not remove it immediately. Instead, we will provide a migration guide (migration\*.md) for users to transition to the new feature. Also we provide a migration tool in the `packages/tools/kolibri-cli` package to help with the migration process. You have to add a migration task from the previous version to the new version in the `packages/tools/kolibri-cli/src/migrations` folder. In the migration package, are a lot of migration tasks already implemented, so you can use them as a reference.
## Project Structure
- `packages/components` – Stencil based web components
- `packages/components/src/component` – components
- `packages/components/src/schema` – schema definitions for all components
- `packages/samples` – sample applications demonstrating usage
- `packages/samples/angular` – Angular sample app; do not edit
- `packages/samples/react` – React sample app; all samples; write component samples here
- `packages/adapters/*` – generated framework integration packages; do not edit
- `packages/themes` – style themes and assets
- `packages/themes/default` – primary maintained standard theme
- All other themes are not actively maintained
- `packages/tools/kolibri-cli` – helper CLI for migration
- Documentation lives in `docs/`.
- Do always ignore and do not edit all `assets` folders in all packages, as these are generated by the build process and should not be edited manually. If you need to change something in the assets, you have to change it in the source code and rebuild the package.
## Theming
The theming is realized with adopted style sheets on web components and will be adopted at the mounted hook of the components. All following styling rules are only relevant for the `components` and `themes` packages.
### The 5 styling layers
1. **A11y Preset layer**: This layer comes out of the `adopted-style-sheets` package and contains the basic styles for accessibility. It is applied to all components.
2. **Basis Global layer**: This layer contains the basis global styles for all components and comes out of the `@public-ui/components` package. It is applied only component specific layout styles without margins and paddings. Generally, the styling works without colors, as the colors should only be set through the custom Theme Layer.
3. **Basis Component layer**: This layer contains the basis styles for one component and comes out of the `@public-ui/components` package. It is applied only component specific layout styles without margins and paddings. Generally, the styling works without colors, as the colors should only be set through the custom Theme Layer.
4. **Theme Global layer**: This layer contains the global styles for all components of a theme and comes out of a own theme package, like `@public-ui/theme-default`.
5. **Theme Component layer**: This layer contains the component specific styles for one component of a theme and comes out of a own theme package, like `@public-ui/theme-default`.
### Global accessibility styles
```css
/*
* This file contains all rules for accessibility.
*/
@layer kol-global {
:host {
/*
* Minimum size of interactive elements.
*/
--a11y-min-size: #{rem(44)};
/*
* No element should be used without a background and font color whose contrast ratio has
* not been checked. By initially setting the background color to white and the font color
* to black, the contrast ratio is ensured and explicit adjustment is forced.
*/
background-color: white;
color: black;
}
* {
/*
* This rule enables the word dividing for all texts. That is important for high zoom levels.
*/
hyphens: auto;
/*
* Verdana is an accessible font that can be used without requiring additional loading time.
*/
font-family: Verdana;
/*
* Letter spacing is required for all texts.
*/
letter-spacing: inherit;
/*
* This rule enables the word dividing for all texts. That is important for high zoom levels.
*/
word-break: break-word;
/*
* Word spacing is required for all texts.
*/
word-spacing: inherit;
}
/*
* All interactive elements should have a minimum size of rem(44).
*/
/* input:not([type='checkbox'], [type='radio'], [type='range']), */
/* option, */
/* select, */
/* textarea, */
[role='button'],
button:not([role='link']),
.kol-input .input {
min-height: var(--a11y-min-size);
min-width: var(--a11y-min-size);
}
/*
* Some interactive elements should not inherit the font-family and font-size.
*/
a,
button,
h1,
h2,
h3,
h4,
h5,
h6,
input,
option,
select,
textarea {
/*
* All elements should inherit the font family from his parent element.
*/
font-family: inherit;
/*
* All elements should inherit the font size from his parent element.
*/
font-size: inherit;
}
}
/**
* Sometimes we need the semantic element for accessibility reasons,
* but we don't want to show it.
*
* - https://www.a11yproject.com/posts/how-to-hide-content/
*/
.visually-hidden {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
```
### Styling rules
The basis global layer set the default font-size and box-sizing for all components.
```css
@layer kol-global {
:host {
font-size: rem(16);
/*
* The max-width is needed to prevent the table from overflowing the
* parent node, if the table is wider than the parent node.
*/
max-width: 100%;
}
* {
/*
* We prefer to box-sizing: border-box for all elements.
*/
box-sizing: border-box;
}
...
}
```
### Custom Theming rules
The custom theme layer is used to set the colors and other theme specific styles. The custom theme layer should not contain any layout styles, as these are already set in the basis global and component layers.
For example, generally the font-family is set in the theme global layer, on the `:host` element, so that all components inherit the font-family from the theme. The font-size is set in the basis global layer, so that all components inherit the font-size from the basis global layer. But it is possible to set a other base font-size in the theme global layer, if needed.
```css
@layer kol-theme-global {
:host {
--font-family: var(--kolibri-font-family, Verdana, Arial, Calibri, Helvetica, sans-serif);
--font-size: var(--kolibri-font-size, #{rem(16)});
...
}
:host {
font-size: var(--font-size);
* {
font-family: var(--font-family);
}
}
...
}
```
In the theme component layer, you can set what ever you need to realize your own custom style guidelines. For example, you can set the colors, borders, shadows, etc. for the component.
```css
@layer kol-theme-component {
...
}
```
### CSS Custom Properties and SASS Variables
CSS custom properties remain part of the global cascade and are not isolated by the Shadow DOM.
Overusing them in theme files can collide with variables defined on a host page.
Expose only well‑prefixed design tokens as custom properties and rely on SASS variables for
internal calculations to keep components robust and avoid unintended style leaks.
### General rules for custom themes
- Do not use `!important` in your styles, as this will override the styles of the basis global and component layers.
- Do only overwrite styling definitions you will really customize. Do not set styling definitions that are already set (redundant) in the basis global and component layers, as this will override the styles of the basis global and component layers.
- Do not `inherit` styles over the `:host` element, as this will override the styles of the basis global and component layers. This makes your component less robust from outside environment styles. Only the `kol-icon` inherits some specific styles, like `color`, `font-size`, `font-family` and `line-height`, as these are needed for the icon to be displayed correctly inline to this neighbored elements.
- Do not set the default `font-family`, `font-size` or `box-sizing` in the basis or theme component layer (redundant), as these are already set in the basis global layers. If you need to set a different font-family or font-size, you can do this in the theme global layer.
- Do not set `margin` or `padding` in the basis global and component layers. If you need to set a different margin or padding, you can do this in the theme global or component layers.
- Do not use `overflow: hidden` in styling or theming, as it often causes issues for reuse and should be avoided.
- **Do not use `@layer` declarations in utility files**: Helper files, mixin files, and partial files (starting with `_`) should not contain `@layer` declarations. These files are utilities and should be layer-agnostic. This is enforced by the custom Stylelint rule `kolibri/no-layer-in-utility-files`.
## Samples
The samples are located in `packages/samples/react` and demonstrate how to use the components in react. Each component has its own folder and the basic sample are in `basic.tsx`. Other stories can be added in the same folder. All samples of a component are registered in the `routes.ts` file.
## Coding Conventions
- Formatting is enforced via **Prettier** with settings defined in `prettier.config.js` (print width 160, single quotes, tabs).
- `.editorconfig` sets `indent_style = tab` and `max_line_length = 160` for code files. Markdown and YAML files use spaces.
- ESLint and Stylelint are run using `pnpm lint`. Pre‑commit hooks run `lint-staged` which formats and lints changed files. Lint rules should **not** be disabled via inline comments. Instead, describe the problem and work towards a clean solution.
- Lists and enumerations in code should be kept in alphanumeric order. This also applies to import specifiers and union type literals.
- Do not disable ESLint, Stylelint or TypeScript rules inline. Fix the code instead of turning such rules off.
- ESLint and Stylelint are run using `pnpm lint`. Pre‑commit hooks run `lint-staged` which formats and lints changed files.
- Lists and enumerations in code should be kept in alphabetical order (see `docs/tutorials/NEW_COMPONENT.md`).
- Commit messages follow the **Conventional Commits** specification.
- See also the [Contributing Guide](CONTRIBUTING.md) for more details on coding conventions and best practices.
- Spell "KoliBri" with this casing in all documentation and code. The only exception is the component named KolKolibri.
- Use ESM import syntax in browser code and scripts whenever supported, instead of `require` imports.
- Do not create barrel files (e.g. `index.ts` that re-export modules). Import modules directly instead.
- Do not place constant declarations before import statements; imports must always be at the very top of the file.
- **Scripts must be platform-independent**: All scripts in the `scripts/` folder must work on Windows, macOS, and Linux without requiring external tools or platform-specific dependencies. Use Node.js built-in modules instead of external command-line tools like `rg`, `grep`, `find`, etc.
## Linting and Formatting
- Run `pnpm lint` to check for linting errors across all packages. This script runs ESLint, Stylelint and TypeScript checks. You can try to automatically fix linting issues with `pnpm lint:eslint --fix`, but this may not resolve all issues.
- Ensure all packages are built by running `pnpm build` before executing `pnpm lint` or `pnpm test`. Some packages rely on generated artifacts that linting and testing depend on.
- Run `pnpm format` to format all code files using Prettier. You can try to automatically fix linting issues with `pnpm format -w`, but this may not resolve all issues.
- If your pull request only modifies Markdown files, skip `pnpm build`, `pnpm lint` and `pnpm test`. Just format the Markdown using `pnpm format` or Prettier.
### Pre-commit checklist
- **Always run `pnpm format` (or `pnpm --filter <package> format` for a single workspace) right before committing.** Formatting failures are one of the most common reasons for blocked quality gates, so make this the last step before `git commit` even for documentation-only changes.
- After formatting, re-stage affected files with `git add -u` so the formatted content is what gets committed.
## Testing
- Run `pnpm test` from the repository root to execute all unit and integration tests.
- Visual and snapshot tests can be updated with `pnpm test:update` or via the `update-snapshots.yml` GitHub workflow (see `CONTRIBUTING.md`).
- Individual packages provide their own test scripts (e.g. `pnpm --filter @public-ui/components test:unit`).
## Pull Request Guidelines
- PR titles should be meaningful as they appear in the release notes.
- Every PR must link to its issue and contain only changes related to that issue.
- Ensure automated tests pass and manual testing is completed when required.
- Update documentation or migration guides if your changes affect them.