Skip to main content
cngx-src documentation

CngxSelectShell

ComponentPrimaryOnPushNo encapsulationv0.1.0WCAG AA

projects/forms/select/select-shell/select-shell.component.ts

Import#

import { CngxSelectShell } from '@cngx/forms/select'

Description#

Native-feeling single-value dropdown with declarative options - consumers project <cngx-option> / <cngx-optgroup> children and the shell derives a hierarchy-aware option model.

Bridges the raw-listbox compose-yourself path and the data-mode <cngx-select [options]> path: same family-level intelligence (reactive trigger ARIA, panel composition, template-slot cascade) applied to a content-projected option list.

Naming: distinct from the internal CngxSelectPanelShell - Shell here is the projection-shell that wraps consumer option markup.

https://cngxjs.github.io/cngx/examples/#/forms/select/select-shell/basic-flat-declarative-options https://cngxjs.github.io/cngx/examples/#/forms/select/select-shell/custom-glyphs-clearglyph-caretglyph https://cngxjs.github.io/cngx/examples/#/forms/select/select-shell/grouped-divider-projected-hierarchy https://cngxjs.github.io/cngx/examples/#/forms/select/select-shell/inside-cngx-form-field-reactive-forms https://cngxjs.github.io/cngx/examples/#/forms/select/select-shell/rich-content-option-plain-text-trigger https://cngxjs.github.io/cngx/examples/#/forms/select/select-shell/search-declarative-cngx-select-search

Metadata#

Host#

Providers#

CNGX_FORM_FIELD_CONTROL
useExisting CngxSelectShell
CNGX_SELECT_PANEL_HOST
useExisting CngxSelectShell
CNGX_SELECT_PANEL_VIEW_HOST
useExisting CngxSelectShell
CNGX_OPTION_STATUS_HOST
useExisting CngxSelectShell
CNGX_OPTION_FILTER_HOST
useExisting CngxSelectShell
CNGX_OPTION_INTERACTION_HOST
useExisting CngxSelectShell
CNGX_SELECT_SHELL_SEARCH_HOST
useExisting CngxSelectShell

Dependencies#

CNGX_TEMPLATE_REGISTRY_FACTORYinject()tpl

Relationships

Index#

Inputs#

announceChanges#boolean | null
input()
default null
input()
default null
ariaLabel#string | null
input()
default null, { alias: 'aria-label' }
ariaLabelledBy#string | null
input()
default null, { alias: 'aria-labelledby' }
autofocus#boolean
input()
default false
caretGlyph#TemplateRef | null
default null
clearable#boolean
input()
default false
clearButtonAriaLabel#string
input()
default this.config.ariaLabels?.clearButton ?? 'Clear selection',
clearGlyph#TemplateRef | null
default null
default null
commitErrorAnnouncePolicy#CngxCommitErrorAnnouncePolicy
input()

Scalar-commit error-announce policy. Per-instance input wins over CngxSelectConfig.commitErrorAnnouncePolicy. Default { kind: 'verbose', severity: 'assertive' }.

default
    this.config.commitErrorAnnouncePolicy ?? { kind: 'verbose', severity: 'assertive' },  
input()
default this.config.commitErrorDisplay
input()
default 'optimistic'
default cngxSelectDefaultCompare as CngxSelectCompareFn<T>,
disabledInput#boolean
input()
default false, { alias: 'disabled' }
hideCaret#boolean
input()
default !this.config.showCaret
hideSelectionIndicator#boolean
input()
default !this.config.showSelectionIndicator
idInput#string | null
input()
default null, { alias: 'id' }
label#string
input()
default ''
loading#boolean
input()
default false
input()
default this.config.loadingVariant
panelClass#string | readonly string[] | null
input()
default null
panelWidth#'trigger' | number | null
input()
default this.config.panelWidth
placeholder#string
input()
default ''
popoverPlacement#PopoverPlacement
input()
default this.config.popoverPlacement
input()
default this.config.refreshingVariant
requiredInput#boolean
input()
default false, { alias: 'required' }
searchDebounceMs#number
input()

Debounce for searchTermChange (ms). Forward-compatible input - the shipped CNGX_SEARCH_EFFECTS_FACTORY emits immediately; consumers overriding the factory read this signal to size their pipeline.

default this.config.typeaheadDebounceInterval
searchTerm#string
model()

