# 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 Cover

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 `
` element the same way native inputs do. ```html
``` 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 Title Content ``` 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 Title Content ``` 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 Title Content ``` 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 Title Content ``` 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 ``, `
``` ### API References --- #### Properties ##### `tabsize` The empty space counted as one tab. **Type:** `number`\ **Default:** `2` ##### `value` The code string. **Type:** `string` ##### `highlighter` Takes the whole code and returns it as highlighted HTML. Defaults to escaping the code as plain text. The returned string is assigned to `innerHTML`. Only return trusted HTML, and sanitize any output derived from untrusted input before returning it. **Type:** `(code: string) => string | Promise` ##### `readonly` Disable user input. **Type:** `boolean`\ **Default:** `false` ##### `linenumbers` Show line numbers. **Type:** `boolean`\ **Default:** `false` ##### `expand` Grow the text area to fit the content, wrapped lines included. **Type:** `boolean`\ **Default:** `false` ##### `wrap` Wrap the text area to fit the content. **Type:** `boolean`\ **Default:** `false` ##### `copyButton` Show copy button. **Type:** `boolean`\ **Default:** `false` ##### `wrapButton` Show wrap button. **Type:** `boolean`\ **Default:** `false` ##### `codeStylesheet` The CSS style sheet selector for code styling, it can be a `link[rel="stylesheet"]` or a `style` element. **Type:** `string | undefined`\ **Default:** `undefined` ##### `oneLine` Mimic regular input element by forcing one line. **Type:** `boolean`\ **Default:** `false` --- #### Attributes ##### `"value"` The code string. **Type:** `string` ##### `"readonly"` Disable user input. **Type:** `boolean` ##### `"tabsize"` The empty space counted as one tab. **Type:** `number`\ **Default:** `2` ##### `"code-stylesheet"` The CSS style sheet selector for code styling, it can be a `link[rel="stylesheet"]` or a `style` element. **Type:** `string` ##### `"expand"` Grow the text area to fit the content, wrapped lines included. **Type:** `boolean` ##### `"wrap"` Wrap the text area to fit the content. **Type:** `boolean` ##### `"linenumbers"` Show line numbers. **Type:** `boolean` ##### `"copy-button"` Show copy button. **Type:** `boolean` ##### `"wrap-button"` Show wrap button. **Type:** `boolean` ##### `"one-line"` Mimic regular input element by forcing one line. **Type:** `boolean` --- #### Events ##### `copyclicked` Fired when the user clicks the copy button, before the code is copied. Cancel it to skip the copy. **Cancelable:** `true` ##### `valuechange` Fired after `value` changes, whether by the user or from code. --- #### Slots | Name | Description | | --------- | ------------------------------------------------------------------------------------------ | | `Default` | The text content of the this slot children will be extracted and used as the initial code. | | `header` | Element to render in the header. | | `footer` | Element to render in the footer. | --- #### CSS Properties | Name | Description | Default | | ------------------------------------ | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | | `--sv-code-editor-bg` | The background color of the code editor. | `--sv-gray-6` | | `--sv-code-editor-accent` | The accent color, used for the selection, the active line and the scrollbar. | `--sv-accent` | | `--sv-code-editor-active-ln-bg` | The background of the line the caret is on. Set it and the outline to `transparent` to drop the highlight. | `hsl(from var(--sv-code-editor-accent) h s l / 20%)` | | `--sv-code-editor-active-ln-bdr-clr` | The line drawn above and below the line the caret is on. | `hsl(from var(--sv-code-editor-accent) h s l / 30%)` | | `--sv-code-editor-bdr-clr` | The color of the border. | `--sv-gray-5` | | `--sv-code-editor-bdr-rad` | The border radius of the code editor. | `--sv-bdr-rad-md` | | `--sv-code-editor-bdr-sz` | The border width of the code editor. | `--sv-bdr-sz-sm` | | `--sv-code-editor-ln-num-bg` | The background color of the line numbers column. | `--sv-gray-5` | | `--sv-code-editor-ln-num-width` | The width of the line numbers column. | `calc(var(--sv-code-editor-font-sz) * 3)` | | `--sv-code-editor-font-family` | The font family of the code. | `monospace` | | `--sv-code-editor-font-sz` | The font size of the code. | `1rem` | | `--sv-code-editor-font-weight` | The font weight of the code. | `normal` | | `--sv-code-editor-ln-height` | The line height of the code. | `1.5` | | `--sv-code-editor-pad` | The padding of the code editor. | `0.5rem` | --- #### CSS Parts | Name | Description | | --------------------- | ----------------------------------------------------------------------------- | | `::part(wrapper)` | The element that wrap [Header \| Editor \| Footer]. | | `::part(container)` | The element that container [LineNumbers \| Textarea/Highlight \| CopyButton]. | | `::part(box)` | The code editor box element (textarea and highlight elements). | | `::part(textarea)` | The code editor textarea element. | | `::part(highlight)` | The code editor highlight container element. | | `::part(wrap-button)` | The wrap button. | | `::part(copy-button)` | The copy button. | --- #### CSS States | Name | Description | | ------------------- | --------------------------- | | `:state(--focused)` | The code editor is focused. | Source: https://staticview.a-labs.space/llms/packages/ui/docs/components/sv-code-editor.md --- ## Collapsible `sv-collapsible` expands and collapses content, and optionally manages the disclosure trigger for it. ### Usage ```html 'slot="trigger"'

