`.
Not every thing has both forms:
- **Component-only**: `src-color-picker`, `src-tab-line`, `src-popover-trigger`, `src-slider-group`, `src-slider`, `src-loading`, `src-logo-loading`, `src-copyright`, `src-overlay-container`.
- **Element-only (layout/chrome)**: `src-form`, `src-form__row`, `src-form__item`, `src-form__button-row`, `src-list`, `src-toolbar`, `src-label`, `src-button-group`.
- **Both forms exist**: `src-button`, `src-icon-button`, `src-hint`, `src-badge`, `src-divider`, `src-tile`, `src-banner`, `src-breadcrumbs`, `src-modal` (CSS structure for modal templates; `SourceModalComponent` and `SourceModalNativeComponent` open only through a service, never as tags), plus the form controls `src-input` / `src-select` / `src-textarea` / `src-checkbox` / `src-radio` / `src-toggle` (element forms paired with stock Material tags via this library's styling).
**Which form to pick** — where both exist, either works: keep to the form the project already uses, so the markup stays consistent. Layout and form plumbing (`src-form`, `src-form__item`, `src-label`) exist only as elements. Inside `
` use stock `matInput` markup, not `class="src-input"` — the library already styles the Material field, and both together double-style it. Element modifiers like `src-input--size-lg` or `src-input--context-success` placed on a Material wrapper propagate into the Material styling — elements and Material are co-operative, not alternatives.
## Setup
`@3dsource/source-ui` is a peer of `@3dsource/source-ui-native` — both must be installed together.
1. **Complete the native setup first** — follow the [@3dsource/source-ui-native setup guide](../source-ui-native/guides/setup.md) (stylesheet import, `section_3dsourcecom` root class, optional `` for native modals, optional dark theme). Those steps apply identically to apps using `@3dsource/source-ui`.
2. **Import the source-ui stylesheet** in addition to the native one. In `styles.scss`:
```scss
@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;
```
3. **CDK Dialog needs no extra provider.** `SourceModalComponent` is opened via `inject(Dialog).open(...)` from `@angular/cdk/dialog`; the default CDK overlay is sufficient. Do not add `provideDialog()`.
4. **Angular Material is a required peer.** Install `@angular/material`, provide `MAT_FORM_FIELD_DEFAULT_OPTIONS` globally with `{ appearance: 'outline' }`, and import the Material modules you need in each consuming component (`MatFormFieldModule`, `MatInputModule`, `MatSelectModule`, `MatAutocompleteModule`, `MatCheckboxModule`, `MatRadioModule`, `MatSlideToggleModule`):
```ts
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
providers: [
{ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { appearance: 'outline' } },
]
```
Without the outline default, the library's form-field styling does not activate.
5. **(If using ngx-toastr)** install `ngx-toastr` (on Angular 22, see the peer note in [Toastr styling](#toastr-styling)), then register its provider:
```ts
import { provideToastr } from 'ngx-toastr';
providers: [provideToastr()]
```
Also import the ngx-toastr stylesheet before `source.ui.scss`, so that the Source UI styles override its default toast classes. The import order and inline toasts in your own container: [Toastr styling](#toastr-styling).
## Key concepts
- **Material styling is global.** Importing `source.ui.scss` overrides Angular Material form field styles for the whole app, for fields with `appearance="outline"`: set it app-wide with `MAT_FORM_FIELD_DEFAULT_OPTIONS` ([Setup](#setup), step 4). No wrapper class on `` required. Use stock Material markup.
- **Hints, errors, labels — use Source UI, not Material.** The Material subscript area that holds `` and `` is hidden (it brings unwanted spacing), and `` is not part of the design. Use `` above the field and `
` below it.
- **`` and `` panels need a `` wrapper** around the `
` children — without it, the panel is unstyled. See [Material form styling](#material-form-styling).
- **Error state follows Material's `ErrorStateMatcher`.** The field turns red when the bound control is invalid and touched (or the form is submitted). For the **success** case, add `class="src-input--context-success"` on `` yourself (Material has no native valid state).
- **Modifier classes** (size, context, weight) are enumerated once in [Material form styling](#material-form-styling). Sizes default to `md` across the form elements; apply `src-input--size-sm` (etc.) on `` to override.
- **Component or element** (see [Source Element vs Source Component](#source-element-vs-source-component)): where both exist, either works; keep to the form the project already uses. Layout chrome and form plumbing exist only as elements.
- **Modal: CDK vs native.** `SourceModalComponent` (CDK `Dialog`, this package) and `SourceModalNativeComponent` (native ``, `@3dsource/source-ui-native`) share the `SourceModalData` contract. Prefer the native one for new code; the CDK one stays supported. How to open the CDK one: [Services](#services), section "CDK Dialog for SourceModalComponent". APIs: [SourceModalComponent](./docs/components/modal.md), [SourceModalNativeComponent](../source-ui-native/docs/components/modal-native.md). If the app sets `OVERLAY_DEFAULT_CONFIG` to `{ usePopover: false }`, see the native [Setup](../source-ui-native/guides/setup.md), step 3.
- **Popovers.** Two equal ways to open one: `` around the trigger element ([SourcePopoverTriggerComponent API](./docs/components/popover-trigger.md)), or `SourcePopoverService.show()` from code ([Services](#services)).
- The content is an ``. Any component can go inside it.
- The service needs a `CdkOverlayOrigin` anchor and is not provided in root: add it to the `providers` of your component. The trigger does both itself.
- When the `breakpointDesktop` media query does not match (by default, below 1024px), the popover opens as a bottom drawer.
- **Tabs — use ``.** `SourceTabsComponent` + `SourceTabComponent` are deprecated. `` is the navigation bar; render the content area yourself.
## Material form styling
`@3dsource/source-ui` does not define separate Angular form components for text input, select, autocomplete, checkbox, radio, or slide-toggle — instead it restyles Angular Material tags via global CSS. Importing `source.ui.scss` overrides the default Material styles for:
- `` with ` ` — text input
- `` with `` — dropdown select
- `` with ` ` — autocomplete
- `` — styled checkbox
- `` / `` — styled radio
- `` — styled toggle
No wrapper class is needed — use stock Material markup and the styles apply automatically.
New forms use Signal Forms: `form()` and the `FormField` directive from `@angular/forms/signals`, bound with `[formField]="profileForm.email"` on the Material control. Existing reactive forms stay reactive. The examples below bind reactive forms (`[formControl]`, which needs `ReactiveFormsModule` from `@angular/forms`); with Signal Forms the markup is the same, only the binding changes.
**Labels.** A field has one or both of two labels:
- the main label, `` above the field (uppercase technical text);
- an inline label inside the field, `
` inside ``, without `src-label`. Avoid it; use it only where space is short.
Never use ``: it adds unwanted wrappers inside the form field and does not match the design. Do not use `` or `` either: the subscript area that shows them is hidden; put hints and errors in `` below the field.
### Form layout
`` wraps the form and provides flex-column spacing. Every field goes inside a `