/** * Copyright Aquera Inc 2025 * * This source code is licensed under the BSD-3-Clause license found in the * LICENSE file in the root directory of this source tree. */ import { css } from 'lit'; export const styles = css` :host { display: block; box-sizing: border-box; -webkit-font-smoothing: var(--nile-webkit-font-smoothing, var(--ng-webkit-font-smoothing)); -moz-osx-font-smoothing: var(--nile-moz-osx-font-smoothing, var(--ng-moz-osx-font-smoothing)); text-rendering: var(--nile-text-rendering, var(--ng-text-rendering)); } :host *, :host *::before, :host *::after { box-sizing: inherit; } [hidden] { display: none; } /* ── Form control ── */ .form-control .form-control__label { display: none; } .form-control--has-label .form-control__label { display: block; margin-bottom: var(--nile-spacing-sm, var(--ng-spacing-sm)); color: var(--nile-colors-dark-900, var(--ng-colors-text-secondary-700)); font-family: var(--nile-font-family-serif, var(--ng-font-family-body)); font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md)); font-style: normal; font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-medium)); line-height: var(--nile-spacing-2xl, var(--ng-line-height-text-sm)); letter-spacing: 0.2px; } .form-control--has-label.form-control--medium .form-control__label { font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm)); } :host([required]) .form-control--has-label .form-control__label::after { content: '*'; margin-inline-start: -2px; color: var(--nile-colors-red-700, var(--ng-colors-text-error-primary-600)); } :host([disabled]) .form-control--has-label .form-control__label { user-select: none; -webkit-user-select: none; } /* ── Popup ── */ .combobox-popup { flex: 1 1 auto; display: inline-flex; width: 100%; position: relative; vertical-align: middle; } .combobox-popup::part(popup) { z-index: 9999; } .combobox-popup[data-current-placement^='top']::part(popup) { transform-origin: bottom; } .combobox-popup[data-current-placement^='bottom']::part(popup) { transform-origin: top; } /* ── Trigger: outer row that never scrolls ── */ .combobox__trigger { display: flex; align-items: center; width: 100%; min-width: 0; position: relative; font-family: var(--nile-font-family-sans-serif, var(--ng-font-family-body)); font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-medium)); letter-spacing: normal; cursor: text; transition: 150ms color, 150ms border, 150ms box-shadow, 150ms background-color; background-color: var(--nile-colors-white-base, var(--ng-colors-bg-primary)); border: solid 1px var(--nile-colors-neutral-500, var(--ng-colors-border-primary)); outline: none; } .combobox__trigger:hover { border-color: var(--nile-colors-dark-900, var(--ng-colors-border-neutral)); } .combobox--open .combobox__trigger, .combobox--focused .combobox__trigger { border-color: var(--ng-colors-border-brand); box-shadow: 0 0 0 1px var(--ng-colors-border-brand) inset; background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary)); } .combobox--disabled .combobox__trigger { background-color: var(--nile-colors-dark-200, var(--ng-colors-bg-disabled-subtle)); border-color: var(--nile-colors-neutral-500, var(--ng-colors-border-primary)); color: var(--nile-colors-dark-500, var(--ng-colors-text-disabled)); cursor: not-allowed; user-select: none; } .combobox--warning .combobox__trigger { border-color: var(--nile-colors-yellow-500, var(--ng-colors-border-warning)); } .combobox--error .combobox__trigger { border-color: var(--nile-colors-red-500, var(--ng-colors-border-error)); } .combobox--success .combobox__trigger { border-color: var(--nile-colors-green-500, var(--ng-componentcolors-utility-success-500)); } /* Size: small */ .combobox--small .combobox__trigger { border-radius: var(--nile-radius-sm, var(--ng-radius-md)); font-size: var(--nile-type-scale-2, var(--ng-font-size-text-xs)); padding: var(--nile-spacing-md, var(--ng-spacing-sm)) var(--nile-spacing-md, var(--ng-spacing-md)); min-height: var(--nile-height-32px, var(--ng-height-32px)); } /* Size: medium */ .combobox--medium .combobox__trigger { border-radius: var(--nile-radius-sm, var(--ng-radius-md)); font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md)); padding: var(--nile-spacing-lg, var(--ng-spacing-md)) var(--nile-spacing-lg, var(--ng-spacing-lg)); min-height: var(--nile-height-40px, var(--ng-height-40px)); box-sizing: border-box; } /* Size: large */ .combobox--large .combobox__trigger { border-radius: var(--nile-radius-sm, var(--ng-radius-md)); font-size: var(--nile-type-scale-4, var(--ng-font-size-text-md)); padding: var(--nile-spacing-xl, var(--ng-spacing-lg)) var(--nile-spacing-xl, var(--ng-spacing-xl)); min-height: var(--nile-height-48px, var(--ng-height-48px)); } .combobox--pill .combobox__trigger { border-radius: var(--nile-radius-3xl, var(--ng-radius-3xl)); } .combobox--filled .combobox__trigger { border: none; background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary)); } .combobox--filled.combobox--open .combobox__trigger, .combobox--filled.combobox--focused .combobox__trigger { outline: 3px solid rgba(0, 89, 255, 0.4); } /* ── Inner area: holds tags + input ── */ .combobox__scroll-area { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 4px; overflow: hidden; } /* Single-line: horizontal scroll for overflowing tags */ .combobox__scroll-area--single-line { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; scrollbar-width: thin; scrollbar-color: var(--nile-colors-neutral-500, var(--ng-colors-border-primary)) transparent; } .combobox__scroll-area--single-line::-webkit-scrollbar { height: 3px; } .combobox__scroll-area--single-line::-webkit-scrollbar-track { background: transparent; } .combobox__scroll-area--single-line::-webkit-scrollbar-thumb { background: var(--nile-colors-neutral-500, var(--ng-colors-bg-quaternary)); border-radius: 3px; } .combobox__scroll-area--single-line::-webkit-scrollbar-thumb:hover { background: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400)); } /* Wrap: tags flow to multiple lines, trigger grows in height */ .combobox__scroll-area--wrap { flex-wrap: wrap; overflow: visible; } /* ── Tags inside the scroll area ── */ .combobox__scroll-area nile-tag { cursor: pointer; flex-shrink: 0; } .combobox--disabled .combobox__scroll-area nile-tag { cursor: not-allowed; } .combobox__tags-count { color: var(--nile-colors-primary-600, var(--ng-colors-text-brand-secondary-700)); font-family: var(--nile-font-family-serif, var(--ng-font-family-body)); font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm)); font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-medium)); line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-sm)); letter-spacing: 0.2px; white-space: nowrap; flex-shrink: 0; } /* ── Input wrapper inside scroll area ── */ .combobox__input-wrapper { flex: 1; min-width: 60px; display: flex; align-items: center; } .combobox__input { width: 100%; font: inherit; border: none; background: none; color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900)); cursor: inherit; overflow: hidden; padding: 0; margin: 0; -webkit-appearance: none; font-family: var(--nile-font-family-serif, var(--ng-font-family-body)); font-size: inherit; font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-regular)); text-overflow: ellipsis; line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-sm)); } .combobox__input::placeholder { font-family: var(--nile-font-family-serif, var(--ng-font-family-body)); color: var(--nile-colors-text-placeholder, var(--ng-colors-text-placeholder)); } .combobox__input:focus { outline: none; } .combobox--disabled .combobox__input { color: var(--nile-colors-dark-500, var(--ng-colors-text-disabled)); pointer-events: none; } /* ── Hidden form value input ── */ .combobox__value-input { position: absolute; top: 0; left: 0; width: 100%; height: 100%; padding: 0; margin: 0; opacity: 0; z-index: -1; } /* ── Action icons (clear, expand) ── */ .combobox__actions { display: flex; align-items: center; flex-shrink: 0; gap: var(--nile-spacing-sm, var(--ng-spacing-sm)); margin-inline-start: auto; } .combobox__clear { display: inline-flex; align-items: center; justify-content: center; border: none; background: none; padding: 0; cursor: pointer; color: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400)); transition: 150ms color; } .combobox__clear:hover { color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900)); } .combobox__clear:focus { outline: none; } .combobox__expand-icon { display: flex; align-items: center; flex-shrink: 0; transition: 250ms rotate ease; rotate: 0; } .combobox--open .combobox__expand-icon { rotate: -180deg; } /* ── Prefix / suffix ── */ .combobox__prefix, .combobox__suffix { flex: 0; display: inline-flex; align-items: center; color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600)); } .combobox__prefix { margin-inline-end: var(--nile-spacing-md, var(--ng-spacing-md)); } /* ── Listbox (dropdown) ── */ .combobox__listbox { display: block; position: relative; font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md)); font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-regular)); background: var(--nile-colors-white-base, var(--ng-colors-bg-primary)); border: solid 1px var(--nile-colors-neutral-500, var(--ng-colors-border-secondary-alt)); border-radius: var(--nile-radius-sm, var(--ng-radius-md)); padding-block: var(--nile-spacing-none, var(--ng-spacing-xs)); padding-inline: var(--nile-spacing-none, var(--ng-spacing-xs)); overscroll-behavior: none; overflow-y: auto; max-width: var(--auto-size-available-width); max-height: var(--auto-size-available-height); box-shadow: 0px 2px 4px 0px rgba(119, 125, 130, 0.15); } /* ── Options ── */ .combobox__options { font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm)); color: rgb(133, 129, 129); width: 100%; } .combobox__options.loading { opacity: 0.5; pointer-events: none; } .combobox__no-results { padding: var(--nile-spacing-lg, var(--ng-spacing-lg)); font-family: var(--nile-font-family-serif, var(--ng-font-family-body)); font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm)); color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600)); text-align: center; } .combobox__no-results-title { font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-medium)); color: var(--nile-colors-dark-700, var(--ng-colors-text-secondary-700)); } .combobox__no-results-subtitle { margin-top: var(--nile-spacing-xs, var(--ng-spacing-xs)); font-size: var(--nile-type-scale-2, var(--ng-font-size-text-xs)); color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600)); } /* ── Options (both virtual and plain) ── */ .combobox__options nile-option { width: 100%; display: block; } .combobox__options nile-option[selected] { background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary)); } .combobox__options nile-option[selected]::part(base) { color: var(--nile-colors-primary-600, var(--ng-colors-text-brand-secondary-700)); } .combobox__options-plain { display: flex; flex-direction: column; } .combobox__options-plain nile-option { flex-shrink: 0; } /* ── Top actions (Select All + Selected/All filter toggle) ── */ .combobox__top-actions { position: sticky; top: 0; z-index: 2; display: flex; flex-direction: row; align-items: center; justify-content: space-between; gap: var(--nile-spacing-lg, var(--ng-spacing-lg)); background: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary)); border-bottom: 1px solid var(--nile-colors-neutral-400, var(--ng-colors-border-secondary)); padding: var(--nile-spacing-lg, var(--ng-spacing-lg)); user-select: none; } .combobox__top-actions--disabled { opacity: 0.6; pointer-events: none; } .combobox__select-all { display: flex; align-items: center; gap: var(--nile-spacing-md, var(--ng-spacing-md)); cursor: pointer; flex: 1 1 auto; font-family: var(--nile-font-family-serif, var(--ng-font-family-body)); font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm)); line-height: 14px; letter-spacing: 0.2px; color: var(--nile-colors-dark-900, var(--ng-colors-text-primary)); } .combobox__show-toggle { display: inline-flex; align-items: center; gap: var(--nile-spacing-md, var(--ng-spacing-md)); border: none; background: none; padding: 0; border-radius: var(--nile-radius-sm, var(--ng-radius-sm)); cursor: pointer; color: var(--nile-colors-primary-600, var(--ng-colors-text-brand-secondary-700)); font-family: var(--nile-font-family-serif, var(--ng-font-family-body)); font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm)); line-height: 14px; letter-spacing: 0.2px; white-space: nowrap; } .combobox__show-toggle[disabled] { color: var(--nile-colors-primary-500, var(--ng-colors-fg-quaternary-400)); cursor: not-allowed; } /* ── Footer ── */ .combobox__footer { position: sticky; bottom: 0; background: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary)); border-top: 1px solid var(--nile-colors-neutral-400, var(--ng-colors-border-secondary)); display: flex; flex-direction: row; align-items: flex-start; padding: var(--nile-spacing-md, var(--ng-spacing-md)) var(--nile-spacing-lg, var(--ng-spacing-lg)) var(--nile-spacing-xl, var(--ng-spacing-xl)); gap: var(--nile-spacing-lg, var(--ng-spacing-lg)); justify-content: space-between; } .combobox__footer.loading { opacity: 0.5; pointer-events: none; } .combobox__footer-clear { display: inline-flex; align-items: center; color: var(--nile-colors-primary-600, var(--ng-colors-text-brand-secondary-700)); border: none; background: none; padding: 0; cursor: pointer; font-family: var(--nile-font-family-serif, var(--ng-font-family-body)); font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm)); letter-spacing: 0.2px; } .combobox__footer-clear:hover { text-decoration: underline; } /* ── Loader ── */ .combobox__loader { width: 100%; text-align: center; display: block; } .combobox__loader--icon { margin-top: var(--nile-spacing-xl, var(--ng-spacing-xl)); animation: combobox-spin 0.6s linear infinite; } .combobox__loader--center { position: absolute; display: flex; justify-content: center; align-items: center; width: 100%; height: 75%; } @keyframes combobox-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .combobox__add-option::part(base) { color: var(--nile-colors-primary-600, var(--ng-colors-text-brand-secondary-700)); } /* ── Grid layout ── */ :host([grid-columns]) .combobox__listbox { overflow-y: auto; } .combobox__grid-row { width: 100%; } .combobox__grid-row nile-option { min-width: 0; overflow: hidden; } .combobox__grid-row nile-option::part(base) { border-radius: var(--nile-radius-xs, var(--ng-radius-sm)); } /* ── Bidirectional grid layout (vertical + horizontal scroll) ── */ .combobox__listbox.combobox__listbox--bidirectional { overflow: auto; max-width: none; scrollbar-width: thin; scrollbar-color: var(--nile-colors-neutral-500, var(--ng-colors-bg-quaternary)) transparent; } .combobox__listbox--bidirectional .combobox__options { width: max-content; min-width: 100%; } .combobox__listbox--bidirectional .combobox__grid-row { width: max-content; min-width: 100%; } /* ── Horizontal grid layout ── */ .combobox__listbox.combobox__listbox--horizontal { overflow-x: auto; overflow-y: hidden; max-height: none; max-width: none; width: 100%; scrollbar-width: thin; scrollbar-color: var(--nile-colors-neutral-500, var(--ng-colors-bg-quaternary)) transparent; } .combobox__listbox--horizontal::-webkit-scrollbar { height: 6px; } .combobox__listbox--horizontal::-webkit-scrollbar-track { background: transparent; } .combobox__listbox--horizontal::-webkit-scrollbar-thumb { background: var(--nile-colors-neutral-500, var(--ng-colors-bg-quaternary)); border-radius: 3px; } .combobox__listbox--horizontal::-webkit-scrollbar-thumb:hover { background: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400)); } .combobox__options--horizontal { display: block; width: max-content; min-width: 100%; } .combobox__grid-col { border-right: 1px solid var(--nile-colors-neutral-200, var(--ng-colors-border-secondary)); } .combobox__grid-col:last-child { border-right: none; } .combobox__grid-col nile-option { width: 100%; display: block; } .combobox__grid-col nile-option::part(base) { border-radius: 0; } /* ── Group headers (data-driven grouping) ── */ /* Plain (non-virtualized) listbox: sticky relative to the scroll container. * Activated only when the host has [sticky-group-header]. */ :host([sticky-group-header]) .combobox__options-plain .combobox__group-header { position: sticky; top: calc(var(--group-depth, 0) * 28px); z-index: 1; } /* Virtualized listbox: each row is absolutely positioned by the virtualizer. * Sticky doesn't pin against the scroll container because the row wrapper's * transform creates a containing block. Instead we render a separate * overlay inside the listbox that mirrors the currently-active group * header (computed on scroll). */ .combobox__group-header-slot { pointer-events: none; } .combobox__group-header-slot .combobox__group-header { height: 100%; box-sizing: border-box; } .combobox__group-sticky-overlay { position: sticky; top: 0; z-index: 2; pointer-events: none; } .combobox__group-sticky-overlay .combobox__group-header { box-shadow: 0 1px 0 0 var(--nile-colors-neutral-300, var(--ng-colors-border-secondary)); } .combobox__group-header { display: flex; align-items: center; gap: 6px; box-sizing: border-box; width: 100%; height: 100%; /* Match the listbox's natural inline padding so the header sits like a * section divider, edge-to-edge with options. Nested groups indent by * depth. Override with --combobox-group-header-indent if needed. */ padding-block: 8px; padding-inline-end: var(--nile-spacing-lg, var(--ng-spacing-lg)); padding-inline-start: calc(var(--combobox-group-header-indent, var(--nile-spacing-lg, var(--ng-spacing-lg))) + var(--group-depth, 0) * 16px); font-family: var(--nile-font-family-sans-serif, var(--ng-font-family-body)); font-size: var(--nile-type-scale-2, var(--ng-font-size-text-xs)); font-weight: var(--nile-font-weight-semibold, var(--ng-font-weight-semibold)); line-height: 1; text-transform: uppercase; letter-spacing: 0.06em; color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600)); background: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary)); border-bottom: 1px solid var(--nile-colors-neutral-300, var(--ng-colors-border-secondary)); pointer-events: none; user-select: none; } .combobox__group-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .combobox__group-prefix { flex-shrink: 0; color: inherit; } /* ── Help / Error ── */ .form-control__help-text { display: none; } .form-control--has-help-text .form-control__help-text { display: block; color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600)); margin-top: var(--nile-spacing-lg, var(--ng-spacing-lg)); font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm)); } `; export default [styles];