Additional details.

``` Closed content is hidden, which takes it out of the tab order and the accessibility tree. Leave both the slot and `trigger-element` unset when something else drives the collapsible. Toggling then goes through `opened`, and the disclosure semantics are yours to provide: ```html 'aria-controls="details"' 'aria-expanded="false"'
Additional details.
``` ### Animation The content expands and collapses with a CSS transition, so a toggle partway through reverses from the current height. Both durations are `0s` under `prefers-reduced-motion: reduce`. ### Performance The collapsible expands in normal flow, so animating one near the top of a long page recalculates the page layout on every frame. Keep animated collapsibles in their own scroll container, or inside a constrained layout like a panel, sidebar, or modal. Where that isn't possible, turn the animation off: ```css sv-collapsible { --sv-collapsible-open-dur: 0s; --sv-collapsible-close-dur: 0s; } ``` ### Structure ```html tree
``` ### API References --- #### Methods ##### `open()` Opens the content, skipping the animation when `isInstant` is `true`. **Type:** `(isInstant?: boolean) => void` ##### `close()` Closes the content, skipping the animation when `isInstant` is `true`. **Type:** `(isInstant?: boolean) => void` ##### `toggle()` Toggles the content between open and closed, skipping the animation when `isInstant` is `true`. **Type:** `(isInstant?: boolean) => void` --- #### Properties ##### `triggerElement` The element that toggles the content. Assigning `null`, or removing the attribute, restores the first element assigned to the `trigger` slot. The resolved trigger receives the disclosure ARIA relationships and toggles the content when clicked. **Type:** `Element | null`\ **Default:** `null` ##### `opened` The requested open state. Assigning this property uses the normal animated transition. Use `open(true)` or `close(true)` for an instant transition. **Type:** `boolean`\ **Default:** `false` --- #### Attributes ##### `"trigger-element"` A CSS selector for the trigger element, resolved against the component's document. A selector that matches nothing leaves the slotted trigger in place. **Type:** `string` ##### `"opened"` Set the open state. **Type:** `boolean` --- #### Events ##### `triggerclicked` Fired when the user clicks the trigger, before the content toggles. Cancel it to keep the current state. **Type:** `CustomEvent<{ opened: boolean; }>`\ **Detail:** `opened` is the new state that would be applied if not canceled.\ **Cancelable:** `true` ##### `openedchange` Fired after `opened` changes, whether by the user or from code. ##### `transitionfinish` Fired when the open or close animation ends. Fires right away when there is no animation. Read `opened` to know the direction. --- #### Slots | Name | Description | | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `trigger` | An optional interactive element that toggles the content and receives the disclosure ARIA relationships. Ignored while `triggerElement` names another element. | | `Default` | The content to expand and collapse. | --- #### CSS Properties | Name | Description | Default | | ----------------------------- | ------------------------------------------ | ------------------------------- | | `--sv-collapsible-open-dur` | Duration of the opening animation. | `350ms` | | `--sv-collapsible-close-dur` | Duration of the closing animation. | `350ms` | | `--sv-collapsible-open-ease` | Easing function for the opening animation. | `cubic-bezier(0.25, 1, 0.5, 1)` | | `--sv-collapsible-close-ease` | Easing function for the closing animation. | `cubic-bezier(0.25, 1, 0.5, 1)` | --- #### CSS Parts | Name | Description | | ------------------ | -------------------------------------- | | `::part(expander)` | The animation and expansion container. | | `::part(content)` | The content container. | --- #### CSS States | Name | Description | | ------------------ | --------------------------------- | | `:state(--opened)` | When the requested state is open. | Source: https://staticview.a-labs.space/llms/packages/ui/docs/components/sv-collapsible.md --- ## Combobox **Form-associated** **Depends on** `` and `` `sv-combobox` combines an editable text field with a listbox. Use `sv-select` when users should choose without typing: a combobox keeps focus in its text field, while a select moves focus through its options. ### Usage ```html 'data-combobox-no-results'

