# Staticview
> Framework-agnostic web components, authored as standard HTML/CSS/TS and compiled to zero-dependency custom elements.
> The Guides and Components sections of https://staticview.a-labs.space/llms.txt inlined in full, so no links need following.
---
## Web Components Handbook
A practical guide to using web components.
This covers the core concepts you need to work with any web component library effectively.
---
### The Shadow DOM
The shadow DOM is an encapsulated DOM tree attached to a custom element.
It is isolated from the main document: styles defined outside do not bleed in, and styles defined inside do not leak out.
The exception is inherited CSS properties. Properties like `font-family`, `color`, and `line-height`
inherit through the shadow boundary the same way they inherit through normal DOM nesting.
A rule like this will affect text inside any component on the page:
```css
body {
font-family: Inter, sans-serif;
color: #111;
}
```
This is by design. It lets components pick up your base typography without any extra configuration.
Everything else, selectors, class names, non-inherited properties, does not cross the boundary.
The sections below cover what does work for theming.
To inspect the shadow DOM of a component in the browser, open DevTools and select the element.
Chrome and Firefox both render the shadow root inline in the Elements panel.
In some browser versions this requires enabling "Show user agent shadow DOM" in the DevTools settings first.
This is useful when you need to understand the internal structure of a component before theming it.
---
### Registration
A web component is a custom HTML element registered against a tag name using `customElements.define()`.
Tag names must contain a hyphen, this is the browser's way of distinguishing custom elements from native ones.
This registration is global and happens once per page. Registering the same tag name twice throws an error.
```js
// This runs once when the component module is loaded.
// Any subsequent import of the same module is a no-op.
customElements.define("my-button", MyButton);
```
In practice this means the component's module should be imported once at the application level or entry point, not in every file that uses the element.
After registration the tag is available everywhere in the document.
---
### Attributes, Properties, and Methods
These work the same way they do on native HTML elements, because web components are HTML elements.
**Attributes** are set in HTML markup or via `setAttribute`. They are always strings.
```html
```
```js
el.setAttribute("placeholder", "Enter your name");
el.removeAttribute("disabled");
```
Boolean attributes follow the HTML convention: presence means true, absence means false. The value does not matter.
**Properties** are accessed via JavaScript. They can hold any type: booleans, numbers, objects, arrays.
```js
el.value = "hello";
el.disabled = true;
console.log(el.count); // number
```
A component will usually keep an attribute and its corresponding property in sync, just like `` keeps `value` and `.value` in sync.
**Methods** are functions exposed on the element instance, the same as calling `el.focus()` or `el.click()` on a native element.
```js
el.open();
el.reset();
```
The API reference documents which attributes, properties, and methods exist, their types, and their defaults.
---
### Slots
Slots are how you pass content into a web component.
They are the equivalent of children in React or Vue's default slot, and they work the same way as the native `` element in HTML templates.
**Default slot**
Any content placed inside the component tags that is not assigned to a named slot goes into the default slot.
```html
This goes into the default slot.
```
**Named slots**
Named slots let the component define specific insertion points.
You assign content to a named slot using the `slot` attribute.
```html
Card Title
This still goes into the default slot.
```
The component controls where each slot is rendered inside its shadow DOM.
You do not control the layout, only the content.
The API reference lists what slots a component exposes.
---
### Events
Web component events work exactly like native DOM events.
You listen with `addEventListener` on the element reference or using inline event attributes.
```js
const el = document.querySelector("my-input");
el.addEventListener("statechange", event => {
console.log(event.detail); // e.g. "opened" or "closed"
});
```
Some events carry a `detail` payload on the event object, the same as `CustomEvent`.
The API reference documents what events a component fires and what `detail` contains, if anything.
Events follow normal DOM bubbling rules unless the component explicitly stops propagation.
You can also listen at a parent level if the event bubbles.
---
### Form Components
Some components in this library are form components.
They accept `name` and `disabled` attributes, expose a `value` property, and associate with the nearest `
```
They use the browser's `ElementInternals` API with `formAssociated = true`,
which means their value is included in `FormData` and submitted with the form without any extra work on your end.
```js
form.addEventListener("submit", event => {
event.preventDefault();
const data = new FormData(form);
console.log(data.get("notifications")); // submitted automatically
});
```
---
### Theming
Because the shadow DOM blocks external CSS selectors, theming a web component requires one of the three mechanisms below.
Most components support all three.
#### CSS Custom Properties
CSS custom properties (variables) cross the shadow DOM boundary.
A component reads variables you define on the outside, which is the primary theming mechanism.
Component libraries typically prefix their variables to avoid conflicts with your own codebase.
For example, a library might use `--sv-color-primary` rather than `--color-primary`. Check the naming convention in the API reference.
Setting a variable globally affects every instance of the component:
```css
:root {
--color-primary: #3b82f6;
--border-radius: 4px;
}
```
Setting it on a specific element scopes it to that instance only:
```css
.sidebar my-button {
--color-primary: #10b981;
}
```
The component's API reference lists every CSS custom property it exposes under "CSS Properties".
#### CSS Parts
`::part()` lets you target specific elements inside the shadow DOM directly with CSS,
bypassing the encapsulation. The component author marks internal elements with a `part` attribute to expose them.
```css
my-card::part(thumbnail) {
border-radius: 8px;
object-fit: cover;
}
my-card::part(title) {
font-size: 1.25rem;
font-weight: 600;
}
```
To know what parts a component exposes, check the "CSS Parts" section of its API reference.
You can also inspect the shadow DOM in DevTools and look for `part="..."` attributes on internal elements.
#### CSS Custom States
Custom states are a way for a component to expose its internal state for CSS targeting. They work like pseudo-classes.
```css
/* Style the component when it is in an open state */
my-accordion:state(--opened) {
border-color: var(--color-primary);
}
/* Transition a part when the component enters or leaves a state */
my-accordion::part(content) {
opacity: 0;
transition: opacity 200ms ease;
}
my-accordion:state(--opened)::part(content) {
opacity: 1;
}
```
Custom states are useful for conditional theming and for triggering animations when a component transitions between states,
without needing JavaScript listeners. The API reference lists exposed states under "CSS States".
---
### Reading the API Reference
Every component in this library has an API reference that documents:
- **Methods** -- functions you can call on the element instance
- **Properties** -- JavaScript properties and their types
- **Attributes** -- HTML attributes, their accepted values, and defaults
- **Events** -- events the component fires and their `detail` payload
- **Slots** -- named and default slots available for content projection
- **CSS Properties** -- custom properties you can set to theme the component
- **CSS Parts** -- internal elements exposed for direct CSS targeting
- **CSS States** -- internal states exposed for conditional styling
When you are unsure what a component accepts or exposes, the API reference is the authoritative source.
The sections in this guide map directly to those categories.
---
### Staticview Conventions
Every component in this library follows the same naming rules.
Learn them once and you can guess most of any component's API before opening its reference.
#### Component Tokens
Each component reads its own CSS custom properties, named `--sv--`:
```css
sv-slider {
--sv-slider-thumb-sz: 1.6em;
--sv-slider-fill-clr: hotpink;
}
```
Set them on the element to style one instance, or on an ancestor to style every instance inside it.
The name reads state, then part, then property, like `active-bg`, `thumb-sz`, or `focus-bdr-clr`.
Common words are always shortened:
| Short | Word |
| ------ | ---------- |
| `bg` | background |
| `clr` | color |
| `bdr` | border |
| `rad` | radius |
| `sz` | size |
| `pad` | padding |
| `dur` | duration |
| `ease` | easing |
| `anim` | animation |
| `btn` | button |
| `ln` | line |
| `num` | number |
| `dir` | direction |
#### Change Events
`change` fires after a property changes, whatever changed it: the user, your code, or a form reset.
`valuechange`, `openedchange`, and `checkedchange` all follow this pattern.
#### Interaction Events
Events named in the past tense, like `triggerclicked`, `optionclicked`, `adjusted`, or `dismissed`, fire only on user interaction.
They fire before anything changes, and they are cancelable.
When they carry a `detail`, it holds the value or state that is about to be applied.
```js
flyout.addEventListener("triggerclicked", event => {
if (event.detail.opened && !isSignedIn) {
event.preventDefault(); // Stays closed
}
});
```
#### Methods and States
Methods are verbs, like `open()`, `close()`, `check()`, and `toggle()`.
The state they change is a property and an attribute with the same name, like `opened`, `checked`, or `pressed`.
Its change event adds `change` to that name, like `openedchange` or `checkedchange`.
In CSS, the state reads `:state(--opened)`, `:state(--checked)`, or `:state(--pressed)`.
Methods that animate take `true` to skip the animation.
`transitionfinish` fires when the animation ends, or right away when there is none.
```js
dialog.open(); // Animates
dialog.open(true); // Skips the animation
dialog.addEventListener("transitionfinish", () => {
console.log(dialog.opened ? "Fully open" : "Fully closed");
});
```
#### Native Form Events
Form components fire native `input` and `change` events, the same way the matching native control does.
Existing form code and framework bindings that listen for them work without changes.
Like native controls, they fire only on user interaction.
Listen to `valuechange` to also catch changes made from code.
Source: https://staticview.a-labs.space/llms/docs/pages/contents/handbook.md
---
## Installation
Install the core package containing all components and types.
```bash
npm install @staticview/ui@beta
```
AI agents can read the docs as Markdown through [`llms.txt`](https://staticview.a-labs.space/llms.txt) or [`llms-full.txt`](https://staticview.a-labs.space/llms-full.txt).
### Optional Tools
#### CLI
Install the `staticview` CLI to add, create, build, and generate documentation for components into your project.
```bash
npm install @staticview/cli@beta
```
See [CLI](https://staticview.a-labs.space/contents/cli/) for available commands.
#### Vite Plugin
If you are authoring components directly in your project,
install the Vite plugin to compile and watch `.ts` web component files.
```bash
npm install @staticview/vite-plugin@beta
```
See [Vite Plugin](https://staticview.a-labs.space/contents/vite-plugin/) for configuration.
#### Staticbolt Plugin
If you are authoring components directly in your project,
install the Staticbolt plugin to compile and watch `.ts` web component files.
```bash
npm install @staticview/staticbolt-plugin@beta
```
See [Staticbolt Plugin](https://staticview.a-labs.space/contents/staticbolt-plugin/) for configuration.
#### ESLint Plugin
Lint rules for authoring and consuming staticview components.
```bash
npm install @staticview/eslint-plugin@beta
```
See [ESLint Plugin](https://staticview.a-labs.space/contents/eslint-plugin/) for available rules.
### Next Steps
1. [Setup](https://staticview.a-labs.space/contents/setup/vanilla-html) to configure TypeScript types for your framework.
2. After setup, see [Theming](https://staticview.a-labs.space/contents/setup/theming/) to style your components.
3. Setup [Editor Support](https://staticview.a-labs.space/contents/setup/editor-support/) to get rich editor support for your components.
Source: https://staticview.a-labs.space/llms/docs/pages/contents/installation.md
---
## Angular
### TypeScript Configuration
Add the Web Component types to your TypeScript configuration:
```jsonc
// tsconfig.app.json
{
"compilerOptions": {
"types": [
// Recommended: Adds native DOM types (e.g. `querySelector`, `document`)
// Or a single component: "@staticview/ui/types/dom/[component-name]"
"@staticview/ui/types/dom",
// Recommended: Exposes component types globally (no imports needed)
// Or a single component: "@staticview/ui/types/global/[component-name]"
"@staticview/ui/types/global",
],
},
}
```
This provides TypeScript support for the web components in your Angular application.
> [!NOTE]
> Angular templates themselves cannot be type-checked for custom elements.
> Angular has no equivalent of JSX type augmentation, and `CUSTOM_ELEMENTS_SCHEMA` (below) tells the compiler
> to accept unknown elements without checking their bindings.
> Typed access is available in component class code through element references.
### Enabling Custom Elements
Add `CUSTOM_ELEMENTS_SCHEMA` to every component (or `NgModule`) whose template uses web components:
```ts
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
@Component({
selector: "app-root",
templateUrl: "./app.html",
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class App {}
```
### Importing Web Components
Web components are registered globally in the browser.
Import them **once** in your application's entry point, before bootstrapping:
```ts
// main.ts
import { bootstrapApplication } from "@angular/platform-browser";
import "@staticview/ui/[component-name]";
import { App } from "./app/app";
bootstrapApplication(App);
```
> [!IMPORTANT]
> Do not import web components in multiple files.
> Import them only once at application startup, before `bootstrapApplication`,
> so the custom elements are defined before Angular renders and assigns properties to them.
### Setting Properties
Use Angular's property binding syntax `[propertyName]` to set JavaScript properties:
```html
```
### Setting Attributes
Use plain attributes for static values, or `[attr.attribute-name]` binding for dynamic ones:
```html
```
### Boolean Attributes
A boolean attribute is on whenever it is present, whatever its value: `close-button="false"` turns the close button **on**.
Angular only removes an attribute bound to `null` or `undefined`, so `[attr.close-button]="showCloseButton"` renders `close-button="false"`.
Bind the JavaScript property instead:
```html
```
Otherwise pass `""` to turn it on and `null` to turn it off:
```html
```
### Handling Events
Use Angular's event binding syntax `(eventName)` to listen for custom events:
```html
```
Since the template is not type-checked, `$event` is untyped — type the handler parameter as `CustomEvent` yourself:
```ts
handleExpand(event: CustomEvent) { ... }
```
### Typed Element References
With `@staticview/ui/types/global` in your TypeScript configuration, every component's instance type
is available globally and pairs with `ElementRef` for fully typed access to properties and methods:
```html
```
```ts
import { Component, CUSTOM_ELEMENTS_SCHEMA, viewChild, type ElementRef } from "@angular/core";
@Component({
/* ... */
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class Example {
panel = viewChild>("panel");
open() {
this.panel()?.nativeElement.opened; // fully typed
}
}
```
Alternatively, import the component's type directly from its module instead of using the global types:
```ts
import type { ComponentName } from "@staticview/ui/[component-name]";
```
It is the same type as the global one and the one DOM queries return.
With `@staticview/ui/types/dom`, DOM queries are typed as well:
```ts
const element = document.querySelector("component-name"); // ComponentName | null
```
### Using Slots
Use `children` to render the content of the web component:
```html
TitleContent
```
Source: https://staticview.a-labs.space/llms/docs/pages/contents/setup/angular.md
---
## Astro
### TypeScript Configuration
Add the Web Component types to your TypeScript configuration:
```jsonc
// tsconfig.json
{
"compilerOptions": {
"types": [
// Required: Enables JSX type support for Astro
// Or a single component: "@staticview/ui/types/astro/[component-name]"
"@staticview/ui/types/astro",
// Optional: Adds native DOM types (e.g. `querySelector`, `document`)
// Or a single component: "@staticview/ui/types/dom/[component-name]"
"@staticview/ui/types/dom",
// Optional: Exposes component types globally (no imports needed)
// Or a single component: "@staticview/ui/types/global/[component-name]"
"@staticview/ui/types/global",
],
},
}
```
This provides TypeScript support for the web components in your Astro application.
### Importing Web Components
Web components are registered globally in the browser. Import once per page.
```astro
```
### Using Components With Astro
Astro treats web components as plain HTML elements.
Source: https://staticview.a-labs.space/llms/docs/pages/contents/setup/astro.md
---
## Editor Support
The package ships editor metadata for all components: autocomplete for tags and attributes,
hover documentation, and richer tooling integration. No generation step is required; the files
are included in the npm package.
- [`custom.html-data.json`](https://github.com/microsoft/vscode-custom-data): used by the HTML language server, covers plain HTML files.
- [`custom-elements.json`](https://custom-elements-manifest.open-wc.org/): used by the Web Components Language Server, covers framework files too.
- [`web-types.json`](https://github.com/JetBrains/web-types): used by JetBrains IDEs, detected automatically.
> [!NOTE]
> These are alternative routes to the same features. Set up the **one** that fits your editor and workflow.
Quick reference:
- **VS Code**: `html.customData` setting, or the Web Components Language Server extension.
- **Neovim**: HTML language server `customData`, or the wc-toolkit plugin.
- **Zed**: Web Components Language Server extension.
- **JetBrains IDEs**: automatic, `web-types.json` is picked up with no configuration.
### VS Code
#### `custom.html-data.json`
Register it in your workspace settings:
```jsonc
// .vscode/settings.json
{
"html.customData": ["./node_modules/@staticview/ui/custom.html-data.json"],
}
```
This covers `.html` files only. For framework files (JSX/TSX, Vue, Svelte), use the language server below instead.
#### `custom-elements.json`
Install the [Web Components Language Server](https://wc-toolkit.com/integrations/vscode/) extension from the VS Code Marketplace.
It automatically detects `custom-elements.json` in your dependencies with no extra configuration needed.
Also works in VSCodium, Cursor, Windsurf, and Theia.
### Neovim
#### `custom.html-data.json`
Pass it to the HTML language server via your LSP config:
```lua
require('lspconfig').html.setup {
settings = {
html = {
customData = { vim.fn.getcwd() .. '/node_modules/@staticview/ui/custom.html-data.json' }
}
}
}
```
#### `custom-elements.json`
Install the [wc-toolkit Neovim plugin](https://wc-toolkit.com/integrations/neovim/). The language server executable can be installed via Mason:
```
:MasonInstall wc-language-server
```
Then set up the plugin:
```lua
require("wc_language_server").setup()
```
It auto-detects `custom-elements.json` from your project dependencies and attaches to HTML, Astro, Vue, Svelte, JSX/TSX, and Markdown files.
### Zed
#### `custom-elements.json` (recommended)
Install the [Web Components Language Server](https://wc-toolkit.com/integrations/zed/) extension from Zed's extension marketplace.
It auto-detects `custom-elements.json` from your dependencies.
#### `custom.html-data.json`
> [!CAUTION]
> The Zed HTML extension does not support `customData` in `settings.json` yet, so this method
> currently has no effect in Zed; use the extension above instead. Once support lands, the
> registration will look like this:
```jsonc
// .zed/settings.json
{
"lsp": {
"vscode-html-language-server": {
"settings": {
"html": {
"customData": ["./node_modules/@staticview/ui/custom.html-data.json"],
},
},
},
},
}
```
### JetBrains IDEs
#### `web-types.json`
JetBrains IDEs (WebStorm, IntelliJ IDEA, Rider, etc.) pick up the package's `web-types.json`
automatically, with no configuration required.
#### `custom-elements.json`
Install the [Web Components Language Server](https://wc-toolkit.com/integrations/jetbrains/) JetBrains plugin.
It reads `custom-elements.json` directly from your dependencies.
> [!NOTE]
> JetBrains IDEs do not support `custom.html-data.json`.
### AI Assistants
The documentation site serves two files following the [llms.txt](https://llmstxt.org/) convention:
- [`llms.txt`](https://staticview.a-labs.space/llms.txt): an index linking every guide, package README, component reference, and example as Markdown.
- [`llms-full.txt`](https://staticview.a-labs.space/llms-full.txt): the guides, READMEs, and component references inlined into a single file. Examples are left out; follow the index for those.
Use the index with tools that can fetch links on demand, and the full file with tools that index a single URL or when pasting everything into one prompt.
#### Cursor
Settings → Features → Docs → Add new doc, then paste the `llms.txt` URL.
Once indexed, reference it in chat with `@Staticview`.
#### Claude Code, Codex, and similar
These read the repository's instructions file, so a line pointing at `llms-full.txt`
is enough, together with an instruction to fetch it before answering questions about `sv-*` components.
Source: https://staticview.a-labs.space/llms/docs/pages/contents/setup/editor-support.md
---
## Preact
### TypeScript Configuration
Add the Web Component types to your TypeScript configuration:
```jsonc
// tsconfig.json
{
"compilerOptions": {
"types": [
// Required: Enables JSX type support for Preact
// Or a single component: "@staticview/ui/types/preact/[component-name]"
"@staticview/ui/types/preact",
// Optional: Adds native DOM types (e.g. `querySelector`, `document`)
// Or a single component: "@staticview/ui/types/dom/[component-name]"
"@staticview/ui/types/dom",
// Optional: Exposes component types globally (no imports needed)
// Or a single component: "@staticview/ui/types/global/[component-name]"
"@staticview/ui/types/global",
],
},
}
```
This provides TypeScript support for the web components in your Preact application.
### Importing Web Components
Web components are registered globally in the browser.
Import them **once** in your application's entry point:
```ts
// app.tsx
import "@staticview/ui/[component-name]";
```
**Important:** Do not import web components in multiple files.
Import them only once at application startup.
### Setting Properties and Attributes
If the web component has a JavaScript property,
Preact will automatically set it, otherwise, it sets it as an HTML attribute.
```tsx
```
### Boolean Attributes
A boolean attribute is on whenever it is present, whatever its value: `close-button="false"` turns the close button **on**.
Preact removes an attribute whose value is `false`, so pass a boolean and let Preact add or remove it:
```tsx
```
Prefer the matching JavaScript property when the component has one.
Preact assigns it directly on the element, so the value reaches the component as a boolean instead of as markup.
The component decides whether to reflect it back to the attribute:
```tsx
```
### Handling Events
Use `on[eventName]` syntax to listen for custom events:
```tsx
```
### Controlled and Uncontrolled Components
On every render, Preact sets `value` and `checked` again on any element whose current value differs from the prop, web components included.
A component that gets `value` without the state following the user's change resets on the next render, even an unrelated one.
For an uncontrolled component, set the starting value with `defaultValue` or `defaultChecked` instead.
A form reset returns to it:
```tsx
```
For a controlled component, pass the state and cancel the event that the component fires before a user change applies.
Then update the state yourself:
```tsx
{
event.preventDefault();
setValue(event.detail.value);
}}
>
```
### Using Slots
Use `children` to render the content of the web component:
```tsx
TitleContent
```
Source: https://staticview.a-labs.space/llms/docs/pages/contents/setup/preact.md
---
## Qwik
### TypeScript Configuration
Add the Web Component types to your TypeScript configuration:
```jsonc
// tsconfig.json
{
"compilerOptions": {
"types": [
// Required: Enables JSX type support for Qwik
// Or a single component: "@staticview/ui/types/qwik/[component-name]"
"@staticview/ui/types/qwik",
// Optional: Adds native DOM types (e.g. `querySelector`, `document`)
// Or a single component: "@staticview/ui/types/dom/[component-name]"
"@staticview/ui/types/dom",
// Optional: Exposes component types globally (no imports needed)
// Or a single component: "@staticview/ui/types/global/[component-name]"
"@staticview/ui/types/global",
],
},
}
```
This provides TypeScript support for the web components in your Qwik application.
### Importing Web Components
Web components are registered globally in the browser.
Import them **once** in your application's entry point:
```ts
// app.tsx
import "@staticview/ui/[component-name]";
```
**Important:** Do not import web components in multiple files.
Import them only once at application startup.
### Setting Properties and Attributes
If the web component has a JavaScript property, Qwik will automatically set it, otherwise, it sets it as an HTML attribute.
```tsx
```
### Boolean Attributes
A boolean attribute is on whenever it is present, whatever its value: `close-button="false"` turns the close button **on**.
Qwik removes an attribute whose value is `false` and sets it to `""` when it is `true`, so pass a boolean:
```tsx
```
Prefer the matching JavaScript property when the component has one.
Qwik assigns it directly on the element, so the value reaches the component as a boolean instead of as markup.
The component decides whether to reflect it back to the attribute:
```tsx
```
### Handling Events
Use `on[EventName]$` syntax to listen for custom events:
```tsx
```
### Using Slots
Use `children` to render the content of the web component:
```html
TitleContent
```
Source: https://staticview.a-labs.space/llms/docs/pages/contents/setup/qwik.md
---
## React 18 and earlier
### TypeScript Configuration
Add the Web Component types to your TypeScript configuration:
```jsonc
// tsconfig.json
{
"compilerOptions": {
"types": [
// Required: Enables JSX type support for React 18 and earlier
// Or a single component: "@staticview/ui/types/react18/[component-name]"
"@staticview/ui/types/react18",
// Optional: Adds native DOM types (e.g. `querySelector`, `document`)
// Or a single component: "@staticview/ui/types/dom/[component-name]"
"@staticview/ui/types/dom",
// Optional: Exposes component types globally (no imports needed)
// Or a single component: "@staticview/ui/types/global/[component-name]"
"@staticview/ui/types/global",
],
},
}
```
This provides TypeScript support for the web components in your React application.
### Importing Web Components
Web components are registered globally in the browser.
Import them **once** in your application's entry point:
```ts
// app.tsx
import "@staticview/ui/[component-name]";
```
**Important:** Do not import web components in multiple files.
them only once at application startup.
### Using Components with React 18 and earlier
React 18 and earlier does not support setting JavaScript properties or attaching events using JSX, its only support setting HTML attributes.
To attach events or settings JavaScript properties use the native DOM API via react ref.
### Boolean Attributes
A boolean attribute is on whenever it is present, whatever its value: `close-button="false"` turns the close button **on**.
React 18 keeps boolean values on custom elements and stringifies them, so `close-button={false}` also renders `close-button="false"`.
Pass `""` to turn it on, and omit the attribute — or pass `undefined` — to turn it off:
```tsx
```
### Using Slots
Use `children` to render the content of the web component:
```tsx
TitleContent
```
Source: https://staticview.a-labs.space/llms/docs/pages/contents/setup/react18.md
---
## React 19+
### TypeScript Configuration
Add the Web Component types to your TypeScript configuration:
```jsonc
// tsconfig.json
{
"compilerOptions": {
"types": [
// Required: Enables JSX type support for React 19 and later
// Or a single component: "@staticview/ui/types/react/[component-name]"
"@staticview/ui/types/react",
// Optional: Adds native DOM types (e.g. `querySelector`, `document`)
// Or a single component: "@staticview/ui/types/dom/[component-name]"
"@staticview/ui/types/dom",
// Optional: Exposes component types globally (no imports needed)
// Or a single component: "@staticview/ui/types/global/[component-name]"
"@staticview/ui/types/global",
],
},
}
```
This provides TypeScript support for the web components in your React application.
### Importing Web Components
Web components are registered globally in the browser.
Import them **once** in your application's entry point:
```ts
// app.tsx
import "@staticview/ui/[component-name]";
```
**Important:** Do not import web components in multiple files.
Import them only once at application startup.
### Setting Properties and Attributes
If the web component has a JavaScript property, React will automatically set it, otherwise, it sets it as an HTML attribute.
```tsx
```
### Boolean Attributes
A boolean attribute is on whenever it is present, whatever its value: `close-button="false"` turns the close button **on**.
React removes an attribute whose value is `false`, so pass a boolean and let React add or remove it.
```tsx
```
Prefer the matching JavaScript property when the component has one.
React assigns it directly on the element, so the value reaches the component as a boolean instead of as markup.
The component decides whether to reflect it back to the attribute:
```tsx
```
### Handling Events
Use `on[eventName]` syntax to listen for custom events:
```tsx
```
### Controlled and Uncontrolled Components
React keeps only its own ``, `