Two-way bindable search term. Drives per-option visibility through CngxOptionFilterHost and filters the listbox AD so keyboard nav skips hidden options. Empty string disables the filter.

default ''
selectionIndicatorPosition#'before' | 'after' | null
input()
default null
input()
default null
skeletonRowCount#number
input()
default this.config.skeletonRowCount
default null
tabIndex#number
input()
default 0
value#T | undefined
model()

Two-way bindable selected value.

Outputs#

closed#void
output()
commitError#unknown
output()
opened#void
output()
openedChange#boolean
output()
retry#void
output()
searchTerm#string
model()

Two-way bindable search term. Drives per-option visibility through CngxOptionFilterHost and filters the listbox AD so keyboard nav skips hidden options. Empty string disables the filter.

searchTermChange#string
output()

Live search term emitted via CNGX_SEARCH_EFFECTS_FACTORY. The factory's skipInitial gate suppresses the seed '' emission so server-driven autocomplete consumers don't fire a blank search.

selectionChange#CngxSelectShellChange
stateChange#AsyncStatus
output()
value#T | undefined
model()

Two-way bindable selected value.

Instance Properties#

activeView#unknown
ProtectedReadonly
this.core.activeView
adItems#unknown
ProtectedReadonly
this.projectedOptionModel.adItems
ariaLabels#unknown
Readonly
this.core.ariaLabels
ariaReadonly#unknown
ProtectedReadonly
this.core.ariaReadonly
commitErrorContext#unknown
ProtectedReadonly
this.core.bindCommitRetry(() =>
  this.scalarHandler.retryLast(),
)
commitErrorValue#unknown
Readonly
this.core.commitErrorValue
commitState#unknown
Readonly
this.core.commitState
derivedOptions#unknown
ProtectedReadonly
this.projectedOptionModel.derivedOptions
disabled#unknown
Readonly
this.core.disabled
effectiveOptions#unknown
ProtectedReadonly
this.core.effectiveOptions
effectiveTabIndex#unknown
ProtectedReadonly
this.core.effectiveTabIndex
errorContext#unknown
ProtectedReadonly
this.core.makeErrorContext(() => this.handleRetry())
externalActivation#unknown
ProtectedReadonly
this.core.externalActivation
fallbackLabels#unknown
Readonly
this.core.fallbackLabels
flatOptions#unknown
ProtectedReadonly
this.core.flatOptions
focused#unknown
Readonly
this.focusState.focused
isCommitting#unknown
Readonly
this.core.isCommitting
listboxCompareWith#unknown
ProtectedReadonly
computed<(a: unknown, b: unknown) => boolean>(
  () => this.compareWith() as unknown as (a: unknown, b: unknown) => boolean,
)
panelClassList#unknown
ProtectedReadonly
this.core.panelClassList
panelRenderer#unknown
Readonly
this.virtualSetup.panelRenderer
panelWidthCss#unknown
ProtectedReadonly
this.core.panelWidthCss
projectedOptions#unknown
ProtectedReadonly
this.projectedOptionModel.projectedOptions
resolvedId#unknown
ProtectedReadonly
this.core.resolvedId
resolvedListboxLabel#unknown
ProtectedReadonly
this.core.resolvedListboxLabel
resolvedSelectionIndicatorPosition#unknown
ProtectedReadonly
this.core.resolvedSelectionIndicatorPosition
resolvedSelectionIndicatorVariant#unknown
ProtectedReadonly
this.core.resolvedSelectionIndicatorVariant
resolvedShowCaret#unknown
ProtectedReadonly
this.core.resolvedShowCaret
resolvedShowSelectionIndicator#unknown
ProtectedReadonly
this.core.resolvedShowSelectionIndicator
retryFn#unknown
Readonly
input<(() => void) | null>(null)
searchMatchFn#unknown
Readonly

Per-instance match policy. Receives (value, label, term) and returns true when the option should stay visible. Default: case-insensitive substring on the label.

input<((value: T, label: string, term: string) => boolean) | null>(null)
selected#unknown
Readonly

Currently selected option resolved against the derived option model.

