# @3dsource/source-ui-native > All local file paths in this document are relative to the package root (`@3dsource/source-ui-native/`). > Lightweight UI primitives with no Angular or RxJS package dependencies (only `tslib`). Can be used in any project (React, Vue, plain HTML, Lovable, etc.) by importing just the compiled CSS stylesheet. Applications using the Angular components provide Angular and RxJS themselves. Angular components use signals API (`input()`, `output()`), `OnPush` change detection, `ViewEncapsulation.None`, and CSS custom properties (`--src-*`) for theming. For breadcrumbs, color picker, popover, slider group, tab line, tooltip, the CDK modal, styled Angular Material form fields and ngx-toastr toasts, see the companion library `@3dsource/source-ui`. Rules that apply to every task — the guides below explain each one: - Import the stylesheet first: `@use '../node_modules/@3dsource/source-ui-native/styles/source.ui.native.scss' as source-ui-native;` in Angular, or `@3dsource/source-ui-native/styles/source-ui-native.min.css` anywhere else. Use only the documented paths. - Put the `section_3dsourcecom` class on the element that wraps the whole app (never on ``); add `section_3dsourcecom--dark` beside it for the dark theme. - Native modals need `` once in the root component's template. - Use default input values (size, appearance, weight, context) unless asked otherwise. Where both a component (``) and an element class (`.src-button`) exist, either works: keep to the form the project already uses. Layout and form plumbing (`src-form`, `src-label`, `src-list`) exist only as element classes. - Style only with `--src-*` design tokens and `src-*` classes: no Tailwind or other utility CSS, no `all: unset`, no invented token names. - Customize a component in this order: inputs first, then its camelCase custom properties (like `--srcDividerColor`) on the inner `.src-*` element (`.src-divider { ... }` in global styles or `.my-block ::ng-deep .src-divider { ... }` in a component; on the component tag they have no effect), and plain CSS overrides only when both are not enough. - Use SVG icons with `fill="currentColor"`; never the Material Icons font or the `material-icons` class. `` in the examples is an icon component that the app creates, as [Icons](./guides/icons.md) shows; the library has none. - Bind test ids as a property: `[data-testid]="'save'"`, not `data-testid="save"`. ## Setup Complete these steps when adding Source UI to a new app. Order matters — nothing renders correctly without steps 1 and 2. 1. **Import the stylesheet.** Use only the two files below. The SCSS entry uses dots (`source.ui.native.scss`), the compiled CSS uses dashes (`source-ui-native.min.css`). For Angular projects, add to `styles.scss`: ```scss @use '../node_modules/@3dsource/source-ui-native/styles/source.ui.native.scss' as source-ui-native; ``` The path is relative to the importing file: from `src/styles.scss` it is `../node_modules/...`. Add `../` until it reaches `node_modules`, e.g. `../../../node_modules/...` from `projects/app/src/styles.scss`. For non-Angular / CSS-only projects, link `node_modules/@3dsource/source-ui-native/styles/source-ui-native.min.css` from ``, or import it in your bundler by package specifier: `import '@3dsource/source-ui-native/styles/source-ui-native.min.css';` (the package `exports` map exposes `./styles/*`, and CSS/SCSS files are declared as side effects, so bundlers keep the import). In a TypeScript file, if `tsc` reports TS2882 for this import, add `declare module '*.css';` to a `.d.ts` file. 2. **Add the `section_3dsourcecom` root class.** Put it on an element that wraps your whole app — inner `` wrapper, a root `
`, or `` as a last resort. NOT on ``. Example: ```html ... ``` Without this class the base reset, typography, scrollbar styles and the page background (`--src-surface-background`) do not apply. Design tokens (declared on `:root`) and element classes are global, but the reset this class scopes also sets `box-sizing: border-box`. Without the class, elements with `width: 100%` and padding grow wider than their container (a `.src-input` in a 300px box renders 322px wide), so always add it. 3. **Place `` in the root component's template** if the app uses the native modal (`SourceModalNativeService`). Angular only creates components inside the root component, so the tag does nothing in `index.html`. Add `SourceOverlayContainerComponent` (from `@3dsource/source-ui-native`) to the root component's `imports` and the tag once, at the end of its template: ```html
``` `SourceModalNativeService.open(...)` attaches into this container; without it, `open()` throws "SourceOverlayContainerComponent is not registered". No other API currently uses this container (popovers, CDK Dialog, and ngx-toastr all bypass it). If the app disables CDK popovers (`{ provide: OVERLAY_DEFAULT_CONFIG, useValue: { usePopover: false } }`), also provide `{ provide: SOURCE_MODAL_USE_TOP_LAYER, useValue: false }` from `@3dsource/source-ui-native`. Otherwise CDK overlays (for example `mat-select`) opened inside a native modal render behind it: the modal sits in the browser top layer, the overlays do not. 4. **(Optional) Enable dark theme.** Add `section_3dsourcecom--dark` alongside `section_3dsourcecom` to switch to dark tokens. Both light and dark token sets are bundled — no extra import. Toggle by adding/removing the `--dark` class at runtime. CDK overlays (the CDK modal, popover, tooltip, Material panels from `@3dsource/source-ui`) render outside that element, so also add `cdk-overlay-container--dark` to the CDK overlay container while the dark theme is on. 5. **(If using `@3dsource/source-ui`)** Install it as a peer of `@3dsource/source-ui-native` and follow the [@3dsource/source-ui setup guide](../source-ui/guides/setup.md) for Angular Material / CDK prerequisites (providers). ## Key concepts - All components use the `src-` selector prefix (e.g. ``, ``) - Angular component imports: `import { SourceButtonComponent } from '@3dsource/source-ui-native'` or `import { SourcePopoverTriggerComponent } from '@3dsource/source-ui'`. All components are exported from the package root — no deep import paths. - 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 `--src-*` CSS custom properties: [Design tokens](#design-tokens). - Every component with a `testID` input binds it to the rendered element as `data-testid` (`` takes it as `data.testID` in the modal config; `` has none). Bind it as a property, `[data-testid]="'save'"`: a static `data-testid="save"` also stays on the host element, so tests find two elements. - 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): [Using Source Elements](#using-source-elements). - Modals use the native ``: open them with `SourceModalNativeService.open(component, config)`. Pass `SourceModalNativeComponent` for the built-in chrome, `SourceModalComponent` from `@3dsource/source-ui` for the CDK chrome, or your own component. Prefer it over the CDK `Dialog` for new code. Old names `SourceModalElement*` are deprecated aliases of `*Native*`. - Never put `` in a template: open it only through `SourceModalNativeService`. - Every footer button closes the modal with the value its `action()` returns. For forms or validation, open a custom component. - `afterClosed()` emits that value, or `undefined` after Esc, a backdrop click or the header close button. - A custom component template starts with `.src-modal`: the service already provides the ``. - Examples and all fields: [SourceModalNativeComponent API](./docs/components/modal-native.md). - Where to put the `section_3dsourcecom` root class and how to turn on the dark theme: [Setup](#setup), steps 2 and 4. - **Customizing a component**, in this order: 1. Its inputs (`size`, `appearance`, `context` and so on). 2. Its custom properties (camelCase, like `--srcDividerColor`). They are declared on the component's inner `.src-*` element, so a value set on the component tag or on a parent is replaced there. Override them on that element: `.src-divider { --srcDividerLength: 120px; }` in global styles, or `.my-block ::ng-deep .src-divider { --srcDividerLength: 120px; }` in your component. 3. Plain CSS rules, only if the first two are not enough. - **Scrollbar**: global scrollbar styling is applied automatically (`scrollbar-width: thin`). Override `--srcScrollbarThumbColor` and `--srcScrollbarTrackColor` on the `section_3dsourcecom` element or on any element inside it; above it they have no effect, because that class declares them. - 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.). - STRICT RULE: Do NOT use `all: unset` to reset browser defaults. It also unsets `box-sizing: border-box` and causes layout bugs. Reset defaults explicitly (e.g. `appearance: none; background: none; border: none; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer;`). ## Components Before building custom UI, always search for an existing Source UI component or Source Element with the same semantic meaning. Only create new components as a last resort. If a user asks for "a button", "a card", "a table row", "a sidebar item", etc: 1. Search for an existing component with the same meaning 2. If exact match is missing, pick the closest semantic match 3. Only create new components as a last resort - **Angular Components** (require Angular): badge, banner, button, copyright, divider, hint, icon-button, loading, logo-loading, modal-native, overlay-container, slider, tile - **Source Elements (CSS-only, no Angular needed)**: badge, banner, breadcrumbs, button, button-group, checkbox, divider, form, hint, icon-button, input, label, list, modal, radio, select, textarea, tile, toggle, toolbar — pure CSS classes applied to standard HTML elements ## Using Source Elements Source Elements let you style standard HTML elements (` ``` ### Icon design tokens - `--src-icon-size` — default icon size (20px, `var(--src-space-5)`) - `--src-icon-default`, `--src-icon-info`, `--src-icon-success`, `--src-icon-error`, `--src-icon-warning` — contextual icon colors ## Design Tokens (inline) > Auto-generated from 1029 total tokens. Below is a curated subset of semantic tokens most useful for development. Full token data: one file per category in docs/tokens/. ### 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(--src-color-alpha-warning-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(--src-color-alpha-success-50) | | --src-gradient-success-hover | var(--src-color-alpha-success-200) | | --src-gradient-error | var(--src-color-alpha-destruct-100) | | --src-gradient-error-hover | var(--src-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: .section_3dsourcecom--dark, .cdk-overlay-container--dark) Source: `variables/color/dark.scss` | Token | Value | |-------|-------| | --src-surface-background | var(--src-color-grey-900) | | --src-surface-background-inverse | var(--src-color-grey-50) | | --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-warning-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-500) | | --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-grey-950) | | --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 | #000000ff | | --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-destruct-100) | | --src-ui-status-basic-critical-hover | var(--src-color-alpha-destruct-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-destruct-200) | | --src-ui-status-light-critical-hover | var(--src-color-alpha-destruct-100) | | --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-height-base | var(--src-space-9) | | --src-border-rounded-none | 0px | | --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-none | 0px | | --src-gap-lg | var(--src-space-2-5) | | --src-text-weight-base | var(--src-font-weight-medium) | | --src-text-lineHeight | var(--src-font-line-sm) | | --src-text-fontSize | var(--src-font-size-sm) | | --src-gap-md | var(--src-space-1-5) | | --src-gap-xl | var(--src-space-3-5) | | --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) | ## Theming: Custom Accent Colors **Beta.** Custom accent theming is in beta: the palette algorithm and the override approach may change. The accent color palette drives all primary interactive elements (buttons, selections, focus rings, links). You can override the default blue (`#017BFF`) with any brand color. ### How accent colors work 1. **Primitives** define the raw palette in `primitives/primitives.scss`: - `--src-color-primary-50` through `--src-color-primary-950` (11 shades) - `--src-color-alpha-accent-10` through `--src-color-alpha-accent-400` (6 alpha variants) 2. **Semantic tokens** in `color/light.scss` and `color/dark.scss` reference the primitives: - `--src-ui-accent-default: var(--src-color-primary-500)` (primary action color) - `--src-ui-accent-default-hover: var(--src-color-primary-600)` (hover state) - `--src-ui-secondary-active: var(--src-color-alpha-accent-50)` (selected backgrounds) - etc. 3. **You only override primitives** — semantic mappings stay intact, so all components update automatically. ### Agent instruction: Override accent color To change the accent color to a custom brand color (e.g. `#FF5722`): 1. Create `_accent-override.scss` in the user's project (NOT in the library): ```scss /* _accent-override.scss */ /* Custom accent color palette — override Source UI default blue */ /* Generated from base color: #FF5722 */ :root { /* primary shades (50=lightest, 950=darkest) */ --src-color-primary-50: #ffece5ff; --src-color-primary-100: #ffd0c2ff; --src-color-primary-200: #ffaa8fff; --src-color-primary-300: #ff835cff; --src-color-primary-400: #ff5c29ff; --src-color-primary-500: #ff5722ff; /* your base color */ --src-color-primary-600: #ff4408ff; --src-color-primary-700: #e43700ff; --src-color-primary-800: #c52f00ff; --src-color-primary-900: #922300ff; --src-color-primary-950: #551400ff; /* Alpha variants (for backgrounds, hover states) */ /* Format: base color (#FF5722) + alpha hex suffix */ --src-color-alpha-accent-10: #ff572214; --src-color-alpha-accent-50: #ff57221f; --src-color-alpha-accent-100: #ff572229; --src-color-alpha-accent-200: #ff57223d; --src-color-alpha-accent-300: #ff572252; --src-color-alpha-accent-400: #ff57225c; } ``` 2. Import it in `styles.scss` AFTER the Source UI stylesheets: ```scss @use '../node_modules/@3dsource/source-ui-native/styles/source.ui.native.scss' as source-ui-native; @use './accent-override'; // ← after library styles ``` In a CSS-only project, put the same `:root` block in a `.css` file loaded after `source-ui-native.min.css`. ### Palette generation algorithm From a single base hex color, generate the 50–950 scale using HSL lightness steps: | Shade | Lightness target | | ----- | ------------------------------------ | | 50 | 95% | | 100 | 88% | | 200 | 78% | | 300 | 68% | | 400 | 58% | | 500 | Base color (keep original lightness) | | 600 | Base lightness − 5% | | 700 | Base lightness − 12% | | 800 | Base lightness − 18% | | 900 | Base lightness − 28% | | 950 | Base lightness − 40% | Alpha variants use the base 500 color with these hex alpha suffixes: - `10` → `14` (8% opacity) - `50` → `1f` (12% opacity) - `100` → `29` (16% opacity) - `200` → `3d` (24% opacity) - `300` → `52` (32% opacity) - `400` → `5c` (36% opacity) ### Rules - **NEVER modify** `primitives.scss`, `light.scss`, or `dark.scss` in the library - **NEVER modify** semantic tokens — they reference primitives automatically - The override file MUST be loaded AFTER the library stylesheet - All 11 shades (50–950) and 6 alpha variants must be defined for full coverage - Suffix `ff` on hex colors = fully opaque; alpha variants use partial opacity suffixes ## Component API reference (inline) > Full API for every component inlined below. No external links needed. ### SourceBadgeComponent (@3dsource/source-ui-native) **Selector:** `src-badge` · **Kind:** Component **Usage:** ```html Active 3 Beta 12% 5 ``` **Inputs:** | Input | Type | Default | Values | Required | Description | |-------|------|---------|--------|----------|-------------| | backgroundColor | string | "var(--src-ui-accent-default, #017bffff)" | — | no | Background color of the badge. Applies only when `context` is not set: any `context`, including `'default'`, uses its own colors. Without `context` the badge is accent blue. | | context | SourceBadgeContextKeys | — | default, info, success, warning, attention, error | no | Defines the context of the badge (e.g. status). | | size | SourceBadgeSizeKeys | "md" | sm, md, lg, xl | no | Size of the badge. | | textColor | string | "var(--src-text-body-main-invert, #f9fafbff)" | — | no | Text color inside the badge. Applies only when `context` is not set. | | customClass | string \| string[] | — | — | no | Custom class(es) to apply to the badge. | | testID (alias: data-testid) | string | "" | — | no | Test ID for querying the badge in tests. | | role | string \| null | "status" | — | no | ARIA role for the badge, with a default of "status" for accessibility. | | ariaLabel | string | — | — | no | ARIA label for the badge, used for accessibility. | ### SourceBannerComponent (@3dsource/source-ui-native) **Selector:** `src-banner` · **Kind:** Component **Usage:** ```html
Attention
Your session will expire in 5 minutes.
Your trial ends in 3 days.
Payment failed
Check your card details and try again.
{{ syncStatus() }} ``` **Inputs:** | Input | Type | Default | Values | Required | Description | |-------|------|---------|--------|----------|-------------| | context | SourceBannerContextKeys | "default" | default, info, success, warning, critical, error | no | Defines the banner context. | | size | SourceBannerSizeKeys | "sm" | sm, md, lg, xl | no | Size of the banner. | | isFullWidth | boolean | true | — | no | If true, the banner will take the full width of its container. | | testID (alias: data-testid) | string | "" | — | no | Test ID for querying the banner in tests. | | role | string | — | — | no | ARIA role for the banner, used for accessibility (e.g. "region", "alert"). | | ariaLive | 'polite' \| 'assertive' \| 'off' | — | — | no | ARIA live region setting for the banner, used for accessibility to indicate how updates should be announced. | ### SourceButtonComponent (@3dsource/source-ui-native) **Selector:** `src-button` · **Kind:** Component **Usage:** ```html Save changes Cancel Delete
Save profile Actions Help ``` **Inputs:** | Input | Type | Default | Values | Required | Description | |-------|------|---------|--------|----------|-------------| | type | SourceButtonTypeKeys | "button" | button, submit, reset | no | Type of the inner `
Edit user
...your form...
// Mode 3: source-ui chrome through the native service (needs @3dsource/source-ui) import { SourceModalComponent } from '@3dsource/source-ui'; this.modalService.open(SourceModalComponent, { data: { headerTitle: 'Saved', footerButtons: [{ label: 'OK', action: () => 'ok' }] }, }); ``` **SourceModalData:** | Field | Type | Required | Description | |-------|------|----------|-------------| | headerTitle | string | no | Title rendered in the modal body. | | closeButton | boolean | no | Renders a close (×) button in the top-right of the header. | | closeButtonAriaLabel | string | no | ARIA label for the icon-only close button. Defaults to 'Close'. | | context | SourceModalContextKeys | no | Visual context ('default' \| 'info' \| 'success' \| 'warning' \| 'error'). Renders a colored icon next to the title. | | content | string | no | HTML string rendered via [innerHTML] inside src-modal__scroll-box. The wrapper is rendered only when content is provided. | | footerButtons | DialogButtonsData \| DialogButtonsData[] | no | Footer buttons. Pass a flat array for one group, or an array of arrays for multiple groups (groups are spaced apart in the footer). Each button closes the modal with the value its action() returns, so a footer button cannot keep the modal open. For forms, use a custom component. | | testID | string | no | data-testid value applied to the modal root and composed into inner selectors (e.g. '-header-close'). | **Service — SourceModalNativeService:** - `open(component: Type, config: SourceModalConfig): SourceModalRef` — Opens `component` inside a native `` and returns a ref. `config.data` is injected via `SOURCE_MODAL_DATA` for the projected component; the rest of `config` (aria-* fields, role, panelClass, sizing) is applied to the dialog wrapper. Requires `` in the app root. Never use the tag in a template. In browsers without the Popover API, or with SOURCE_MODAL_USE_TOP_LAYER set to false, the dialog opens with show() instead of showModal(). `width` sizes the dialog wrapper, as in CDK; to resize the `.src-modal` card, set `--srcModalWidth` on it. **SourceModalRef:** Handle returned by SourceModalNativeService.open(). Custom components inject SOURCE_MODAL_REF to access this ref and close the modal with a result. | Method | Description | |--------|-------------| | `close(result?: R)` | Closes the dialog and completes both `closed` and `afterClosed()` with the result. Idempotent — second call is a no-op. | | `afterClosed(): Observable` | Observable that emits the close result once and completes. It emits undefined after Esc, a backdrop click or the header close button. | | `closed: Observable` | Same stream as `afterClosed()` exposed as a property — provides CDK-style ergonomics (`ref.closed.subscribe(...)`). | | `data: D` | The `data` payload that was passed in the config — same value as injecting SOURCE_MODAL_DATA from inside the projected component. | ### SourceOverlayContainerComponent (@3dsource/source-ui-native) **Selector:** `src-overlay-container` · **Kind:** Component **Usage:** ```html
``` ### SourceSliderComponent (@3dsource/source-ui-native) **Selector:** `src-slider` · **Kind:** Component **Usage:** ```html
``` **Inputs:** | Input | Type | Default | Values | Required | Description | |-------|------|---------|--------|----------|-------------| | id | string | — | — | no | ID of the input to connect the label and input[type=range]. | | value | number | — | — | yes | The value of the slider. | | min | number | — | — | yes | The minimum value of the range. | | max | number | — | — | yes | The maximum value of the range. | | thumbSize | number | 16 | — | no | The size of the thumb. | | trackHeight | number | 4 | — | no | The height of the visual track. The height of the input will not be affected. | | step | number | 1 | — | no | The step size of the slider. | | showTicks | boolean | false | — | no | Whether to show ticks at each step. | | isDisabled | boolean | false | — | no | Whether the slider is disabled. | | orientation | 'horizontal' \| 'vertical' | "horizontal" | — | no | Orientation of the slider. `'vertical'` rotates the horizontal slider with a CSS transform, so its layout box stays horizontal: give its container the height the slider needs. The minimum is at the bottom. | | testID (alias: data-testid) | string | "" | — | no | Test ID for querying the slider in tests. | | ariaLabel | string | — | — | no | ARIA label for the slider, used when there is no visible label. | | ariaValueText | string | — | — | no | Custom text representation of the current value (e.g., 50C instead of 50). | **Outputs:** | Output | Type | Description | |--------|------|-------------| | onChange | number | Optional change event handler. | | onInput | number | Optional input event handler. | ### SourceTileComponent (@3dsource/source-ui-native) **Selector:** `src-tile` · **Kind:** Component **Usage:** ```html Material preview
Oak wood
Oak wood
Oak wood
Oak wood
Oak wood
Maple
Maple
Walnut
Walnut
Living room scene
Living room with oak floor and walnut furniture
Maple
Maple
Walnut
Walnut
``` **Inputs:** | Input | Type | Default | Values | Required | Description | |-------|------|---------|--------|----------|-------------| | width | string | — | — | no | CSS width of the tile container (e.g. '92px', '100%'). When omitted the tile fills its parent. | | counter | string | — | — | no | Text displayed in the counter badge overlay on the image (e.g. '+3'). | | counterPlacement | SourceTileCounterPlacementKeys | "center" | top-right, top-left, bottom-right, bottom-left, center | no | Position of the counter badge within the image area. | | aspectRatio | string | "1/1" | — | no | CSS aspect-ratio of the image area (e.g. '1/1', '6/5'). | | titleLineClamp | number | — | — | no | Maximum number of visible title lines before text is clamped with ellipsis. | | isInteractive | boolean | true | — | no | When false the tile has no hover/active feedback and uses a default cursor. | | isActive | boolean | — | — | no | Applies the active/selected visual state with accent border and shadow. | | isDisabled | boolean | — | — | no | Dims the tile and disables all pointer events. | | isLoading | boolean | — | — | no | Shows a loading overlay with a spinner on top of the image area. | | testID (alias: data-testid) | string | "" | — | no | Sets a data-testid attribute on the root element for testing. | ## Source Elements (CSS-only styling) CSS-only Source Elements — BEM classes applied to native HTML tags. No Angular imports needed. Requires source.ui.native.scss stylesheet. Stylesheet: `@3dsource/source-ui-native/styles/source-ui-native.min.css` Use Source Elements when: you don't need Angular signal bindings, you want minimal overhead, or you're prototyping without Angular. ### Badge Element Status badge. Use for labels, tags, and status indicators. **Core class:** `src-badge` — Inline-flex pill badge for status labels and tags. **Usage:** ```html Active 3 ``` **Size modifiers:** - `src-badge--size-sm` — Small size for the badge. - `src-badge--size-md` (default) — Default size for the badge. - `src-badge--size-lg` — Large size for the badge. - `src-badge--size-xl` — Extra large size for the badge. **Context modifiers:** - `src-badge--context-default` (default) — Neutral background, muted label colour. - `src-badge--context-info` — Info-blue styling. - `src-badge--context-success` — Success-green styling. - `src-badge--context-warning` — Warning-amber styling. - `src-badge--context-attention` — Attention-yellow styling. - `src-badge--context-error` — Error-red styling. **Sub-elements:** - `src-badge__icon` — Prefix/postfix icon wrapper inside badge. **Custom properties:** `--srcBadgeBackgroundColor`, `--srcBadgeTextColor` ### Banner Element Notification banner. Use for page-level alerts. **Core class:** `src-banner` — Full-width notification banner container. **Usage:** ```html
Information
Your changes have been saved successfully.
``` **Context modifiers:** - `src-banner--context-info` — Info-blue styling. - `src-banner--context-success` — Success-green styling. - `src-banner--context-warning` — Warning-amber styling. - `src-banner--context-error` (alias: `src-banner--context-critical`) — Error-red styling. - `src-banner--context-critical` — Critical-red styling (same as error). **Size modifiers:** - `src-banner--size-sm` — Small size, the default of the banner by design: other elements default to md, the banner to sm. Add it explicitly, because without a size class the banner gets the md tokens. Tech-style uppercase title. - `src-banner--size-md` — Medium size. Tech-style uppercase title. - `src-banner--size-lg` — Large size. Capitalized title with larger font. - `src-banner--size-xl` — Extra-large size. Capitalized title with larger font. **Sub-elements:** - `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. ### Breadcrumbs Element CSS-only breadcrumb navigation trail. Renders items in a horizontal list with "/" separators. Content inside each item is fully consumer-controlled (links, buttons, spans). **Core class:** `src-breadcrumbs` — Wrapper for the breadcrumb navigation. Apply to a
``` **Sub-elements:** - `src-dialog` — For CSS-only use without Angular: apply on a native `` element to reset its padding/border/background and style its `::backdrop` with the design-system curtain color. Open it with `showModal()` and close it with `close()`. In Angular, open modals with `SourceModalNativeService`, which creates the `` itself. - `src-modal__header` — Header row. Hosts only the close button: the title goes into `.src-modal__body` as `.src-modal__title`. No bottom border by default: set `--srcModalTitleBorder` to add one. - `src-modal__body` — Scrollable content area with padding. Grid-based; children `__title` and `__scroll-box` span the full width by default. - `src-modal__body--icon` — Switches body grid to two columns (24px icon + content). Use together with `.src-modal__icon` when rendering a context icon (info/success/warning/error). - `src-modal__icon` — Icon slot in the left column of `.src-modal__body--icon`. Spans all body rows. - `src-modal__title` — Semibold title inside the body. Word-break on overflow. - `src-modal__scroll-box` — Scrollable content wrapper spanning the full body grid width. - `src-modal__footer` — Action buttons row. Right-aligned by default; when two `.src-modal__footer-group` children are present it switches to space-between via `:has()`. Top border. On narrow viewports (<=767px) stacks column-reverse. - `src-modal__footer-group` — Button group inside `.src-modal__footer`. Use one group for right-aligned buttons, or two groups to split them between left and right. - `src-modal__close` — Absolutely-positioned close button at top-right of the header. Typically applied to `.src-icon-button`. **Custom properties:** `--srcModalWidth`, `--srcModalMaxWidth`, `--srcModalMaxHeight`, `--srcModalBg`, `--srcModalBoxShadow`, `--srcModalBorderRadius`, `--srcModalTitleSize`, `--srcModalTitleLineHeight`, `--srcModalTitleColor`, `--srcModalBodyPadding`, `--srcModalTitleBorder`, `--srcModalFooterBorder` ### Radio Group Element Radio button group container. **Core class:** `src-radio-group` — Flex column container for radio buttons. **Usage:** ```html
``` **Layout modifiers:** - `src-radio-group--horizontal` — Switches to horizontal flex-row with wrapping. **Sub-elements:** - `src-radio` (required) — Flex container for a single radio button. Wraps input[type="radio"] with custom appearance. Place it inside .src-radio-group: the group declares the border and colors of the radio, and on its own the radio has no border. - `src-radio__label` — Text label beside the radio button. - `src-radio--size-sm` — Small size for the radio and its label. - `src-radio--size-md` (default) — Default size for the radio and its label. - `src-radio--size-lg` — Large size for the radio and its label. - `src-radio--size-xl` — Extra large size for the radio and its label. **Custom properties:** `--srcRadioSize`, `--srcRadioGroupGap` ### Select Element Native dropdown select. Same modifiers as src-input. **Core class:** `src-select` — The main class for the select element. **Usage:** ```html ``` **Weight modifiers:** - `src-select--primary` (default) — Default visual appearance of select - with visible border. - `src-select--secondary` — Visual appearance for less prominent select - with visible background, but without border. - `src-select--ghost` — Visual appearance for the least prominent select - without visible background and border. **Size modifiers:** - `src-select--size-sm` — Smallest size of select. - `src-select--size-md` (default) — Default size of select. - `src-select--size-lg` — Large size of select. - `src-select--size-xl` — Extra large size of select. **Context modifiers:** - `src-select--context-success` — Green border for the select. Used for success context. - `src-select--context-error` — Red border for the select. Used for error context. **State modifiers:** - `src-select--disabled` — Disabled look only: the select stays reachable by Tab and is submitted with the form. To disable the select, use the disabled attribute, which gives the same look. ### Textarea Element Multi-line text input. **Core class:** `src-textarea` — The main class for the textarea element. **Usage:** ```html