No matching color

``` A button becomes an option only when it carries a `value` attribute, and every value has to be unique. An option's label is its text. A disabled option stays visible and keeps taking part in filtering. Options are found at any depth inside the flyout, but only its direct children are watched for changes. Call `refresh()` after adding or removing an option nested deeper than that. Name the control with `
``` Any focusable element in the flyout content is a menu item, whatever its role. Put the menu item role on the element that takes focus, and add `data-menu-ignore` to a focusable element that should not be an item. Disabled buttons stay in the list but keyboard navigation skips over them. A popup holding arbitrary controls, such as text fields or sliders, wants `sv-flyout` on its own without `sv-menu`. Items added to or removed from the flyout's default slot are picked up automatically. Changes deeper inside an already-slotted container are not, so call `refresh()` after mutating one. ### Submenus Opening one submenu closes its open siblings: ```html 'mode="submenu"' ``` ### Context menus `mode="context"` opens the menu where the pointer was when a `contextmenu` event fired inside its trigger. Clicking the trigger no longer opens anything: ```html 'mode="context"' ``` Setting `openAtPosition` widens this to a `contextmenu` event anywhere in the document, opening the menu at that fixed coordinate. An event inside the trigger still wins and uses its pointer coordinates. For coordinates of your own, set the nested flyout's anchor and open the menu yourself: ```js const menu = document.querySelector("sv-menu"); const flyout = menu.querySelector("sv-flyout"); flyout.anchorComponent.anchorRect = { left: event.clientX, top: event.clientY }; menu.open(); ``` ### Keyboard navigation #### Trigger focused, menu closed | Key | Behavior | | ----------------------------- | ---------------------------------------- | | `Enter`, `Space`, `ArrowDown` | Opens and focuses the first enabled item | | `ArrowUp` | Opens and focuses the last enabled item | #### Menu open | Key | Behavior | | ------------------- | ----------------------------------------------------------------------------------------- | | `ArrowDown` | Focuses the next enabled item, wrapping after the last | | `ArrowUp` | Focuses the previous enabled item, wrapping before the first | | `PageDown` | Moves five enabled items forward and wraps | | `PageUp` | Moves five enabled items backward and wraps | | `Home` | Focuses the first enabled item | | `End` | Focuses the last enabled item | | `Escape` | Closes the innermost open menu and returns focus to its trigger | | `Tab` | Closes the menu and lets focus move on | | Printable character | Focuses the next item whose text starts with the accumulated prefix, cycling through ties | Printable keys typed within 500 ms of each other build the typeahead prefix. #### Submenu additions | State | Key | Behavior | | -------------- | -------------------------------------- | ----------------------------------------------- | | Closed submenu | `ArrowRight` (LTR) / `ArrowLeft` (RTL) | Opens and focuses the first enabled item | | Closed submenu | `Enter` or `Space` | Opens and focuses the first enabled item | | Open submenu | `ArrowLeft` (LTR) / `ArrowRight` (RTL) | Closes and returns focus to the submenu trigger | ### API References --- #### Methods ##### `refresh()` Rescans menu items and submenus after nested flyout content changes that do not produce a slot change. ##### `open()` Opens the menu, skipping the animation when `isInstant` is `true`. **Type:** `(isInstant?: boolean) => void` ##### `close()` Closes the menu and its known submenus, skipping animations when `isInstant` is `true`. **Type:** `(isInstant?: boolean) => void` ##### `toggle()` Toggles the menu between open and closed, skipping animations when `isInstant` is `true`. **Type:** `(isInstant?: boolean) => void` --- #### Properties ##### `openAtPosition` A fixed viewport coordinate at which a context-mode menu opens in response to a `contextmenu` event.\ When unset, a context menu opens only for events within its trigger and uses the pointer coordinates. **Type:** `{ left: number; top: number; }` ##### `mode` The menu's trigger and keyboard-interaction mode. - **`menu`**\ Opens from the trigger with command-menu keyboard navigation. - **`submenu`**\ Adds directional submenu keyboard navigation and gives the trigger the `menuitem` role. - **`context`**\ Opens from a `contextmenu` event instead of a trigger click. The nested flyout receives the `menu` role. Consumers remain responsible for assigning `menuitem`, `menuitemcheckbox`, or `menuitemradio` roles and their corresponding states to menu items. **Type:** `"menu" | "submenu" | "context"`\ **Reflects:** `"mode"` ##### `opened` The nested flyout's requested open state. Assigning this property uses the normal animated transition. Use `open(true)` or `close(true)` for an instant transition. **Type:** `boolean` --- #### Attributes ##### `"opened"` The nested flyout's requested open state. Assigning this property uses the normal animated transition. Use `open(true)` or `close(true)` for an instant transition. **Type:** `boolean` ##### `"mode"` The menu's trigger and keyboard-interaction mode. - **`menu`**\ Opens from the trigger with command-menu keyboard navigation. - **`submenu`**\ Adds directional submenu keyboard navigation and gives the trigger the `menuitem` role. - **`context`**\ Opens from a `contextmenu` event instead of a trigger click. The nested flyout receives the `menu` role. Consumers remain responsible for assigning `menuitem`, `menuitemcheckbox`, or `menuitemradio` roles and their corresponding states to menu items. **Values:** `"menu"`, `"submenu"`, `"context"` --- #### Slots | Name | Description | | --------- | ---------------------------------------------------------- | | `Default` | The default slot where the `sv-flyout` should be rendered. | Source: https://staticview.a-labs.space/llms/packages/ui/docs/components/sv-menu.md --- ## Progress Bar `sv-progress-bar` is a straight bar that visually represents progress. ### Usage The bar takes the full width of its container. Slotted content sits in a row before the track, with the first and last element pushed to opposite ends: ```html Uploading % ``` A child element with `data-value` displays the current `value`, and one with `data-percentage` displays the current `percentage`. The attribute's number sets the decimal places; without one, the number is rounded to at most two decimals. Those elements are left empty while the bar is indeterminate. Content in the `fill` slot is centered and is clipped when the filled portion is too short for it. Give the bar enough thickness to fit the text: ```html 'slot="fill"' % ``` ```css sv-progress-bar { --sv-progress-bar-thickness: 1.25rem; } ``` On a `vertical` bar, the slotted content stacks above the track. A vertical bar has no height of its own. Give it one: ```css sv-progress-bar[vertical] { block-size: 10rem; } ``` The bar is a flex column. Change its `flex-direction` to move the content around the track. `column-reverse` puts it below the track. On a vertical bar, `row` with `align-items: stretch` puts it beside the track: ```css sv-progress-bar[vertical] { flex-direction: row; align-items: stretch; } ``` While indeterminate, a short fill slides along the track. Under `prefers-reduced-motion` the short fill sits still in the middle of the track. The whole motion animates on `::part(fill)`. An `animation` set there replaces it. ### Accessibility The bar sets `role="progressbar"` and keeps the ARIA value attributes in sync with `value`, `min`, and `max`. Label it with `aria-label` or `aria-labelledby`. A child element with `data-value-text` sets `aria-valuetext` from its text content: ```html "data-value-text" 'data-percentage="0"'