computed<CngxSelectOptionDef<T> | null>(() => this.selectedOption(), {
  equal: (a, b) => {
    if (a === b) {
      return true;
    }
    if (a === null || b === null) {
      return false;
    }
    return (this.compareWith() as CngxSelectCompareFn<unknown>)(a.value, b.value);
  },
})
showCommitError#unknown
ProtectedReadonly
this.core.showCommitError
showInlineError#unknown
ProtectedReadonly
this.core.showInlineError
showRefreshIndicator#unknown
ProtectedReadonly
this.core.showRefreshIndicator
skeletonIndices#unknown
ProtectedReadonly
this.core.skeletonIndices
triggerAria#unknown
ProtectedReadonly
this.core.triggerAria
triggerLabelTpl#unknown
ProtectedReadonly

Variant-specific trigger-label slot. Inline because the directive's typed context shape varies per variant.

computed<TemplateRef<
  CngxSelectTriggerLabelContext<T>
> | null>(() => this.triggerLabelDirective()?.templateRef ?? null)
virtualItemCount#unknown
ProtectedReadonly
this.virtualSetup.virtualItemCount
visibleProjectedOptions#unknown
ProtectedReadonly
this.projectedOptionModel.visibleProjectedOptions

Methods#

clearLocalItems#void
close#void
focus#void
focus(options?: FocusOptions)
@paramoptions?FocusOptions
open#void
patchData#void
patchData(item: CngxSelectOptionDef<T>)
toggle#void

HostBindings#

BindingExpression
[id]resolvedId()
[attr.aria-readonly]ariaReadonly()

Structural styles shared across the entire CngxSelect family - imported via styleUrls from every variant (CngxSelect, CngxMultiSelect, CngxCombobox, CngxTypeahead, CngxTreeSelect, CngxReorderableMultiSelect, CngxActionSelect, CngxActionMultiSelect, CngxSelectShell, and the panel components).

All variants run encapsulation: None so the rules below are global; the .cngx-select__* BEM-style class prefix is the namespace.

State modifiers

  • .cngx-option--highlighted on an option row - primary-tinted background marking the keyboard-focused row
  • [aria-disabled='true'] on an option - opacity 0.5 + cursor: not-allowed
  • .cngx-select__option--pending - cursor: progress while a row's commit is in flight
  • .cngx-select__chip-list--reordering - whole-strip cursor: grabbing while a drag is active
  • .cngx-select__chip--dragging on a chip - Trello-style lift (shadow + scale + tilt + accent fill)
  • .cngx-select__chip--drag-over on a chip - vertical drop bar painted on the leading edge via ::before

Variants

Chip-list overflow modes via data-overflow:

  • default - flex-wrap chips across multiple rows
  • data-overflow='scroll-x' - single row + horizontal scroll
  • data-overflow='truncate' - single row + clipped overflow + the .cngx-select__chip-overflow-badge count pill

Error surfaces with two layouts:

  • .cngx-select__error - column-stacked block (message + retry)
  • .cngx-select__error--inline - inline banner above the option list
  • .cngx-select__commit-error - per-commit failure banner

Slots

  • .cngx-select__panel - the floating panel surface (anchor-positioned via position-try-fallbacks)
  • .cngx-select__group-header - uppercase optgroup label
  • .cngx-select__option / .cngx-select__check - option row + the selected-state checkmark
  • .cngx-select__loading / .cngx-select__empty - inline message rows
  • .cngx-select__skeleton / .cngx-select__skeleton-row - first-load shimmer placeholders (static under prefers-reduced-motion)
  • .cngx-select__spinner-wrap / .cngx-select__spinner - first-load spinner ring
  • .cngx-select__loading-bar - first-load top-edge progress bar
  • .cngx-select__refreshing / .cngx-select__refreshing-spinner / .cngx-select__refreshing-dots - subsequent-load indicators
  • .cngx-select__option-spinner / .cngx-select__option-error - per-row commit feedback
  • .cngx-select__chip-list / .cngx-select__chip-overflow-badge - chip strip + overflow count
  • .cngx-select__chip-wrap / .cngx-select__chip-handle - reorderable chip surface + optional drag-handle glyph
  • .cngx-select__error / .cngx-select__error--inline / .cngx-select__error-message / .cngx-select__error-retry / .cngx-select__commit-error - error block, banner, and retry pieces

Inheritance

Tokens are registered top-level in @layer cngx.tokens via @property so any consumer (cngx.theme layer, app layer) can override without learning the type.