Comment exceeds maximum length.

``` **Weight modifiers:** - `src-textarea--secondary` — Visual appearance with background fill, no border. - `src-textarea--ghost` — Transparent background, no border. **Size modifiers:** - `src-textarea--size-sm` — Smallest size (28px min-height). - `src-textarea--size-md` (default) — Default size (36px min-height). - `src-textarea--size-lg` — Large size (44px min-height). - `src-textarea--size-xl` — Extra large size (56px min-height). **Context modifiers:** - `src-textarea--context-success` — Green border for success context. - `src-textarea--context-error` — Red border for error context. **State modifiers:** - `src-textarea--disabled` — Disabled look only: the textarea stays reachable by Tab, editable and is submitted with the form. To disable the textarea, use the disabled attribute. ### Tile Element Image thumbnail tile. Use for material previews, preset cards, and option selectors. **Core class:** `src-tile` — Tile container. Sets relative positioning, width, and custom property defaults. **Usage:** ```html
Oak wood
3
Oak wood
Steel blue
``` **Modifier modifiers:** - `src-tile--active` — Active/selected state with accent border and focus shadow. - `src-tile--static` — Non-interactive tile — no hover/active feedback, default cursor. - `src-tile--disabled` — Dimmed tile with reduced opacity and no pointer events. - `src-tile--clamped` — Enables line-clamping on the title. Set --srcTileTitleLineClamp to control the number of visible lines. **Sub-elements:** - `src-tile__image` (required) — Image area with border, border-radius, aspect-ratio, and hover/active states. Place an inside: it fills the area. Any other element, like a color swatch, needs its own size: display: block; width: 100%; height: 100%. - `src-tile__title` — Title text below the image area. Hidden when empty. - `src-tile__delete` — Absolutely positioned delete button slot at top-right corner of the tile. - `src-tile__props` — Icon strip at bottom-left of the image area. Child elements are sized via --srcTilePropsItemSize. - `src-tile__counter` — Counter badge overlay on the image. Requires a placement modifier. - `src-tile__counter--center` — Centers the counter in the image area. The component uses it by default. - `src-tile__counter--top-right` — Places the counter at top-right of the image area. - `src-tile__counter--top-left` — Places the counter at top-left of the image area. - `src-tile__counter--bottom-right` — Places the counter at bottom-right of the image area. - `src-tile__counter--bottom-left` — Places the counter at bottom-left of the image area. - `src-tile__loading` — Full-overlay loading state covering the image area with a faded background. **Custom properties:** `--srcTileWidth`, `--srcTileAspectRatio`, `--srcTileBorderColor`, `--srcTileBorderRadius`, `--srcTileBoxShadow`, `--srcTileTransition`, `--srcTileImagePadding`, `--srcTilePointerEvents`, `--srcTileHoverBorderColor`, `--srcTileHoverBoxShadow`, `--srcTileActiveBorderColor`, `--srcTileActiveBoxShadow`, `--srcTileDisabledOpacity`, `--srcTileTitleColor`, `--srcTileTitleFontSize`, `--srcTileTitleLineHeight`, `--srcTileTitleLineClamp`, `--srcTilePropsItemSize`, `--srcTilePropsColor`, `--srcTilePropsBg`, `--srcTileCounterBg`, `--srcTileCounterColor` ### Toggle Element Toggle switch wrapping a native checkbox. **Core class:** `src-toggle` — Toggle switch wrapping a native checkbox. Styled as a pill-shaped track with animated thumb. **Usage:** ```html ``` **Sub-elements:** - `src-toggle__label` — Text label beside the toggle. ### Toolbar Element Inline container for grouping buttons and icon-buttons with shadow and rounded corners. **Core class:** `src-toolbar` — Inline container for grouping buttons and icon-buttons with shadow and rounded corners. **Usage:** ```html


