# 3D Source UI Component Libraries

> All local file paths in this document are relative to the package root (`@3dsource/source-ui-native/`).


> Two Angular UI component libraries by 3D Source: `@3dsource/source-ui-native` (lightweight, zero-dependency UI primitives) and `@3dsource/source-ui` (higher-level components built on Angular CDK/Material). Both use Angular 19+ signals API (`input()`, `output()`), zoneless change detection, `ViewEncapsulation.None`, and CSS custom properties (`--src-*`) for theming.

## Key concepts

- All components use the `src-` selector prefix (e.g. `<src-button>`, `<src-badge>`)
- Inputs use Angular signals: `input()`, `input.required()`, `output()`
- Enum-like inputs are typed as union types derived from `as const` objects (e.g. `SourceButtonAppearanceKeys` = `"plain" | "inline" | "filled" | "default"`)
- Design tokens are SCSS CSS custom properties with `--src-` prefix, organized by category: color (light/dark themes), layout (responsive breakpoints), typeface, UI sizing
- `@3dsource/source-ui` depends on `@3dsource/source-ui-native` — always install both when using source-ui
- Modals have TWO approaches: native `<dialog>`-based via `SourceModalElementService` (source-ui-native, no CDK needed) and CDK Dialog-based via `Dialog.open(SourceModalComponent)` (source-ui, needs `@angular/cdk/dialog`)
- Popovers are opened via `SourcePopoverService`, not template binding
- The library provides TWO levels of styling: Angular Components (with `input()/output()` API) AND CSS-only Source Elements (BEM classes on native HTML tags — no Angular imports needed)
- The `section_3dsourcecom` class must be placed on the root app container element for Source UI styles to apply. Place it on `<app-root>` inner wrapper, the root `<section>`, or `<body>` as a last resort. Do NOT place it on `<html>`. Example: `<body class="section_3dsourcecom">` or `<div class="section_3dsourcecom">` as the first child of `<app-root>`.
- **Dark theme**: add `section_3dsourcecom--dark` class alongside `section_3dsourcecom` to activate the dark color scheme. For CDK overlays, add `cdk-overlay-container--dark` to the overlay container. Toggle between light and dark by adding/removing the `--dark` class. Both light and dark tokens are bundled — no extra import needed.
- **Scrollbar**: global scrollbar styling is applied automatically (`scrollbar-width: thin`). Override with `--srcScrollbarThumbColor` and `--srcScrollbarTrackColor` CSS custom properties on any ancestor element.
- STRICT RULE: Do NOT use Tailwind CSS or any utility-first CSS framework. All styling must use Source UI design tokens (`--src-*` CSS custom properties), Source Element BEM classes (`src-*`), and standard CSS/SCSS. Never generate Tailwind classes (`flex`, `p-4`, `bg-blue-500`, etc.).

## Library selection priority

STRICT RULE: Only install `@3dsource/source-ui` when Angular Material components (form fields, checkbox, radio, select, autocomplete, toggle) or CDK-based features (popover, color-picker, tabs, tooltip, CDK modal) are explicitly needed. Default to `@3dsource/source-ui-native` only.

Choose the appropriate library based on your project type:

1. **Non-Angular projects** (Lovable, Webflow, plain HTML, React, Vue, any non-Angular framework) → Install `@3dsource/source-ui-native` via npm. Import ONLY the compiled CSS file: `@3dsource/source-ui-native/styles/source-ui-native.min.css`. Use Source Elements (BEM CSS classes on native HTML tags). Do NOT install `@3dsource/source-ui` — it requires Angular and will not work.
2. **Angular without CDK/Material** → Install only `@3dsource/source-ui-native`. Use Angular components (`SourceButtonComponent`, `SourceBadgeComponent`, etc.) + Source Elements.
3. **Angular with CDK/Material** → Install both `@3dsource/source-ui-native` and `@3dsource/source-ui`. This gives access to color-picker, popover, tabs, tooltip, CDK modal, and styled Material form fields.

## Libraries

### @3dsource/source-ui-native v3.3.1

Lightweight UI primitives with zero dependencies (only `tslib`). **No Angular peer dependency** — works without Angular entirely. Can be used in any project (React, Vue, plain HTML, Lovable, etc.) by importing just the compiled CSS stylesheet. Includes:
- **Angular Components** (require Angular): badge, banner, button, copyright, divider, hint, icon-button, loading, logo-loading, modal-element, slider
- **Source Elements (CSS-only, no Angular needed)**: badge, banner, button, checkbox, divider, hint, icon-button, input, label, list, modal, radio, select, textarea, toggle — pure CSS classes applied to standard HTML elements

### @3dsource/source-ui v3.2.1

Higher-level components built on top of Angular CDK and Angular Material. Provides custom styling for Material form fields (input, select, autocomplete, checkbox, radio, toggle) to match the Source UI design system. Peer dependencies: `@3dsource/source-ui-native >=2.0.0`, `@angular/core >=19.0.0`, `@angular/material >=19.0.0`, `swiper >=11.2.6`. Components: color-picker, popover, slider-group, tabs, tooltip, toastr styling, Material form field styling.

**Important:** When using `@3dsource/source-ui`, you must provide `MAT_FORM_FIELD_DEFAULT_OPTIONS` with `{ appearance: 'outline' }` globally in your app config for correct form field styling.

## Component API reference (inline)

> Full API for every component inlined below. No external JSON links needed.

### Library: @3dsource/source-ui-native

### SourceBadgeComponent (@3dsource/source-ui-native)
**Selector:** `src-badge` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| backgroundColor | string | "var(--src-ui-accent-default, #017bffff)" | — | no | — |
| context | SourceBadgeContextKeys | — | default, info, success, warning, attention, error | no | — |
| size | SourceBadgeSizeKeys | "md" | sm, md, lg, xl | no | — |
| textColor | string | "var(--src-text-body-main-invert, #f9fafbff)" | — | no | — |
| customClass | string \| string[] | — | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |
| role | string \| null | "status" | — | no | — |
| ariaLabel | string | — | — | no | — |

### SourceBannerComponent (@3dsource/source-ui-native)
**Selector:** `src-banner` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| context | SourceBannerContextKeys | "default" | default, info, success, warning, critical, error | no | — |
| size | SourceBannerSizeKeys | "sm" | sm | no | — |
| isFullWidth | boolean | true | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |
| role | string | — | — | no | — |
| ariaLive | 'polite' \| 'assertive' \| 'off' | — | — | no | — |

### SourceButtonComponent (@3dsource/source-ui-native)
**Selector:** `src-button` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| type | SourceButtonTypeKeys | "button" | button, submit, reset | no | — |
| appearance | SourceButtonAppearanceKeys | "filled" | plain, inline, filled, default | no | — |
| weight | SourceButtonWeightKeys | "secondary" | primary, secondary, ghost | no | — |
| size | SourceButtonSizeKeys | "md" | slim, medium, large, sm, md, lg, xl | no | — |
| context | SourceButtonContextKeys | "default" | default, error, success, info | no | — |
| customClass | string \| string[] | "" | — | no | — |
| isFullWidth | boolean | false | — | no | — |
| isPressed | boolean | false | — | no | — |
| isDisabled | boolean | false | — | no | — |
| isLoading | boolean | false | — | no | — |
| isInverted | boolean | false | — | no | — |
| iconButton | boolean | false | — | no | — |
| srcButtonConfig | SourceButton | — | — | no | — |
| formID | string | — | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |
| ariaLabel | string | — | — | no | — |

**Outputs:**

| Output | Type | Description |
|--------|------|-------------|
| onClick | Event | — |
| onSubmit | Event | — |

### SourceCopyrightComponent (@3dsource/source-ui-native)
**Selector:** `src-copyright` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| linkText | string | "Powered by 3D Source" | — | no | — |
| isCollapsible | boolean | false | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |

### SourceDividerComponent (@3dsource/source-ui-native)
**Selector:** `src-divider` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| testID (alias: data-testid) | string | "" | — | no | — |

### SourceHintComponent (@3dsource/source-ui-native)
**Selector:** `src-hint` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| isError | boolean | false | — | no | — |
| context | SourceHintContextKeys | "default" | default, error, success, info | no | — |
| size | SourceHintSizeKeys | "md" | sm, md, lg, xl | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |
| id | string | — | — | no | — |
| role | string | — | — | no | — |
| ariaLive | 'polite' \| 'assertive' \| 'off' | — | — | no | — |