Panel surface, every primary-tinted glyph, and every danger-toned error surface delegate to the foundation so a dark-mode swap cascades through the floating panel even when anchor positioning detaches it from the trigger's DOM context:

  • --cngx-select-panel-border -> --cngx-color-border
  • --cngx-select-panel-bg -> --cngx-color-surface
  • --cngx-select-panel-color -> --cngx-color-text
  • --cngx-select-panel-shadow -> --cngx-shadow-md
  • --cngx-select-check-color -> --cngx-color-primary
  • --cngx-select-spinner-color -> --cngx-color-primary
  • --cngx-select-loading-bar-color -> --cngx-color-primary
  • --cngx-select-refreshing-color -> --cngx-color-primary
  • --cngx-select-option-spinner-color -> --cngx-color-primary
  • --cngx-select-option-error-color -> --cngx-color-danger
  • --cngx-select-error-color -> --cngx-color-danger
  • --cngx-select-chip-remove-hover-color -> --cngx-color-danger
  • --cngx-select-chip-drag-bg -> --cngx-color-primary
  • --cngx-select-chip-drop-bar-color -> --cngx-color-primary
  • --cngx-select-trigger-invalid-border-color -> --cngx-color-danger
  • --cngx-select-trigger-invalid-outline-color -> --cngx-color-danger

--cngx-select-panel-min-width is intentionally NOT registered via @property so the anchor-size(width) fallback survives when the consumer doesn't override it; registering it with any initial-value would shadow the var() fallback and break anchor positioning.

Dark mode

Three hooks swap alpha-on-black surfaces (panel shadow, option highlight, spinner track, chip-overflow tint, chip remove-hover tint, chip handle muted, chip drag shadow) plus the skeleton shimmer gradient and the option-spinner track:

  • prefers-color-scheme: dark
  • [data-color-scheme="dark"]
  • .dark class

Foundation-delegated tokens ride the foundation cascade unchanged.

Pair with

  • @cngx/themes/material/select-theme - Material 3 surface treatment across the entire family

Trigger skin for CngxSelectShell - the declarative-projection counterpart to CngxSelect (consumers project <cngx-option> / <cngx-optgroup> / <cngx-select-divider> instead of binding to a data source). The host carries .cngx-select-shell; surface mirrors single-select/select.component.css but namespaces every tunable through --cngx-select-shell-* so the declarative variant can be themed independently of the data-mode CngxSelect. Structural rules (panel frame, option rows, async-state surfaces) ride on shared/select-base.css.

State modifiers

  • :focus-visible on .cngx-select-shell__trigger - focus-ring outline + offset
  • [aria-disabled='true'] on the trigger - opacity dim + cursor: not-allowed
  • :hover on .cngx-select-shell__clear - opacity 1
  • :focus-visible on the clear button - 2px primary-tinted outline

Slots

  • .cngx-select-shell__root - display: contents host shim
  • .cngx-select-shell__trigger - the bordered row (user-select: none prevents drag-click text selection)
  • .cngx-select-shell__label - ellipsis-truncating value summary (inline-flex with --label-gap between glyph and text)
  • .cngx-select-shell__caret - panel-state glyph
  • .cngx-select-shell__clear - reset button

Inheritance

Trigger tokens delegate up the family chain so consumer themes can override at the level they want to brand:

  • --cngx-select-shell-* -> --cngx-select-* -> hardcoded
  • --cngx-select-shell-border -> --cngx-color-border
  • --cngx-select-shell-focus-outline -> --cngx-color-primary
  • --cngx-select-shell-focus-ring -> --cngx-color-primary

Once registered via @property the inner var() steps are documentation-only; system tokens (--cngx-color-*) are the brand-wide override path.

Pair with

  • @cngx/themes/material/select-theme - Material 3 surface treatment shared across the entire select family

Index#

Surface

--cngx-select-panel-border#*
Default value 1px solid oklch(0.85 0.01 250)

Border shorthand of the dropdown panel. Falls back through --cngx-color-border. inherits: true so the :root delegating value reaches the floating panel host (anchor-positioned, may sit outside the normal DOM flow).

See: [[--cngx-color-border]]

--cngx-select-panel-bg#<color>
Default value oklch(1 0 0)

Background of the dropdown panel. Falls back through --cngx-color-surface.

See: [[--cngx-color-surface]]

--cngx-select-panel-color#*
Default value currentColor

Text color inside the panel. syntax: '*' + initial-value currentColor lets the panel inherit text color from its ancestor by default. Registering as <color> would forbid currentColor since <color> requires a computationally- independent value.