``` **Modifier modifiers:** - `src-toolbar--compact` — Removes inner paddings. - `src-toolbar--vertical` — Stacks children vertically. Separate groups with a horizontal `
`: a vertical divider collapses here. - `src-toolbar--disabled` — Disables pointer events and applies a muted background. Buttons inside should be disabled separately. **Size modifiers:** - `src-toolbar--size-sm` — Small toolbar. - `src-toolbar--size-md` (default) — Medium toolbar (default). - `src-toolbar--size-lg` — Large toolbar. - `src-toolbar--size-xl` — Extra-large toolbar. **Custom properties:** `--srcToolbarBgColor`, `--srcToolbarBorderColor`, `--srcToolbarBorder`, `--srcToolbarPaddings`, `--srcToolbarGap`, `--srcToolbarBorderRadius`, `--srcToolbarShadow` ## Design tokens - [primitives](./docs/tokens/primitives.md): Raw color palette (`--src-color-*`) and spacing scale (`--src-space-*`); the values that semantic tokens point to - [color-light](./docs/tokens/color-light.md): Semantic colors of the light theme, the default: surfaces, text, icons, borders, UI accents and states, shadows, gradients - [color-dark](./docs/tokens/color-dark.md): The same semantic color names with dark-theme values; active under `.section_3dsourcecom--dark` - [typeface](./docs/tokens/typeface.md): Font tokens (`--src-font-*`): families, sizes, line heights, letter spacing, weights - [ui-sm](./docs/tokens/ui-sm.md): Component sizing tokens for the small size, for smaller and denser interfaces; active on an element with a `*--size-sm` modifier (such as `src-button--size-sm`) and inside it - [ui-md](./docs/tokens/ui-md.md): Component sizing tokens at the default size, on `:root`: padding, gaps, icon size, border radius, text size and line height, focus ring width - [ui-lg](./docs/tokens/ui-lg.md): Component sizing tokens for the large size, for roomy layouts and key actions that stand alone on a page (such as a sign-in form); active on an element with a `*--size-lg` modifier (such as `src-button--size-lg`) and inside it - [ui-xl](./docs/tokens/ui-xl.md): Component sizing tokens for the extra large size; active on an element with a `*--size-xl` modifier (such as `src-button--size-xl`) and inside it - [layout-sm](./docs/tokens/layout-sm.md): Layout tokens for spacing around and between containers: `--src-layout-gap-const-*`, `--src-layout-padding-const-*`, `--src-layout-radius-const-*`; the base values, for screens under 768px. The `*-const-*` tokens keep these values on every screen. - [layout-md](./docs/tokens/layout-md.md): Layout token values for screens from 768px; only the responsive tokens change here, the `*-const-*` ones stay the same - [layout-lg](./docs/tokens/layout-lg.md): Layout token values for screens from 1440px; only the responsive tokens change here, the `*-const-*` ones stay the same - [layout-xl](./docs/tokens/layout-xl.md): Layout token values for screens from 1920px; only the responsive tokens change here, the `*-const-*` ones stay the same ## Optional - [Full documentation (self-contained)](./docs/llms-full.txt): Every guide plus all component APIs, Source Elements and design tokens inlined — no external links needed