### SourceIconButtonComponent (@3dsource/source-ui-native)
**Selector:** `src-icon-button` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| name | unknown | — | — | no | — |
| type | SourceIconButtonTypeKeys | "button" | button, submit, reset | no | — |
| appearance | SourceIconButtonAppearanceKeys | "filled" | filled, plain, inline | no | — |
| weight | SourceIconButtonWeightKeys | "secondary" | primary, secondary, ghost | no | — |
| size | SourceIconButtonSizeKeys | "md" | xs, sm, md, lg, xl, default | no | — |
| shape | SourceIconButtonShapeKeys | "square" | square, round | no | — |
| context | SourceIconButtonContextKeys | "default" | default, error, success, info, warning | no | — |
| counter | number \| undefined | "undefined" | — | no | — |
| isPressed | boolean | false | — | no | — |
| isInverted | boolean | false | — | no | — |
| isDisabled | boolean | false | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |
| ariaLabel | string | — | — | no | — |

**Outputs:**

| Output | Type | Description |
|--------|------|-------------|
| onClick | Event | — |

### SourceLoadingComponent (@3dsource/source-ui-native)
**Selector:** `src-loading` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| size | number | 32 | — | no | — |
| progress | number \| null | "null" | — | no | — |
| lineCap | SourceLoadingLineCapKeys | "round" | round, square, butt | no | — |
| backgroundStrokeColor | string | "transparent" | — | no | — |
| progressStrokeColor | string | "var(--src-ui-accent-default, #017bffff)" | — | no | — |
| strokeWidth | number | 3 | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |
| role | string | — | — | no | — |
| ariaLabel | string | — | — | no | — |
| ariaValueNow | number | — | — | no | — |
| ariaValueMin | number | — | — | no | — |
| ariaValueMax | number | — | — | no | — |

### SourceLogoLoadingComponent (@3dsource/source-ui-native)
**Selector:** `src-logo-loading` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| size | number | 32 | — | no | — |
| strokeColor | string | "var(--src-ui-accent-default, #017bffff)" | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |
| role | string | "status" | — | no | — |
| ariaLabel | string | — | — | no | — |

### SourceModalElementComponent (@3dsource/source-ui-native)
**Selector:** `src-modal-element` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| ariaLabel | string | — | — | no | — |
| closeButtonLabel | string | "Close" | — | no | — |

**Outputs:**

| Output | Type | Description |
|--------|------|-------------|
| closeEvent | unknown | — |
| closed | void | — |

### SourceSliderComponent (@3dsource/source-ui-native)
**Selector:** `src-slider` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| id | string | — | — | no | — |
| value | number | — | — | yes | — |
| min | number | — | — | yes | — |
| max | number | — | — | yes | — |
| thumbSize | number | 16 | — | no | — |
| trackHeight | number | 4 | — | no | — |
| step | number | 1 | — | no | — |
| showTicks | boolean | false | — | no | — |
| isDisabled | boolean | false | — | no | — |
| orientation | 'horizontal' \| 'vertical' | "horizontal" | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |
| ariaLabel | string | — | — | no | — |
| ariaValueText | string | — | — | no | — |

**Outputs:**

| Output | Type | Description |
|--------|------|-------------|
| onChange | number | — |
| onInput | number | — |

### Library: @3dsource/source-ui

### SourcePopoverTriggerComponent (@3dsource/source-ui)
**Selector:** `src-popover-trigger` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| srcPopoverTpl | TemplateRef<HTMLElement> | — | — | yes | — |
| headerTitle | string | — | — | no | — |
| activeClass | string | — | — | no | — |
| hasBackButton | boolean | false | — | no | — |
| hasCloseButton | boolean | true | — | no | — |
| hasBackdrop | boolean | true | — | no | — |
| closeOnBackdropClick | boolean | true | — | no | — |
| popoverMaxHeight | string | "auto" | — | no | — |
| panelCustomClass | string | — | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |
| breakpointDesktop | string | "(min-width: 1024px)" | — | no | — |
| positions | ConnectedPosition[] | "[
    {
      originX: 'start',
      originY: 'bottom',
      overlayX: 'start',
      overlayY: 'top',
      offsetY: 4,
    },
    {
      originX: 'start',
      originY: 'top',
      overlayX: 'start',
      overlayY: 'bottom',
      offsetY: -8,
    },
  ]" | — | no | — |

**Outputs:**

| Output | Type | Description |
|--------|------|-------------|
| onPopoverShown | boolean | — |
| onBackButtonClick | OverlayRef | — |

### SourceSliderGroupComponent (@3dsource/source-ui)
**Selector:** `src-slider-group` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| min | number | — | — | yes | — |
| max | number | — | — | yes | — |
| value | number | — | — | yes | — |
| label | string | "" | — | no | — |
| id | string | "" | — | no | — |
| step | number | 1 | — | no | — |
| units | string | "%" | — | no | — |
| showTicks | boolean | false | — | no | — |
| showRange | boolean | false | — | no | — |
| isDisabled | boolean | false | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |

**Outputs:**

| Output | Type | Description |
|--------|------|-------------|
| groupValueChange | number | — |

### SourceTabLineComponent (@3dsource/source-ui)
**Selector:** `src-tab-line` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| tabs | any[] | — | — | yes | — |
| label | string | — | — | yes | — |
| selectedIndex | number | 0 | — | no | — |
| appearance | SourceTabAppearanceKeys | "default" | default, button | no | — |
| isCompact | boolean | false | — | no | — |
| offsetBefore | number \| undefined | "undefined" | — | no | — |
| offsetAfter | number \| undefined | "undefined" | — | no | — |
| spaceBetween | number \| undefined | "undefined" | — | no | — |
| isFullWidth | boolean | false | — | no | — |
| isSwiper | boolean | false | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |

**Outputs:**

| Output | Type | Description |
|--------|------|-------------|
| onSelectTab | number | — |

### SourceTooltipDirective (@3dsource/source-ui)
**Selector:** `[srcTooltip]` · **Kind:** Directive

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| srcTooltip | string \| TemplateRef<void> | — | — | yes | — |
| srcTooltipPosition | SourceTooltipPositionKeys | "top" | top, bottom, left, right | no | — |
| srcTooltipHideDelay | number | 0 | — | no | — |
| srcTooltipMaxWidth | string | "280px" | — | no | — |
| srcTooltipCustomClass | string | "" | — | no | — |
| sourceTooltipData | SourceTooltipData | — | — | no | — |

### ColorPaletteComponent (@3dsource/source-ui)
**Selector:** `src-color-palette` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| selectedColor | string | — | — | yes | — |
| isNeedUpdatePalette | number | — | — | yes | — |

**Outputs:**

| Output | Type | Description |
|--------|------|-------------|
| paletteColorUpdate | string | — |

### ColorSliderComponent (@3dsource/source-ui)
**Selector:** `src-color-slider` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| selectedColor | string | — | — | yes | — |
| orientation | SourceColorPickerOrientationKeys | — | horizontal, vertical | yes | — |
| sliderThickness | number | — | — | yes | — |
| isNeedUpdateSlider | number | — | — | yes | — |

**Outputs:**

| Output | Type | Description |
|--------|------|-------------|
| sliderColorUpdate | string | — |

### SourceColorPickerComponent (@3dsource/source-ui)
**Selector:** `src-color-picker` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| selectedColor | string | — | — | yes | — |
| isCompact | boolean | false | — | no | — |
| orientation | SourceColorPickerOrientationKeys | "horizontal" | horizontal, vertical | no | — |
| hasInput | boolean | true | — | no | — |
| sliderThickness | number | 28 | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |

**Outputs:**

| Output | Type | Description |
|--------|------|-------------|
| colorUpdate | string | — |

### SourceTabComponent (@3dsource/source-ui)
**Selector:** `src-tab` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| isActive | boolean | false | — | no | — |

### SourceTabsComponent (@3dsource/source-ui)
**Selector:** `src-tabs` · **Kind:** Component

**Inputs:**