--cngx-select-panel-shadow#*
Default value 0 4px 12px oklch(0 0 0 / 0.12)

Drop-shadow shorthand. Falls back through --cngx-shadow-md. inherits: true so the :root dark-mode override (deeper shadow on dark) reaches the floating panel host.

--cngx-select-placeholder-color#<color>
Default value oklch(0 0 0 / 0.5)

Color of the placeholder text shown when no value is selected.

--cngx-select-caret-color#<color>
Default value oklch(0 0 0 / 0.5)

Color of the dropdown caret glyph shared across every variant. Muted by default to mirror the placeholder token; the Material bridge maps it to --mat-sys-on-surface-variant. inherits: true so a trigger-level override reaches the glyph element.

--cngx-select-clear-color#<color>
Default value oklch(0 0 0 / 0.5)

Color of the clear-button glyph shared across every variant. Tracks the same muted default as the caret so both trigger affordances read uniformly. inherits: true so a trigger-level override reaches the glyph element.

--cngx-select-shell-border#*
Default value 1px solid oklch(0.85 0.01 250)

Border shorthand of the trigger.

--cngx-select-shell-bg#<color>
Default value transparent

Background of the trigger.

--cngx-select-shell-color#*
Default value currentColor

Text color of the trigger.

--cngx-select-shell-caret-opacity#<number>
Default value 0.7

Opacity of the caret glyph.

Layout

--cngx-select-panel-radius#*
Default value 0.25rem

Corner radius of the dropdown panel.

--cngx-select-panel-padding#*
Default value 0.25rem

Inner padding of the panel.

--cngx-select-panel-max-height#*
Default value 16rem

Maximum height before vertical scrolling kicks in.

--cngx-select-option-padding#*
Default value 0.375rem 0.5rem

Padding shorthand of each option row.

--cngx-select-option-min-height#*
Default value auto

Minimum height of an option row - defaults to auto so dense rows stay compact.

--cngx-select-option-radius#*
Default value 0.125rem

Corner radius of an option row.

--cngx-select-caret-size#*
Default value 1.25em

Font-size of the dropdown caret glyph shared across every variant.

--cngx-select-chip-gap#*
Default value 0.25rem

Gap between chips inside the trigger chip list.

--cngx-select-chip-wrap-radius#*
Default value 0.25rem

Corner radius of the reorderable chip wrap container.

--cngx-select-chip-wrap-gap#*
Default value 0.25rem

Gap between the chip body and any projected drag handle.

--cngx-select-shell-min-width#*
Default value 10rem

Minimum inline size of the trigger.

--cngx-select-shell-min-height#*
Default value 2.25rem

Minimum block size of the trigger. Shared family default so the shell trigger matches the other variants instead of sizing to content.

--cngx-select-shell-gap#*
Default value 0.5rem

Gap between the label, caret, and clear button.

--cngx-select-shell-padding#*
Default value 0.5rem 0.75rem

Padding shorthand of the trigger.

--cngx-select-shell-radius#*
Default value 0.25rem

Corner radius of the trigger.

--cngx-select-shell-label-gap#*
Default value 0.375rem

Gap inside the label slot (between glyph and text).

State / Highlighted

--cngx-select-option-highlight-bg#<color>
Default value oklch(0.66 0.19 50 / 0.1)

Background of the keyboard-highlighted option row. Defaults to a low-alpha tint of --cngx-color-primary so the highlight reads as brand-accented without competing with selection state.

See: [[--cngx-color-primary]]

State / Selected

--cngx-select-check-color#<color>
Default value oklch(0.66 0.19 50)

Color of the selected-option checkmark glyph. Falls back through --cngx-color-primary.

See: [[--cngx-color-primary]]

State / Disabled

--cngx-select-disabled-opacity#<number>
Default value 0.5

Opacity multiplier applied when the trigger is disabled. Shared family-wide so every variant dims its disabled trigger identically.

--cngx-select-shell-disabled-opacity#<number>
Default value 0.5

Opacity multiplier applied when the trigger is disabled.

State / Loading

--cngx-select-skeleton-gap#*
Default value 0.25rem

Vertical gap between skeleton placeholder rows.

--cngx-select-skeleton-padding#*
Default value 0.25rem

Padding around the skeleton placeholder block.

--cngx-select-skeleton-row-height#*
Default value 1.75rem

Height of each skeleton placeholder row.