%

``` Slotted content is hidden from assistive technology. Don't slot interactive elements. ### Structure ```html tree
``` ### API References --- #### Properties ##### `value` The current value, clamped to `min`/`max`. The assigned value is kept unclamped so range changes re-clamp from it. `null` (the default) puts the bar in the indeterminate state. Non-finite assignments are treated as `null`. **Type:** `number | null` ##### `min` The minimum value. Non-finite assignments reset it to `0` (the default), and changes re-clamp `value`. **Type:** `number`\ **Default:** `0` ##### `max` The maximum value. Non-finite assignments reset it to `100` (the default), and changes re-clamp `value`. **Type:** `number`\ **Default:** `100` ##### `percentage` The current value as a percentage `(0-100)` of the range, or `null` when indeterminate. Assigning maps the percentage onto the range and stores the result in `value`. `null` or a non-finite assignment makes the bar indeterminate. **Type:** `number | null` ##### `bufferValue` How far ahead of `value` the content is loaded, clamped to `min`/`max`. It shows as a second fill behind the first one. `null` (the default) shows no buffer. Non-finite assignments are treated as `null`. **Type:** `number | null` ##### `bufferPercentage` The buffer as a percentage `(0-100)` of the range, or `null` when there is no buffer. Assigning maps the percentage onto the range and stores the result in `bufferValue`. `null` or a non-finite assignment removes the buffer. **Type:** `number | null` --- #### Attributes ##### `"vertical"` Makes the bar vertical. It then fills from the bottom. **Type:** `boolean` ##### `"value"` The current value, clamped to `min`/`max`. The assigned value is kept unclamped so range changes re-clamp from it. `null` (the default) puts the bar in the indeterminate state. Non-finite assignments are treated as `null`. **Type:** `number` ##### `"min"` The minimum value. Non-finite assignments reset it to `0` (the default), and changes re-clamp `value`. **Type:** `number`\ **Default:** `0` ##### `"max"` The maximum value. Non-finite assignments reset it to `100` (the default), and changes re-clamp `value`. **Type:** `number`\ **Default:** `100` ##### `"percentage"` The current value as a percentage `(0-100)` of the range, or `null` when indeterminate. Assigning maps the percentage onto the range and stores the result in `value`. `null` or a non-finite assignment makes the bar indeterminate. **Type:** `number` ##### `"buffer-value"` How far ahead of `value` the content is loaded, clamped to `min`/`max`. It shows as a second fill behind the first one. `null` (the default) shows no buffer. Non-finite assignments are treated as `null`. **Type:** `number` ##### `"buffer-percentage"` The buffer as a percentage `(0-100)` of the range, or `null` when there is no buffer. Assigning maps the percentage onto the range and stores the result in `bufferValue`. `null` or a non-finite assignment removes the buffer. **Type:** `number` --- #### Events ##### `valuechange` Fired when the current value changes, including when a `min` or `max` change re-clamps it. **Type:** `CustomEvent<{ value: number | null; previousValue: number | null; }>` --- #### Slots | Name | Description | | --------- | ---------------------------------------------------------------------- | | `Default` | Content shown before the track, such as a label and the current value. | | `fill` | Content shown inside the filled portion of the track. | --- #### CSS Properties | Name | Description | Default | | ------------------------------------ | --------------------------------------------------- | ---------------------------------------------------------------------- | | `--sv-progress-bar-track-clr` | Color of the track. | `--sv-gray-5` | | `--sv-progress-bar-fill-clr` | Color of the filled portion of the track. | `--sv-accent` | | `--sv-progress-bar-buffer-clr` | Color of the buffered portion of the track. | `color-mix(in srgb, var(--sv-progress-bar-fill-clr) 35%, transparent)` | | `--sv-progress-bar-thickness` | Thickness of the track and its filled portion. | `6px` | | `--sv-progress-bar-track-thickness` | Thickness of the track. | `--sv-progress-bar-thickness` | | `--sv-progress-bar-fill-thickness` | Thickness of the filled portion of the track. | `--sv-progress-bar-thickness` | | `--sv-progress-bar-buffer-thickness` | Thickness of the buffered portion of the track. | `--sv-progress-bar-fill-thickness` | | `--sv-progress-bar-rad` | Corner radius of the track and its filled portion. | `1em` | | `--sv-progress-bar-track-rad` | Corner radius of the track. | `--sv-progress-bar-rad` | | `--sv-progress-bar-fill-rad` | Corner radius of the filled portion of the track. | `--sv-progress-bar-rad` | | `--sv-progress-bar-buffer-rad` | Corner radius of the buffered portion of the track. | `--sv-progress-bar-fill-rad` | | `--sv-progress-bar-gap` | Space between the slotted content and the track. | `0.5em` | | `--sv-progress-bar-dur` | Duration of the fill animation. | `350ms` | | `--sv-progress-bar-ease` | Easing function for the fill animation. | `cubic-bezier(0.25, 1, 0.5, 1)` | --- #### CSS Parts | Name | Description | | ----------------- | -------------------------------------------------------- | | `::part(content)` | The row that holds the slotted content before the track. | | `::part(track)` | The progress bar's track. | | `::part(buffer)` | The buffered portion of the track. | | `::part(fill)` | The filled portion of the track. | --- #### CSS States | Name | Description | | ------------------------- | ---------------------------------------------------------------- | | `:state(--indeterminate)` | The progress bar has no value and is in the indeterminate state. | Source: https://staticview.a-labs.space/llms/packages/ui/docs/components/sv-progress-bar.md --- ## Progress Ring `sv-progress-ring` is an SVG-based ring that visually represents progress. ### Usage The ring fills the element, so give it a size: ```css sv-progress-ring { inline-size: 6rem; block-size: 6rem; } ``` Slotted content is centered inside the ring. A child element with `data-value` displays the current `value`, and one with `data-percentage` displays the current `percentage`. The attribute's number sets the decimal places; without one, the number is rounded to at most two decimals: ```html 'data-percentage="0"' % ``` Those elements are left empty while the ring is indeterminate. Without a `value`, the ring is indeterminate and spins. Under `prefers-reduced-motion` a short arc sits still at the top of the ring. The whole motion animates on `::part(fill)`, so an `animation` there replaces it, and `::part(svg)` is free for adding rotation on top: ```css sv-progress-ring:state(--indeterminate)::part(fill) { stroke-dasharray: calc(3.1415 * 25%) calc(3.1415 * 75%); animation: my-orbit 1s linear infinite; } ``` The circle's path length is `calc(3.1415 * 100%)`, since a dash percentage resolves against the ring's SVG width. A dash pattern that totals one path length and an offset that advances by one path length per cycle loop seamlessly: ```css @keyframes my-orbit { to { stroke-dashoffset: calc(-3.1415 * 100%); } } ``` ### Accessibility The ring sets `role="progressbar"` and keeps the ARIA value attributes in sync with `value`, `min`, and `max`. Label it with `aria-label` or `aria-labelledby`. A child element with `data-value-text` sets `aria-valuetext` from its text content: ```html "data-value-text" 'data-percentage="0"'