| Input | Type | Default | Values | Required | Description |
|-------|------|---------|--------|----------|-------------|
| label | string | — | — | yes | — |
| data | SourceTabData[] | — | — | yes | — |
| selectedIndex | number | 0 | — | no | — |
| headerTemplate | TemplateRef<any> | — | — | no | — |
| isCompact | boolean | false | — | no | — |
| isFullWidth | boolean | false | — | no | — |
| isSwiper | boolean | false | — | no | — |
| swiperConfig | SwiperOptions | — | — | no | — |
| testID (alias: data-testid) | string | "" | — | no | — |

**Outputs:**

| Output | Type | Description |
|--------|------|-------------|
| onSelectTab | number | — |


## Source Elements (CSS-only styling)

Source Elements let you style standard HTML elements (`<button>`, `<input>`, `<select>`, etc.) using BEM CSS classes — no Angular component imports needed. Just add the class to a native HTML tag. All styles come from the `source.ui.native.scss` stylesheet.

- [Source Elements API (JSON)](./docs/api/source-elements.json): Machine-readable reference for all CSS-only elements with modifiers, sub-elements, and usage examples.

Use Source Elements when: you don't need Angular signal bindings, you want minimal overhead, or you're prototyping without Angular.

### Badge Element
Apply `src-badge` class to any appropriate HTML tag.
- **Context**: `src-badge--context-default` (default) | `src-badge--context-info` | `src-badge--context-success` | `src-badge--context-warning` | `src-badge--context-attention` | `src-badge--context-error`
- `src-badge__icon` — Prefix/postfix icon wrapper inside badge.
- Customise via CSS custom properties: `--srcBadgeBackgroundColor`, `--srcBadgeTextColor`.

### Banner Element
Apply `src-banner` class to any appropriate HTML tag.
- **Context**: `src-banner--context-info` | `src-banner--context-success` | `src-banner--context-warning` | `src-banner--context-error` | `src-banner--context-critical`
- `src-banner__icon-prefix` — Leading icon slot.
- `src-banner__icon-postfix` — Trailing icon slot (e.g. close button).
- `src-banner__title` — Uppercase bold title within the banner.
- `src-banner__content` — Main body content wrapper.