--cngx-select-skeleton-row-radius#*
Default value 0.125rem

Corner radius of each skeleton placeholder row.

--cngx-select-spinner-padding#*
Default value 1rem

Padding around the first-load spinner wrapper.

--cngx-select-spinner-size#*
Default value 1.5rem

Diameter of the first-load spinner ring.

--cngx-select-spinner-border#*
Default value 2px solid oklch(0 0 0 / 0.15)

Track stroke of the first-load spinner ring. inherits: true so the :root dark-mode override (alpha-on-white on dark) reaches the spinner inside the floating panel.

--cngx-select-spinner-color#<color>
Default value oklch(0.66 0.19 50)

Indicator stroke of the first-load spinner ring. Falls back to --cngx-color-primary.

--cngx-select-loading-bar-height#<length>
Default value 3px

Height of the first-load loading bar.

--cngx-select-loading-bar-color#<color>
Default value oklch(0.66 0.19 50)

Color of the first-load loading bar. Falls back to --cngx-color-primary.

State / Refreshing

--cngx-select-refreshing-height#<length>
Default value 2px

Height of the subsequent-load refreshing bar.

--cngx-select-refreshing-color#<color>
Default value oklch(0.66 0.19 50)

Color of the refreshing bar gradient. Falls back to --cngx-color-primary.

--cngx-select-refreshing-spinner-padding#*
Default value 0.25rem

Padding around the refreshing spinner wrapper.

--cngx-select-refreshing-dots-gap#*
Default value 0.25rem

Gap between the three refreshing dots.

--cngx-select-refreshing-dots-padding#*
Default value 0.375rem

Padding around the refreshing dots block.

--cngx-select-refreshing-dot-size#*
Default value 0.375rem

Diameter of each refreshing dot.

--cngx-select-refreshing-dot-color#*
Default value currentColor

Color of each refreshing dot.

State / Commit

--cngx-select-option-spinner-size#*
Default value 0.875rem

Diameter of the per-row commit spinner.

--cngx-select-option-spinner-color#<color>
Default value oklch(0.66 0.19 50)

Indicator stroke of the per-row commit spinner.

--cngx-select-option-error-color#<color>
Default value oklch(0.6 0.18 25)

Glyph color of the per-row commit error indicator. Falls back to --cngx-color-danger.

--cngx-select-commit-error-padding#*
Default value 0.375rem 0.5rem

Padding of the commit error banner.

--cngx-select-commit-error-radius#*
Default value 0.125rem

Corner radius of the commit error banner.

State / Overflow

--cngx-select-chip-overflow-badge-bg#<color>
Default value oklch(0 0 0 / 0.08)

Background of the chip overflow badge shown in truncate overflow mode.

--cngx-select-chip-overflow-badge-color#<color>
Default value oklch(0 0 0 / 0.6)

Text color of the chip overflow badge.

State / Remove

--cngx-select-chip-remove-size#*
Default value 1.25rem

Hit-target diameter of the chip remove button inside a reorderable chip wrap.

--cngx-select-chip-remove-hover-bg#<color>
Default value oklch(0 0 0 / 0.12)

Background tint of the chip remove button on hover.

--cngx-select-chip-remove-hover-color#<color>
Default value oklch(0.6 0.18 25)

Foreground color of the chip remove button on hover. Falls back to --cngx-color-danger.

State / Reorder

--cngx-select-chip-handle-color#<color>
Default value oklch(0.5 0.01 250)

Color of the optional projected drag-handle glyph.

--cngx-select-chip-handle-size#*
Default value 0.75rem

Font-size of the optional projected drag-handle glyph.

State / Dragging

--cngx-select-chip-drag-shadow#*
Default value 0 8px 20px oklch(0 0 0 / 0.28)

Drop-shadow of the chip lifted into the dragging state. inherits: true so the :root dark-mode override (deeper shadow on dark) reaches the chip while it's being dragged.

--cngx-select-chip-drag-bg#<color>
Default value oklch(0.66 0.19 50)

Background of the chip lifted into the dragging state. Falls back to --cngx-color-primary.

See: [[--cngx-color-primary]]

--cngx-select-chip-drag-color#<color>
Default value oklch(1 0 0)

Text color of the chip lifted into the dragging state.

--cngx-select-chip-drag-scale#<number>
Default value 1.06

Scale multiplier of the dragging chip - Trello-style lift.