%

``` Slotted content is hidden from assistive technology, so don't slot interactive elements. ### Structure ```html tree
``` ### API References --- #### Properties ##### `value` The current value, clamped to `min`/`max`. The assigned value is kept unclamped so range changes re-clamp from it. `null` (the default) puts the ring in the indeterminate state; non-finite assignments are treated as `null`. **Type:** `number | null` ##### `min` The minimum value. Non-finite assignments reset it to `0` (the default), and changes re-clamp `value`. **Type:** `number`\ **Default:** `0` ##### `max` The maximum value. Non-finite assignments reset it to `100` (the default), and changes re-clamp `value`. **Type:** `number`\ **Default:** `100` ##### `percentage` The current value as a percentage `(0-100)` of the range, or `null` when indeterminate. Assigning maps the percentage onto the range and stores the result in `value`. `null` or a non-finite assignment makes the ring indeterminate. **Type:** `number | null` --- #### Attributes ##### `"value"` The current value, clamped to `min`/`max`. The assigned value is kept unclamped so range changes re-clamp from it. `null` (the default) puts the ring in the indeterminate state; non-finite assignments are treated as `null`. **Type:** `number` ##### `"min"` The minimum value. Non-finite assignments reset it to `0` (the default), and changes re-clamp `value`. **Type:** `number`\ **Default:** `0` ##### `"max"` The maximum value. Non-finite assignments reset it to `100` (the default), and changes re-clamp `value`. **Type:** `number`\ **Default:** `100` ##### `"percentage"` The current value as a percentage `(0-100)` of the range, or `null` when indeterminate. Assigning maps the percentage onto the range and stores the result in `value`. `null` or a non-finite assignment makes the ring indeterminate. **Type:** `number` --- #### Events ##### `valuechange` Fired when the current value changes, including when a `min` or `max` change re-clamps it. **Type:** `CustomEvent<{ value: number | null; previousValue: number | null; }>` --- #### Slots | Name | Description | | --------- | ------------------------------------ | | `Default` | The circular progress bar's content. | --- #### CSS Properties | Name | Description | Default | | ------------------------------------ | ------------------------------------------------------------------------------------------ | ------------------------------- | | `--sv-progress-ring-track-clr` | Color of the track. | `--sv-gray-5` | | `--sv-progress-ring-fill-clr` | Color of the filled portion of the track. | `--sv-accent` | | `--sv-progress-ring-bg` | Background color of the circular container. | `transparent` | | `--sv-progress-ring-track-thickness` | Thickness of the track. | `4px` | | `--sv-progress-ring-fill-thickness` | Thickness of the filled portion of the track. | `4px` | | `--sv-progress-ring-fill-linecap` | Line cap style for the filled portion. Use `butt \| round \| square`. | `round` | | `--sv-progress-ring-dash-num` | Number of dashes the fill splits into. Use `1` for a solid fill. | `1` | | `--sv-progress-ring-dash-gap` | Length of the gap between dashes. Has no effect when `--sv-progress-ring-dash-num` is `1`. | `4px` | | `--sv-progress-ring-clockwise` | Fill direction. Use `1` for clockwise, `-1` for counter-clockwise. | `1` | | `--sv-progress-ring-dur` | Duration of the fill animation. | `350ms` | | `--sv-progress-ring-ease` | Easing function for the fill animation. | `cubic-bezier(0.25, 1, 0.5, 1)` | --- #### CSS Parts | Name | Description | | --------------- | ----------------------------------------- | | `::part(svg)` | The circular progress bar's SVG element. | | `::part(track)` | The circular progress bar's track circle. | | `::part(fill)` | The circular progress bar's fill circle. | --- #### CSS States | Name | Description | | ------------------------- | ----------------------------------------------------------------- | | `:state(--indeterminate)` | The progress ring has no value and is in the indeterminate state. | Source: https://staticview.a-labs.space/llms/packages/ui/docs/components/sv-progress-ring.md --- ## Radio **Form-associated** `sv-radio` is a radio button that groups like a native one. Radios with the same `name` in the same form are one group, and checking one unchecks the rest. ### Usage ```html
Size Small Medium Large
``` The content is the label, and it names the radio for assistive technology. Give the group's container `role="radiogroup"` and name it, with a `` in a `
` or with `aria-label`. A radio without a `name` is a group of its own, so the user can check it but never uncheck it. Lay out a group with plain CSS on its container, in a row or a column. ### Keyboard interaction Tab stops once on a group: on the checked radio, or on every radio while none is checked. | Key | Behavior | | -------------------------- | ------------------------------------------------------------------------- | | `Space` | Checks the focused radio | | `Enter` | Submits the radio's form | | `ArrowDown` / `ArrowRight` | Moves to the next enabled radio in the group, checks it, and wraps around | | `ArrowUp` / `ArrowLeft` | Moves to the previous enabled radio in the group, checks it, and wraps | In a right-to-left layout, `ArrowLeft` and `ArrowRight` swap, so they follow the screen. ### Form behavior The checked radio submits its `value` under the group's `name`, and `value` defaults to `"on"` like a native radio. One `required` radio makes the whole group required, and every radio in it reports `valueMissing` until one is checked. Resetting the form restores each radio's `checked` attribute. Only user interaction fires `clicked`, `input`, and `change`, and only on the radio that becomes checked. `checkedchange` fires on every radio whose state changes, including the one that another radio unchecks. ### Structure ```html tree
``` ### API References --- #### Methods ##### `check()` Checks the radio and unchecks the rest of its group, skipping the animation when `isInstant` is `true`. **Type:** `(isInstant?: boolean) => void` ##### `uncheck()` Unchecks the radio, skipping the animation when `isInstant` is `true`. **Type:** `(isInstant?: boolean) => void` --- #### Properties ##### `type` The type of the form element, always `"radio"`. Setting it has no effect. **Type:** `string`\ **Default:** `"radio"` ##### `checked` Whether the radio is checked. Checking it unchecks the other radios in its group. **Type:** `boolean`\ **Default:** `false` ##### `defaultChecked` The default checked state of the radio. It reflects the element's `checked` attribute. **Type:** `boolean` ##### `value` The value submitted with the form while the radio is checked. It reflects the `value` attribute and defaults to `"on"`. **Type:** `string`\ **Reflects:** `"value"` ##### `name` Name of the radio group. Radios with the same name in the same form form one group. **Type:** `string`\ **Reflects:** `"name"` ##### `required` Whether one radio in the group must be checked. One required radio makes the whole group required. **Type:** `boolean`\ **Reflects:** `"required"` ##### `disabled` Whether the radio's own disabled attribute is present. **Type:** `boolean`\ **Reflects:** `"disabled"` --- #### Attributes ##### `"disabled"` Whether the radio is disabled. **Type:** `boolean` ##### `"checked"` Whether the radio is checked. Checking it unchecks the other radios in its group. **Type:** `boolean` ##### `"name"` Name of the radio group. Radios with the same name in the same form form one group. **Type:** `string` ##### `"required"` Whether one radio in the group must be checked. One required radio makes the whole group required. **Type:** `boolean` ##### `"value"` The value submitted with the form while the radio is checked. It reflects the `value` attribute and defaults to `"on"`. **Type:** `string` --- #### Events ##### `clicked` Fired when the user checks the radio with a click or a key, before it changes. Cancel it to keep the group as it is. **Cancelable:** `true` ##### `checkedchange` Fired after `checked` changes, whether by the user or from code, including when another radio in the group takes over. --- #### Slots | Name | Description | | --------- | ---------------------------------------------------------------------------------------------------------- | | `dot` | Content shown inside the ring, like a dot or an icon. Show it only while checked with `:state(--checked)`. | | `Default` | The radio label. It also names the radio for assistive technology. | --- #### CSS Properties | Name | Description | Default | | --------------------------- | -------------------------------------------------------------- | -------------------------------- | | `--sv-radio-sz` | The size of the radio ring. | `1.2em` | | `--sv-radio-bg` | The background color of the radio ring. | `--sv-gray-6` | | `--sv-radio-bdr-clr` | The border color of the radio ring. | `--sv-gray-5` | | `--sv-radio-active-bdr-clr` | The border color of the radio ring while the radio is checked. | `--sv-accent` | | `--sv-radio-bdr-sz` | The size of the radio ring border. | `--sv-bdr-sz-md` | | `--sv-radio-active-bdr-sz` | The size of the radio ring border while the radio is checked. | `calc(var(--radio-size) / 4)` | | `--sv-radio-gap` | The space between the radio ring and the label. | `0.5em` | | `--sv-radio-dur` | The duration of the check animation. | `300ms` | | `--sv-radio-ease` | The easing function of the check animation. | `cubic-bezier(0, 0.55, 0.45, 1)` | --- #### CSS Parts | Name | Description | | ------------------- | ------------------------------------------------------------- | | `::part(container)` | The container element that holds the indicator and the label. | | `::part(radio)` | The ring that marks the radio. | --- #### CSS States | Name | Description | | ------------------- | --------------------- | | `:state(--checked)` | The radio is checked. | Source: https://staticview.a-labs.space/llms/packages/ui/docs/components/sv-radio.md --- ## Rating **Form-associated** `sv-rating` lets users pick a value by clicking or dragging across a row of shapes. ### Usage ```html ``` A wrapping `