### Button Element
Apply `src-button` class to any appropriate HTML tag.
- **Weight**: `src-button--primary` | `src-button--secondary` (default) | `src-button--ghost`
- **Appearance**: `src-button--plain` | `src-button--inline`
- **Size**: `src-button--size-sm` | `src-button--size-md` (default) | `src-button--size-lg` | `src-button--size-xl` | `src-button--full-width`
- **Context**: `src-button--context-info` | `src-button--context-success` | `src-button--context-error`
- **State**: `src-button--pressed`
- [Demo](https://preview.3dsource.com/front-libraries/master/#/components/SourceButtonElement)

### Checkbox Element
Apply `src-checkbox` class to any appropriate HTML tag.
- `src-checkbox__label` — Text label beside the checkbox.
- [Demo](https://preview.3dsource.com/front-libraries/master/#/components/FormElements)

### Divider Element
Apply `src-divider` class to any appropriate HTML tag.
- Customise via CSS custom properties: `--srcDividerColor`, `--srcDividerThickness`, `--srcDividerOffsetTop`, `--srcDividerOffsetBottom`.

### Hint Element
Apply `src-hint` class to any appropriate HTML tag.
- **Context**: `src-hint--context-error` | `src-hint--context-info` | `src-hint--context-success` | `src-hint--error`
- `src-hint__icon` — Prefix icon slot.

### Icon Button Element
Apply `src-icon-button` class to any appropriate HTML tag.
- **Appearance**: `src-icon-button--plain` | `src-icon-button--inline`
- **Weight**: `src-icon-button--primary` | `src-icon-button--secondary` (default) | `src-icon-button--ghost`
- **Size**: `src-icon-button--size-sm` | `src-icon-button--size-md` (default) | `src-icon-button--size-lg` | `src-icon-button--size-xl`
- **Shape**: `src-icon-button--round`
- **Context**: `src-icon-button--context-info` | `src-icon-button--context-success` | `src-icon-button--context-warning` | `src-icon-button--context-error`
- **State**: `src-icon-button--pressed`
- [Demo](https://preview.3dsource.com/front-libraries/master/#/components/SourceIconButtonElement)

### Input Element
Apply `src-input` class to any appropriate HTML tag.
- **Weight**: `src-input--primary` (default) | `src-input--secondary` | `src-input--ghost`
- **Size**: `src-input--size-sm` | `src-input--size-md` (default) | `src-input--size-lg` | `src-input--size-xl`
- **Context**: `src-input--context-success` | `src-input--context-error`
- **State**: `src-input--disabled`
- [Demo](https://preview.3dsource.com/front-libraries/master/#/components/SourceInputElement)

### Label Element
Apply `src-label` class to any appropriate HTML tag.

### List Element
Apply `src-list` class to any appropriate HTML tag.
- **Size**: `src-list--compact`
- `src-list__item` — The main class for the list item element.
- `src-list__item--flex` — Class modifier for a flex list item. Use this when your content includes an icon or has a more complex structure. You can still style it in your CSS.
- `src-list__item--disabled` — List item disabled state. The "disabled" attribute is also supported.
- `src-list__item--selected` — Selected state for the list item.
- `src-list__item--context-error` — Visually distinct appearance to emphasize a critical action.
- [Demo](https://preview.3dsource.com/front-libraries/master/#/components/SourceListElement)

### Modal Element
Apply `src-modal` class to any appropriate HTML tag.
- `src-modal__header` — Header area with bottom border.
- `src-modal__body` — Scrollable content area with padding.
- `src-modal__body--icon` — Two-column grid layout (icon + content).
- `src-modal__icon` — Icon in the first column of icon-body layout.
- `src-modal__title` — Bold title text.
- `src-modal__scroll-box` — Scrollable content area spanning full grid width.
- `src-modal__footer` — Action buttons row, right-aligned, with top border.
- `src-modal__footer-group` — Button group within footer.
- `src-modal__close` — Absolutely positioned close button at top-right.

### Radio Group Element
Apply `src-radio-group` class to any appropriate HTML tag.
- **Layout**: `src-radio-group--horizontal`
- `src-radio` — Flex container for a single radio button. Wraps input[type="radio"] with custom appearance.
- `src-radio__label` — Text label beside the radio button.
- [Demo](https://preview.3dsource.com/front-libraries/master/#/components/FormElements)

### Select Element
Apply `src-select` class to any appropriate HTML tag.
- **Weight**: `src-select--primary` (default) | `src-select--secondary` | `src-select--ghost`
- **Size**: `src-select--size-sm` | `src-select--size-md` (default) | `src-select--size-lg` | `src-select--size-xl`
- **Context**: `src-select--context-success` | `src-select--context-error`
- **State**: `src-select--disabled`
- [Demo](https://preview.3dsource.com/front-libraries/master/#/components/SourceSelectElement)

### Textarea Element
Apply `src-textarea` class to any appropriate HTML tag.
- **Weight**: `src-textarea--secondary` | `src-textarea--ghost`
- **Size**: `src-textarea--size-sm` | `src-textarea--size-md` (default) | `src-textarea--size-lg` | `src-textarea--size-xl`
- **Context**: `src-textarea--context-success` | `src-textarea--context-error`
- **State**: `src-textarea--disabled`

### Toggle Element
Apply `src-toggle` class to any appropriate HTML tag.
- `src-toggle__label` — Text label beside the toggle.
- [Demo](https://preview.3dsource.com/front-libraries/master/#/components/FormElements)

## Stylesheet import paths

STRICT RULE: Use ONLY the paths listed below. Do NOT fabricate paths like `@3dsource/source-ui-native/src/lib/styles/...` or `dist/...`.

**SCSS import (Angular projects with a builder) — add to your `styles.scss`:**
```
// source-ui-native only:
@use '../node_modules/@3dsource/source-ui-native/styles/source.ui.native.scss' as source-ui-native;

// source-ui-native + source-ui (both):
@use '../node_modules/@3dsource/source-ui-native/styles/source.ui.native.scss' as source-ui-native;
@use '../node_modules/@3dsource/source-ui/styles/source.ui.scss' as source-ui;
```

**Compiled CSS import (non-Angular / CSS-only / no builder) — add to `<head>` or import in your bundler:**
```
node_modules/@3dsource/source-ui-native/styles/source-ui-native.min.css
```

IMPORTANT: SCSS entry files use dots in the name (`source.ui.native.scss`), while compiled CSS uses dashes (`source-ui-native.min.css`). Do not confuse them.

## Icons

The library is icon-agnostic — no icon font is bundled. Icons are projected into components via `<ng-content>` (Angular) or placed directly inside elements (CSS-only).

STRICT RULE: Do NOT use the Material Icons font (`<link href="https://fonts.google.com/icon?family=Material+Icons">` or the `material-icons` CSS class). The font-based icon approach conflicts with Source UI styles. Use **SVG icons** instead.

Recommended icon source: [Material Symbols (Rounded)](https://fonts.google.com/icons?icon.style=Rounded) with settings: Style Rounded, Weight 400, Fill On, Optical size 20dp.

### SVG icon setup (Angular projects)

1. Create an `assets/icons/` folder in your project.
2. Download SVG icons from your design or from [Material Symbols](https://fonts.google.com/icons?icon.style=Rounded).
3. In each SVG file: set `fill="currentColor"` (for CSS color control), remove `width`/`height` attributes, keep `viewBox`.
4. Create an `SvgIconComponent` in your project (this component is NOT part of the library — copy it into your codebase):

```typescript
import { HttpClient } from '@angular/common/http';
import { Component, effect, inject, input, signal, untracked } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { first } from 'rxjs';

@Component({
  selector: 'src-icon',
  imports: [],
  template: `@if (svg()) {
    <div [innerHTML]="svg()" class="src-icon" [style.--srcIconSize]="size()"></div>
  }`,
  styles: [`
    .src-icon { width: var(--srcIconSize); height: var(--srcIconSize); color: inherit; }
    .src-icon svg { width: 100%; height: 100%; fill: currentColor; }
  `],
})
export class SvgIconComponent {
  name = input<string>('');
  size = input<string>('20px');
  PATH_TO_ICON_FOLDER = 'assets/icons';
  svg = signal<SafeHtml | null>(null);
  http = inject(HttpClient);
  sanitizer = inject(DomSanitizer);

  _ = effect(() => {
    const path = this.PATH_TO_ICON_FOLDER + '/' + this.name() + '.svg';
    untracked(() => {
      this.http.get(path, { responseType: 'text' }).pipe(first()).subscribe({
        next: (rawSvg) => this.svg.set(this.sanitizer.bypassSecurityTrustHtml(rawSvg)),
        error: () => console.warn('Icon "' + this.name() + '" not found at ' + path),
      });
    });
  });
}
```

5. Usage: `<src-icon name="close"></src-icon>`, `<src-icon name="chevron_left" size="32px"></src-icon>`
6. Default size: `20px`. Color inherits from parent element.

### SVG icon setup (non-Angular / CSS-only projects)

Inline the SVG directly in your HTML:
```html
<button class="src-icon-button">
  <svg viewBox="0 0 24 24" fill="currentColor"><path d="..."/></svg>
</button>
```

### Icon design tokens

- `--src-icon-size` — default icon size (16px)
- `--src-icon-default`, `--src-icon-info`, `--src-icon-success`, `--src-icon-error`, `--src-icon-warning` — contextual icon colors

- [Icons documentation](https://preview.3dsource.com/front-libraries/master/#/icons)

## Material Form Components (source-ui)

`@3dsource/source-ui` provides custom styling for Angular Material form fields. These are NOT separate Angular components — the library overrides default Material styles when you import `source.ui.scss`. Styled Material components:
- `<mat-form-field>` with `<input matInput>` — text input
- `<mat-form-field>` with `<mat-select>` — dropdown select
- `<mat-form-field>` with `<input matInput [matAutocomplete]>` — autocomplete
- `<mat-checkbox>` — styled checkbox
- `<mat-radio-group>` / `<mat-radio-button>` — styled radio
- `<mat-slide-toggle>` — styled toggle

All Material form fields support the same sizing system as Source Elements via class modifiers on the `<mat-form-field>` tag. Default size is `md` (no class needed). Context state classes use `--context-` prefix: `--context-success`, `--context-error` (previously `--state-success` / `--state-error`).

- [Demo](https://preview.3dsource.com/front-libraries/master/#/components/FormComponents)

## Full component registry

- [Component Registry](./docs/api/_registry.json): Index of all 20 components across both libraries with selectors, kinds, and JSON file references

## Design Tokens (inline)

> Auto-generated from 1029 total tokens. Below is a curated subset of semantic tokens most useful for development. Full token data: design-tokens.json.

### primitives (scope: global)
Source: `variables/primitives/primitives.scss`

| Token | Value |
|-------|-------|
| --src-space-0 | 0px |
| --src-space-px | 1px |
| --src-space-0-5 | 2px |
| --src-space-1 | 4px |
| --src-space-1-5 | 6px |
| --src-space-2 | 8px |
| --src-space-2-5 | 10px |
| --src-space-3 | 12px |
| --src-space-3-5 | 14px |
| --src-space-4 | 16px |
| --src-space-5 | 20px |
| --src-space-6 | 24px |
| --src-space-7 | 28px |
| --src-space-8 | 32px |
| --src-space-9 | 36px |
| --src-space-10 | 40px |
| --src-space-11 | 44px |
| --src-space-12 | 48px |
| --src-space-14 | 56px |
| --src-space-16 | 64px |
| --src-space-20 | 80px |
| --src-space-24 | 96px |
| --src-space-28 | 112px |
| --src-space-32 | 128px |
| --src-space-36 | 144px |
| --src-space-40 | 160px |
| --src-space-44 | 176px |
| --src-space-48 | 192px |
| --src-space-52 | 208px |
| --src-space-56 | 224px |
| --src-space-60 | 240px |
| --src-space-64 | 256px |
| --src-space-72 | 288px |
| --src-space-80 | 320px |
| --src-space-96 | 384px |
| --src-color-primary-50 | #f1f6ffff |
| --src-color-primary-100 | #d6e9ffff |
| --src-color-primary-200 | #add4ffff |
| --src-color-primary-300 | #7dbbffff |
| --src-color-primary-400 | #4ea4ffff |
| --src-color-primary-500 | #017bffff |
| --src-color-primary-600 | #016fe6ff |
| --src-color-primary-700 | #0162ccff |
| --src-color-primary-800 | #014ca3ff |
| --src-color-primary-900 | #003a7aff |
| --src-color-primary-950 | #00244dff |
| --src-color-alpha-accent-10 | #017bff14 |
| --src-color-alpha-accent-50 | #017bff1f |
| --src-color-alpha-accent-100 | #017bff29 |
| --src-color-alpha-accent-200 | #017bff3d |
| --src-color-alpha-accent-300 | #017bff52 |
| --src-color-alpha-accent-400 | #017bff5c |

### color-light (scope: global)
Source: `variables/color/light.scss`

| Token | Value |
|-------|-------|
| --src-surface-background | var(--src-color-grey-50) |
| --src-surface-background-inverse | var(--src-color-grey-800) |
| --src-ui-accent-default | var(--src-color-primary-500) |
| --src-ui-accent-default-hover | var(--src-color-primary-600) |
| --src-ui-accent-disabled | var(--src-color-alpha-test-200) |
| --src-ui-accent-success | var(--src-color-green-500) |
| --src-ui-accent-success-hover | var(--src-color-green-600) |
| --src-ui-accent-error | var(--src-color-red-500) |
| --src-ui-accent-error-hover | var(--src-color-red-600) |
| --src-ui-accent-active | var(--src-color-grey-700) |
| --src-ui-accent-active-hover | var(--src-color-grey-900) |
| --src-ui-secondary-default | var(--src-color-alpha-default-10) |
| --src-ui-secondary-default-hover | var(--src-color-alpha-default-50) |
| --src-ui-secondary-disabled | var(--src-color-alpha-white-10) |
| --src-ui-secondary-active | var(--src-color-alpha-accent-50) |
| --src-ui-secondary-info | var(--src-color-alpha-accent-10) |
| --src-ui-secondary-info-hover | var(--src-color-alpha-accent-50) |
| --src-ui-secondary-success | var(--src-color-alpha-success-10) |
| --src-ui-secondary-success-hover | var(--src-color-alpha-success-50) |
| --src-ui-secondary-error | var(--src-color-alpha-destruct-10) |
| --src-ui-secondary-error-hover | var(--src-color-alpha-destruct-100) |
| --src-ui-secondary-progress | var(--color-alpha-progress-10) |
| --src-ui-input-default | var(--src-color-alpha-white-10) |
| --src-ui-input-secondary | var(--src-color-alpha-default-10) |
| --src-ui-input-hover | var(--src-color-alpha-accent-10) |
| --src-ui-input-disabled | var(--src-color-alpha-default-50) |
| --src-ui-input-success | var(--src-color-alpha-white-10) |
| --src-ui-input-success-hover | var(--src-color-alpha-success-10) |
| --src-ui-input-error | var(--src-color-alpha-white-10) |
| --src-ui-input-error-hover | var(--src-color-alpha-destruct-10) |
| --src-surface-curtain | var(--src-color-alpha-default-600) |
| --src-surface-fade | var(--src-color-alpha-white-600) |
| --src-surface-bg | var(--src-color-alpha-default-200) |
| --src-ui-light | var(--src-light) |
| --src-border-control-default | var(--src-color-neutral-300) |
| --src-border-control-hover | var(--src-color-neutral-500) |
| --src-border-button-basic | var(--src-color-grey-200) |
| --src-border-button-basic-hover | var(--src-color-grey-400) |
| --src-border-button-info | var(--src-color-primary-300) |
| --src-border-button-info-hover | var(--src-color-primary-500) |
| --src-border-button-success | var(--src-color-green-400) |
| --src-border-button-success-hover | var(--src-color-green-500) |
| --src-border-button-error | var(--src-color-red-300) |
| --src-border-button-error-hover | var(--src-color-red-500) |
| --src-border-button-disabled | var(--src-color-grey-200) |
| --src-border-input-basic | var(--src-color-grey-300) |
| --src-border-input-hover | var(--src-color-grey-400) |
| --src-border-input-filled | var(--src-color-grey-300) |
| --src-border-input-active | var(--src-color-primary-500) |
| --src-border-input-success | var(--src-color-green-500) |
| --src-border-input-success-hover | var(--src-color-green-600) |
| --src-border-input-error | var(--src-color-red-500) |
| --src-border-input-error-hover | var(--src-color-red-500) |
| --src-border-container-basic | var(--src-color-grey-300) |
| --src-border-container-hover | var(--src-color-grey-400) |
| --src-border-container-light | var(--src-color-alpha-default-50) |
| --src-border-container-active | var(--src-color-primary-400) |
| --src-border-container-success | var(--src-color-green-200) |
| --src-border-container-error | var(--src-color-red-200) |
| --src-text-body-main | var(--src-color-grey-900) |
| --src-text-body-secondary | var(--src-color-grey-600) |
| --src-text-body-grey | var(--src-color-grey-400) |
| --src-text-body-lable | var(--src-color-grey-500) |
| --src-text-body-disabled | var(--src-color-grey-400) |
| --src-text-body-main-invert | var(--src-color-grey-50) |
| --src-text-body-secondary-invert | var(--src-color-grey-300) |
| --src-icon-default | var(--src-color-grey-700) |
| --src-icon-label | var(--src-color-grey-500) |
| --src-icon-hover | var(--src-color-grey-900) |
| --src-icon-grey | var(--src-color-grey-400) |
| --src-icon-disabled | var(--src-color-grey-400) |
| --src-icon-main-invert | var(--src-light) |
| --src-icon-secondary-invert | var(--src-color-grey-200) |
| --src-icon-info | var(--src-color-primary-500) |
| --src-icon-info-hover | var(--src-color-primary-600) |
| --src-icon-success | var(--src-color-green-600) |
| --src-icon-success-hover | var(--src-color-green-700) |
| --src-icon-error | var(--src-color-red-500) |
| --src-icon-error-hover | var(--src-color-red-600) |
| --src-icon-warning | var(--src-color-tertiary-600) |
| --src-icon-warning-hover | var(--src-color-tertiary-700) |
| --src-icon-attention | var(--src-color-yellow-800) |
| --src-icon-attention-hover | var(--src-color-yellow-900) |
| --src-graphics-positive | var(--src-color-green-500) |
| --src-graphics-negative | var(--src-color-red-500) |
| --src-graphics-accent | var(--src-color-primary-500) |
| --src-graphics-dark-grey | var(--src-color-grey-500) |
| --src-graphics-orange | #f5a80fff |
| --src-graphics-yellow | #f0e442ff |
| --src-graphics-turquoise | #00ced1ff |
| --src-graphics-brown | #8b4513ff |
| --src-graphics-black | var(--src-color-grey-700) |
| --src-text-body-accent | var(--src-color-primary-600) |
| --src-text-body-success | var(--src-color-green-600) |
| --src-text-body-destruct | var(--src-color-red-600) |
| --src-text-ui-primary-main | var(--src-light) |
| --src-text-ui-primary-secondary | var(--src-color-grey-200) |
| --src-text-ui-primary-disabled | var(--src-color-grey-400) |
| --src-text-ui-primary-main-invert | var(--src-color-grey-50) |
| --src-text-ui-primary-secondary-invert | var(--src-color-grey-200) |
| --src-text-ui-secondary-main | var(--src-color-grey-900) |
| --src-text-ui-secondary-secondary | var(--src-color-grey-600) |
| --src-text-ui-secondary-grey | var(--src-color-grey-400) |
| --src-text-ui-secondary-disabled | var(--src-color-grey-400) |
| --src-text-ui-secondary-main-invert | var(--src-color-grey-50) |
| --src-text-ui-secondary-secondary-invert | var(--src-color-grey-300) |
| --src-shadow-hard | var(--src-color-alpha-test-200) |
| --src-shadow-light | var(--src-color-alpha-default-50) |
| --src-shadow-accent-light | var(--src-color-alpha-accent-100) |
| --src-shadow-accent-hard | var(--src-color-alpha-accent-200) |
| --src-shadow-success | var(--src-color-alpha-success-50) |
| --src-shadow-success-hover | var(--src-color-alpha-success-200) |
| --src-shadow-error | var(--src-color-alpha-destruct-100) |
| --src-shadow-error-hover | var(--src-color-alpha-destruct-200) |
| --src-text-ui-accent-main | var(--src-color-primary-600) |
| --src-text-ui-accent-hover | var(--src-color-primary-700) |
| --src-text-ui-success-main | var(--src-color-green-600) |
| --src-text-ui-success-hover | var(--src-color-green-700) |
| --src-text-ui-distruct-main | var(--src-color-red-500) |
| --src-text-ui-distruct-hover | var(--src-color-red-600) |
| --src-surface-container-main | var(--src-light) |
| --src-surface-container-on-top | var(--src-color-alpha-default-10) |
| --src-surface-container-secondary | var(--src-color-grey-50) |
| --src-surface-container-info | var(--src-color-primary-50) |
| --src-surface-container-success | var(--src-color-green-50) |
| --src-surface-container-error | var(--src-color-red-50) |
| --src-surface-toast-basic | var(--src-color-alpha-default-50) |
| --src-surface-toast-info | var(--src-color-primary-600) |
| --src-surface-toast-success | var(--src-color-green-600) |
| --src-surface-toast-error | var(--src-color-red-500) |
| --src-border-infoPrompt-basic | var(--src-color-grey-300) |
| --src-border-infoPrompt-light | var(--src-color-alpha-default-50) |
| --src-border-infoPrompt-info | var(--src-color-primary-200) |
| --src-border-infoPrompt-success | var(--src-color-green-200) |
| --src-border-infoPrompt-error | var(--src-color-red-200) |
| --src-gradient-light-start | var(--src-color-alpha-test-100) |
| --src-gradient-light-end | var(--src-color-alpha-default-10) |
| --src-gradient-accent-light | var(--src-color-alpha-accent-10) |
| --src-gradient-accent-hard | var(--src-color-alpha-accent-50) |
| --src-gradient-success | var(--color-alpha-success-50) |
| --src-gradient-success-hover | var(--color-alpha-success-200) |
| --src-gradient-error | var(--color-alpha-destruct-100) |
| --src-gradient-error-hover | var(--color-alpha-destruct-200) |
| --src-tech-sticker | var(--src-color-tertiary-100) |
| --wireframe-main | var(--src-color-neutral-600) |
| --wireframe-secondary | var(--src-color-neutral-500) |
| --wireframe-light | var(--src-color-neutral-300) |
| --wireframe-surface-primary | var(--src-light) |
| --wireframe-surface-secondary | var(--src-color-alpha-default-50) |
| --wireframe-border | var(--src-color-alpha-default-200) |
| --wireframe-invert | var(--src-light) |
| --src-tech-description | var(--src-color-tertiary-900) |
| --src-light | #ffffffff |
| --src-dark | #000000ff |
| --src-ui-status-basic-neutral | var(--src-color-grey-500) |
| --src-ui-status-basic-neutral-hover | var(--src-color-grey-600) |
| --src-ui-status-basic-critical | var(--src-color-red-500) |
| --src-ui-status-basic-critical-hover | var(--src-color-red-600) |
| --src-ui-status-basic-info | var(--src-color-primary-500) |
| --src-ui-status-basic-info-hover | var(--src-color-primary-600) |
| --src-ui-status-basic-success | var(--src-color-green-500) |
| --src-ui-status-basic-success-hover | var(--src-color-green-500) |
| --src-ui-status-basic-warning | var(--src-color-tertiary-500) |
| --src-ui-status-basic-warning-hover | var(--src-color-tertiary-600) |
| --src-ui-status-basic-attention | var(--src-color-yellow-500) |
| --src-ui-status-basic-attention-hover | var(--src-color-yellow-600) |
| --src-ui-status-light-neutral | var(--src-color-alpha-default-100) |
| --src-ui-status-light-neutral-hover | var(--src-color-alpha-default-200) |
| --src-ui-status-light-critical | var(--src-color-alpha-destruct-100) |
| --src-ui-status-light-critical-hover | var(--src-color-alpha-destruct-200) |
| --src-ui-status-light-info | var(--src-color-alpha-accent-200) |
| --src-ui-status-light-info-hover | var(--src-color-alpha-accent-300) |
| --src-ui-status-light-success | var(--src-color-alpha-success-100) |
| --src-ui-status-light-success-hover | var(--src-color-alpha-success-200) |
| --src-ui-status-light-warning | var(--src-color-alpha-warning-200) |
| --src-ui-status-light-warning-hover | var(--src-color-alpha-warning-300) |
| --src-ui-status-light-attention | var(--src-color-alpha-attention-200) |
| --src-ui-status-light-attention-hover | var(--src-color-alpha-attention-300) |
| --src-text-ui-warning-main | var(--src-color-tertiary-600) |
| --src-text-ui-warning-hover | var(--src-color-tertiary-700) |
| --src-text-ui-attention-main | var(--src-color-yellow-800) |
| --src-text-ui-attention-hover | var(--src-color-yellow-900) |

### color-dark (scope: global)
Source: `variables/color/dark.scss`

| Token | Value |
|-------|-------|
| --src-surface-background | var(--src-color-grey-900) |
| --src-surface-background-inverse | var(--src-color-grey-800) |
| --src-ui-accent-default | var(--src-color-primary-400) |
| --src-ui-accent-default-hover | var(--src-color-primary-500) |
| --src-ui-accent-disabled | var(--src-color-alpha-white-100) |
| --src-ui-accent-success | var(--src-color-green-600) |
| --src-ui-accent-success-hover | var(--src-color-green-500) |
| --src-ui-accent-error | var(--src-color-red-600) |
| --src-ui-accent-error-hover | var(--src-color-red-500) |
| --src-ui-accent-active | var(--src-color-grey-200) |
| --src-ui-accent-active-hover | var(--src-color-grey-50) |
| --src-ui-secondary-default | var(--src-color-alpha-white-50) |
| --src-ui-secondary-default-hover | var(--src-color-alpha-default-100) |
| --src-ui-secondary-disabled | var(--src-color-alpha-default-100) |
| --src-ui-secondary-active | var(--src-color-alpha-accent-100) |
| --src-ui-secondary-info | var(--src-color-alpha-accent-200) |
| --src-ui-secondary-info-hover | var(--src-color-alpha-accent-100) |
| --src-ui-secondary-success | var(--src-color-alpha-success-200) |
| --src-ui-secondary-success-hover | var(--src-color-alpha-success-50) |
| --src-ui-secondary-error | var(--src-color-alpha-destruct-200) |
| --src-ui-secondary-error-hover | var(--src-color-alpha-destruct-100) |
| --src-ui-secondary-progress | var(--src-color-alpha-progress-10) |
| --src-ui-input-default | var(--src-color-alpha-white-10) |
| --src-ui-input-secondary | var(--src-color-alpha-default-200) |
| --src-ui-input-hover | var(--src-color-alpha-default-200) |
| --src-ui-input-disabled | var(--src-color-alpha-default-200) |
| --src-ui-input-success | var(--src-color-alpha-white-10) |
| --src-ui-input-success-hover | var(--src-color-alpha-success-50) |
| --src-ui-input-error | var(--src-color-alpha-white-10) |
| --src-ui-input-error-hover | var(--src-color-alpha-destruct-50) |
| --src-surface-curtain | var(--src-color-alpha-default-600) |
| --src-surface-fade | var(--src-color-alpha-default-200) |
| --src-surface-bg | var(--src-color-alpha-white-50) |
| --src-ui-light | var(--src-dark) |
| --src-border-control-default | var(--src-color-neutral-300) |
| --src-border-control-hover | var(--src-color-neutral-100) |
| --src-border-button-basic | var(--src-color-grey-600) |
| --src-border-button-basic-hover | var(--src-color-grey-500) |
| --src-border-button-info | var(--src-color-primary-500) |
| --src-border-button-info-hover | var(--src-color-primary-400) |
| --src-border-button-success | var(--src-color-green-700) |
| --src-border-button-success-hover | var(--src-color-green-600) |
| --src-border-button-error | var(--src-color-red-500) |
| --src-border-button-error-hover | var(--src-color-red-600) |
| --src-border-button-disabled | var(--src-color-grey-800) |
| --src-border-input-basic | var(--src-color-grey-700) |
| --src-border-input-hover | var(--src-color-grey-500) |
| --src-border-input-filled | var(--src-color-grey-700) |
| --src-border-input-active | var(--src-color-primary-500) |
| --src-border-input-success | var(--src-color-green-600) |
| --src-border-input-success-hover | var(--src-color-green-400) |
| --src-border-input-error | var(--src-color-red-700) |
| --src-border-input-error-hover | var(--src-color-red-700) |
| --src-border-container-basic | var(--src-color-grey-800) |
| --src-border-container-hover | var(--src-color-grey-600) |
| --src-border-container-light | var(--src-color-alpha-white-50) |
| --src-border-container-active | var(--src-color-primary-500) |
| --src-border-container-success | var(--src-color-green-800) |
| --src-border-container-error | var(--src-color-red-800) |
| --src-text-body-main | var(--src-color-grey-50) |
| --src-text-body-secondary | var(--src-color-grey-300) |
| --src-text-body-grey | var(--src-color-grey-400) |
| --src-text-body-lable | var(--src-color-grey-300) |
| --src-text-body-disabled | var(--src-color-grey-500) |
| --src-text-body-main-invert | var(--src-color-grey-900) |
| --src-text-body-secondary-invert | var(--src-color-grey-600) |
| --src-icon-default | var(--src-color-grey-200) |
| --src-icon-label | var(--src-color-grey-400) |
| --src-icon-hover | var(--src-color-grey-50) |
| --src-icon-grey | var(--src-color-grey-400) |
| --src-icon-disabled | var(--src-color-grey-600) |
| --src-icon-main-invert | var(--src-light) |
| --src-icon-secondary-invert | var(--src-color-grey-200) |
| --src-icon-info | var(--src-color-primary-500) |
| --src-icon-info-hover | var(--src-color-primary-400) |
| --src-icon-success | var(--src-color-green-500) |
| --src-icon-success-hover | var(--src-color-green-400) |
| --src-icon-error | var(--src-color-red-400) |
| --src-icon-error-hover | var(--src-color-red-300) |
| --src-icon-warning | var(--src-color-tertiary-400) |
| --src-icon-warning-hover | var(--src-color-tertiary-300) |
| --src-icon-attention | var(--src-color-yellow-400) |
| --src-icon-attention-hover | var(--src-color-yellow-600) |
| --src-graphics-positive | var(--src-color-green-400) |
| --src-graphics-negative | var(--src-color-red-400) |
| --src-graphics-accent | var(--src-color-primary-500) |
| --src-graphics-dark-grey | var(--src-color-grey-400) |
| --src-graphics-orange | #ffb92dff |
| --src-graphics-yellow | #f0e442ff |
| --src-graphics-turquoise | #00ced1ff |
| --src-graphics-brown | #8b4513ff |
| --src-graphics-black | var(--src-color-grey-200) |
| --src-text-body-accent | var(--src-color-primary-400) |
| --src-text-body-success | var(--src-color-green-400) |
| --src-text-body-destruct | var(--src-color-red-400) |
| --src-text-ui-primary-main | var(--src-light) |
| --src-text-ui-primary-secondary | var(--src-color-grey-200) |
| --src-text-ui-primary-disabled | var(--src-color-grey-400) |
| --src-text-ui-primary-main-invert | var(--src-color-grey-900) |
| --src-text-ui-primary-secondary-invert | var(--src-color-grey-700) |
| --src-text-ui-secondary-main | var(--src-color-grey-50) |
| --src-text-ui-secondary-secondary | var(--src-color-grey-200) |
| --src-text-ui-secondary-grey | var(--src-color-grey-400) |
| --src-text-ui-secondary-disabled | var(--src-color-grey-500) |
| --src-text-ui-secondary-main-invert | var(--src-color-grey-900) |
| --src-text-ui-secondary-secondary-invert | var(--src-color-grey-600) |
| --src-shadow-hard | var(--src-color-alpha-dark-100) |
| --src-shadow-light | var(--src-color-alpha-dark-50) |
| --src-shadow-accent-light | var(--src-color-alpha-accent-300) |
| --src-shadow-accent-hard | var(--src-color-alpha-accent-400) |
| --src-shadow-success | var(--src-color-alpha-success-200) |
| --src-shadow-success-hover | var(--src-color-alpha-success-50) |
| --src-shadow-error | var(--src-color-alpha-destruct-200) |
| --src-shadow-error-hover | var(--src-color-alpha-destruct-100) |
| --src-text-ui-accent-main | var(--src-color-primary-400) |
| --src-text-ui-accent-hover | var(--src-color-primary-300) |
| --src-text-ui-success-main | var(--src-color-green-400) |
| --src-text-ui-success-hover | var(--src-color-green-300) |
| --src-text-ui-distruct-main | var(--src-color-red-400) |
| --src-text-ui-distruct-hover | var(--src-color-red-300) |
| --src-surface-container-main | var(--src-color-grey-800) |
| --src-surface-container-on-top | var(--src-color-alpha-white-10) |
| --src-surface-container-secondary | var(--src-color-basic-black) |
| --src-surface-container-info | var(--src-color-blue-950) |
| --src-surface-container-success | var(--src-color-green-950) |
| --src-surface-container-error | var(--src-color-red-950) |
| --src-surface-toast-basic | var(--src-color-alpha-default-200) |
| --src-surface-toast-info | var(--src-color-primary-400) |
| --src-surface-toast-success | var(--src-color-green-400) |
| --src-surface-toast-error | var(--src-color-red-400) |
| --src-border-infoPrompt-basic | var(--src-color-grey-800) |
| --src-border-infoPrompt-light | var(--src-color-alpha-white-50) |
| --src-border-infoPrompt-info | var(--src-color-primary-800) |
| --src-border-infoPrompt-success | var(--src-color-green-800) |
| --src-border-infoPrompt-error | var(--src-color-red-800) |
| --src-gradient-light-start | var(--src-color-alpha-dark-200) |
| --src-gradient-light-end | var(--src-color-alpha-dark-100) |
| --src-gradient-accent-light | var(--src-color-alpha-accent-300) |
| --src-gradient-accent-hard | var(--src-color-alpha-accent-400) |
| --src-gradient-success | var(--src-color-alpha-success-200) |
| --src-gradient-success-hover | var(--src-color-alpha-success-50) |
| --src-gradient-error | var(--src-color-alpha-destruct-200) |
| --src-gradient-error-hover | var(--src-color-alpha-destruct-100) |
| --src-tech-sticker | var(--src-color-tertiary-800) |
| --wireframe-main | var(--src-color-neutral-300) |
| --wireframe-secondary | var(--src-color-neutral-400) |
| --wireframe-light | var(--src-color-neutral-500) |
| --wireframe-surface-primary | var(--src-dark) |
| --wireframe-surface-secondary | var(--src-color-alpha-white-50) |
| --wireframe-border | var(--src-color-alpha-white-100) |
| --wireframe-invert | var(--src-dark) |
| --src-tech-description | var(--src-color-tertiary-50) |
| --src-light | #ffffffff |
| --src-dark | #ffffffff |
| --src-ui-status-basic-neutral | var(--src-color-alpha-white-100) |
| --src-ui-status-basic-neutral-hover | var(--src-color-alpha-white-600) |
| --src-ui-status-basic-critical | var(--src-color-alpha-success-100) |
| --src-ui-status-basic-critical-hover | var(--src-color-alpha-success-50) |
| --src-ui-status-basic-info | var(--src-color-alpha-accent-300) |
| --src-ui-status-basic-info-hover | var(--src-color-alpha-accent-200) |
| --src-ui-status-basic-success | var(--src-color-alpha-success-200) |
| --src-ui-status-basic-success-hover | var(--src-color-alpha-success-100) |
| --src-ui-status-basic-warning | var(--src-color-alpha-warning-300) |
| --src-ui-status-basic-warning-hover | var(--src-color-alpha-warning-200) |
| --src-ui-status-basic-attention | var(--src-color-alpha-attention-300) |
| --src-ui-status-basic-attention-hover | var(--src-color-alpha-attention-200) |
| --src-ui-status-light-neutral | var(--src-color-alpha-white-100) |
| --src-ui-status-light-neutral-hover | var(--src-color-alpha-white-600) |
| --src-ui-status-light-critical | var(--src-color-alpha-success-100) |
| --src-ui-status-light-critical-hover | var(--src-color-alpha-success-50) |
| --src-ui-status-light-info | var(--src-color-alpha-accent-300) |
| --src-ui-status-light-info-hover | var(--src-color-alpha-accent-200) |
| --src-ui-status-light-success | var(--src-color-alpha-success-200) |
| --src-ui-status-light-success-hover | var(--src-color-alpha-success-100) |
| --src-ui-status-light-warning | var(--src-color-alpha-warning-300) |
| --src-ui-status-light-warning-hover | var(--src-color-alpha-warning-200) |
| --src-ui-status-light-attention | var(--src-color-alpha-attention-300) |
| --src-ui-status-light-attention-hover | var(--src-color-alpha-attention-200) |
| --src-text-ui-warning-main | var(--src-color-tertiary-400) |
| --src-text-ui-warning-hover | var(--src-color-tertiary-500) |
| --src-text-ui-attention-main | var(--src-color-tertiary-200) |
| --src-text-ui-attention-hover | var(--src-color-tertiary-100) |

### typeface (scope: global)
Source: `variables/typeface/web.scss`

| Token | Value |
|-------|-------|
| --src-font-family-header | Inter |
| --src-font-family-body | Inter |
| --src-font-family-mono | PT Mono |
| --src-font-weight-bold | Bold |
| --src-font-weight-semiBold | SemiBold |
| --src-font-weight-medium | Medium |
| --src-font-weight-regular | Regular |
| --src-font-size-tech | 9px |
| --src-font-size-xs | 12px |
| --src-font-size-sm | 14px |
| --src-font-size-base | 16px |
| --src-font-size-md | 20px |
| --src-font-size-lg | 24px |
| --src-font-size-xl | 28px |
| --src-font-size-2xl | 32px |
| --src-font-size-3xl | 40px |
| --src-font-line-tech | 12px |
| --src-font-size-4xl | 48px |
| --src-font-line-xs | 16px |
| --src-font-line-sm | 20px |
| --src-font-line-base | 24px |
| --src-font-line-md | 28px |
| --src-font-line-lg | 32px |
| --src-font-line-xl | 36px |
| --src-font-line-2xl | 44px |
| --src-font-line-3xl | 52px |
| --src-font-line-4xl | 56px |
| --src-font-spacing-tech | 1.2000000476837158px |
| --src-font-spacing-xl | -0.20000000298023224px |
| --src-font-spacing-2xl | -0.30000001192092896px |
| --src-font-spacing-3xl | -0.5px |
| --src-font-spacing-4xl | -1px |

### ui-md (scope: global)
Source: `variables/ui/_md.scss`

| Token | Value |
|-------|-------|
| --src-media-thumbnail | 48px |
| --src-media-preview | 1024px |
| --src-padding-xs | var(--src-space-2) |
| --src-padding-sm | var(--src-space-3) |
| --src-padding-md | var(--src-space-4) |
| --src-padding-lg | var(--src-space-5) |
| --src-padding-xl | var(--src-space-7) |
| --src-height-xs | var(--src-space-4) |
| --src-icon-size | var(--src-space-5) |
| --src-icon-line-width | 1.440000057220459px |
| --src-height-sm | var(--src-space-5) |
| --src-border-border | 1px |
| --src-border-rounded-none | 0px |
| --src-height-base | var(--src-space-9) |
| --src-height-lg | 52px |
| --src-border-rounded-xs | var(--src-space-1) |
| --src-border-rounded | var(--src-space-1-5) |
| --src-border-rounded-parent | var(--src-space-2-5) |
| --src-border-rounded-lg | var(--src-space-4) |
| --src-border-rounded-full | 9999px |
| --src-gap-md | var(--src-space-1-5) |
| --src-text-lineHeight | var(--src-font-line-sm) |
| --src-gap-xl | var(--src-space-3-5) |
| --src-text-fontSize | var(--src-font-size-sm) |
| --src-text-weight-base | var(--src-font-weight-medium) |
| --src-gap-lg | var(--src-space-2-5) |
| --src-gap-none | 0px |
| --src-gap-sm | var(--src-space-1) |
| --src-text-weight-bold | var(--src-font-weight-bold) |
| --src-text-weight-medium | var(--src-font-weight-semiBold) |
| --src-shadow-focused | var(--src-space-1) |
| --src-shadow-ambient-inner | -1px |
| --src-shadow-ambient-inner-light | 1px |
| --src-shadow-ambient-outer | 1px |
| --src-shadow-blur | 1px |

### layout-md (scope: @media (min-width: 768px))
Source: `variables/layout/_md.scss`

| Token | Value |
|-------|-------|
| --src-layout-padding-const-xs | var(--src-space-1) |
| --src-layout-padding-const-sm | var(--src-space-2) |
| --src-layout-padding-const-md | var(--src-space-3) |
| --src-layout-padding-const-lg | var(--src-space-4) |
| --src-layout-padding-const-xl | var(--src-space-6) |
| --src-layout-padding-const-2xl | var(--src-space-8) |
| --src-layout-padding-var-xs | var(--src-space-2) |
| --src-layout-padding-table-sm | var(--src-space-3) |
| --src-layout-padding-var-sm | var(--src-space-3) |
| --src-layout-padding-var-md | var(--src-space-4) |
| --src-layout-padding-var-lg | var(--src-space-5) |
| --src-layout-padding-var-xl | var(--src-space-8) |
| --src-layout-padding-var-2xl | var(--src-space-11) |
| --src-layout-gap-const-none | 0px |
| --src-layout-gap-const-xs | var(--src-space-1) |
| --src-layout-gap-const-sm | var(--src-space-2) |
| --src-layout-gap-const-md | var(--src-space-3) |
| --src-layout-gap-const-lg | var(--src-space-4) |
| --src-layout-gap-const-xl | var(--src-space-6) |
| --src-layout-gap-const-2xl | var(--src-space-8) |
| --src-layout-gap-var-none | 0px |
| --src-layout-gap-var-sm | var(--src-space-2) |
| --src-layout-gap-var-md | var(--src-space-3) |
| --src-layout-gap-var-lg | var(--src-space-4) |
| --src-layout-gap-var-xl | var(--src-space-8) |
| --src-layout-height-const-sm | var(--src-space-7) |
| --src-layout-height-const-md | var(--src-space-8) |
| --src-layout-height-const-lg | var(--src-space-9) |
| --src-layout-height-const-h-xl | var(--src-space-10) |
| --src-layout-height-const-h-2xl | var(--src-space-16) |
| --src-layout-height-var-xs | var(--src-space-8) |
| --src-layout-height-var-sm | var(--src-space-10) |
| --src-layout-height-var-base | var(--src-space-20) |
| --src-layout-height-var-md | var(--src-space-28) |
| --src-layout-height-var-lg | var(--src-space-24) |
| --src-layout-height-var-xl | var(--src-space-36) |
| --src-layout-radius-var-rounded-kid | var(--src-space-2) |
| --src-layout-radius-var-rounded-parent | var(--src-space-3) |
| --src-layout-radius-rounded-none | 0px |
| --src-layout-border-border | 1px |
| --src-layout-table-height | var(--src-space-14) |
| --src-layout-radius-const-rounded-sm | var(--src-space-1-5) |
| --src-layout-radius-const-rounded | var(--src-space-2) |
| --src-layout-radius-const-rounded-md | var(--src-space-3) |
| --src-layout-radius-const-rounded-lg | var(--src-space-4) |
| --src-layout-radius-const-rounded-xl | var(--src-space-6) |
| --src-layout-radius-const-rounded-2xl | var(--src-space-8) |
| --src-layout-radius-rounded-ui-full | 9999px |
| --src-shadow-basic | var(--src-space-1-5) |
| --src-graphs-label | var(--src-space-2) |
| --src-graphs-label-var | var(--src-space-2-5) |
| --src-graphs-height-label-var | var(--src-space-7) |
| --src-graphs-height-label-const | var(--src-space-5) |
| --src-graphs-height-s | var(--src-space-8) |
| --screen-width | 768px |
| --card-width | 320px |
| --preview-width | 216px |
| --src-typography-var-p-sm-fontSize | var(--src-font-size-sm) |
| --src-typography-var-p-sm-weight | var(--src-font-weight-regular) |
| --src-typography-var-p-sm-lineHeight | var(--src-font-line-sm) |
| --src-typography-var-p-md-fontSize | var(--src-font-size-base) |
| --src-typography-var-p-md-weight | var(--src-font-weight-regular) |
| --src-typography-var-p-md-lineHeight | var(--src-font-line-base) |
| --src-typography-var-h-sm-fontSize | var(--src-font-size-md) |
| --src-typography-var-h-sm-weight | var(--src-font-weight-semiBold) |
| --src-typography-var-h-sm-lineHeight | var(--src-font-line-md) |
| --src-typography-var-h-md-fontSize | var(--src-font-size-lg) |
| --src-typography-var-h-md-weight | var(--src-font-weight-semiBold) |
| --src-typography-var-h-md-lineHeight | var(--src-font-line-lg) |
| --src-typography-var-h-lg-fontSize | var(--src-font-size-xl) |
| --src-typography-var-h-lg-weight | var(--src-font-weight-semiBold) |
| --src-typography-var-h-lg-lineHeight | var(--src-font-line-xl) |
| --src-typography-var-h-xl-fontSize | var(--src-font-size-3xl) |
| --src-typography-var-h-xl-weight | var(--src-font-weight-semiBold) |
| --src-typography-var-h-xl-lineHeight | var(--src-font-line-3xl) |
| --src-typography-var-p-lg-fontSize | var(--src-font-size-lg) |
| --src-typography-var-p-lg-weight | var(--src-font-weight-regular) |
| --src-typography-var-p-lg-lineHeight | var(--src-font-line-lg) |

## Demo site

- [Live demo site](https://preview.3dsource.com/front-libraries/master/): Interactive examples of all components with live code snippets (uses HashLocationStrategy — routes like `/#/components/SourceButtonComponent`)

## Optional

- [Full component registry JSON](./docs/api/_registry.json): Machine-readable index for programmatic discovery