--cngx-select-chip-drag-tilt#<angle>
Default value -1.5deg

Rotation tilt applied to the dragging chip - Trello-style lift.

--cngx-select-chip-drop-bar-width#<length>
Default value 3px

Width of the drop-indicator bar between chips.

--cngx-select-chip-drop-bar-color#<color>
Default value oklch(0.66 0.19 50)

Color of the drop-indicator bar between chips. Falls back to --cngx-color-primary.

State / Error

--cngx-select-error-gap#*
Default value 0.5rem

Gap between the error message and the retry button.

--cngx-select-error-padding#*
Default value 0.5rem 0.75rem

Padding of the panel-wide error block.

--cngx-select-error-color#<color>
Default value oklch(0.6 0.18 25)

Text color of every error surface. Falls back to --cngx-color-danger.

See: [[--cngx-color-danger]]

--cngx-select-error-inline-padding#*
Default value 0.375rem 0.5rem

Padding of the inline error banner shown above the option list.

--cngx-select-error-inline-radius#*
Default value 0.125rem

Corner radius of the inline error banner.

--cngx-select-error-retry-border#*
Default value 1px solid currentColor

Border shorthand of the error retry button.

State / Trigger invalid

--cngx-select-trigger-invalid-border-color#<color>
Default value oklch(0.6 0.18 25)

Border color painted on the trigger wrapper when aria-invalid="true". Defaults track --cngx-color-danger via the delegating :root entry below.

--cngx-select-trigger-invalid-border-width#<length>
Default value 1px

Border width painted on the trigger wrapper when aria-invalid="true".

--cngx-select-trigger-invalid-outline-color#<color>
Default value oklch(0.6 0.18 25)

Outline color layered on the invalid trigger when focus is inside it. Defaults track --cngx-color-danger via the delegating :root entry below.

--cngx-select-trigger-invalid-glow#*
Default value 0 0 0 3px oklch(0.6 0.18 25 / 0.2)

Soft halo layered behind the invalid trigger at focus time. Authored as a box-shadow so it composes with any consumer-supplied focus outline.

State / Focus

--cngx-select-shell-focus-outline#*
Default value 2px solid oklch(0.66 0.19 50)

Focus-ring outline shorthand. Falls back to --cngx-color-primary.

See: [[--cngx-color-primary]]

--cngx-select-shell-focus-ring#<color>
Default value oklch(0.66 0.19 50)

Focus-ring color used on the clear button's focus state.

State / Clear

--cngx-select-shell-clear-opacity#<number>
Default value 0.6

Resting opacity of the clear button.

Material theme

import { ChangeDetectionStrategy, Component, ViewEncapsulation, signal } from '@angular/core';

import { CngxSelectShell, CngxSelectOption } from '@cngx/forms/select';

/**
 * `CngxSelectShell` rendered against a Material 3 palette via the published
 * `@cngx/themes/material/select-theme` bridge.
 *
 * The stylesheet builds a real M3 theme: `mat.theme` emits the `--mat-sys-*`
 * system tokens, then `select.theme($theme)` routes every `--cngx-select-*`
 * token onto its Material counterpart, so the trigger, panel surface, and
 * selected-option tones inherit the palette with no per-instance overrides.
 * `ViewEncapsulation.None` lets the global `html` theme and the
 * `:where(cngx-select-shell)` bridge rules reach both the trigger and the
 * top-layer panel.
 */
@Component({
  selector: 'app-root',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  imports: [CngxSelectShell, CngxSelectOption],
  styleUrl: './material-theme.component.scss',
  template: `
    <div class="demo">
      <cngx-select-shell
        [label]="'Favorite color'"
        [(value)]="value"
        [selectionIndicatorPosition]="'after'"
        placeholder="Pick a color…"
      >
        <cngx-option [value]="'red'">Red</cngx-option>
        <cngx-option [value]="'green'">Green</cngx-option>
        <cngx-option [value]="'blue'">Blue</cngx-option>
        <cngx-option [value]="'amber'">Amber</cngx-option>
        <cngx-option [value]="'violet'">Violet</cngx-option>
      </cngx-select-shell>
      <p class="demo__readout">Selected: {{ value() ?? '—' }}</p>
    </div>
  `,
})
export class MaterialThemeExample {
  protected readonly value = signal<string | undefined>(undefined);
}
export { MaterialThemeExample as AppComponent };