ComponentsSelect
Select
atomA themed select trigger + option menu — the native picker, restyled to the kit.
Deploy region
Where your app runs.
Recipe CSS
This is the exact CSS your kit ships for Select — token-driven, so it re-themes with every knob. Get it (and the rest) from the configurator's Use kit panel.
/* === Select trigger === */
.select-trigger {
display: flex;
align-items: center;
justify-content: space-between;
/* Same height as inputs (--k-in-h) so a select sitting beside a search
field stays aligned at EVERY density — adjacent-element rule (#190).
Was a fixed padding-block:8 that diverged from .in as density grew. */
min-height: var(--k-in-h-default, 40px);
padding-block: 0;
padding-inline: max(var(--k-s-12), calc(var(--k-radius-md) * 0.6));
/* --k-field-radius (not --k-radius-md) so Plain flattens to a straight
underline — radius-md here left the bottom hairline curling up at the ends. */
border-radius: var(--k-field-radius);
background: var(--k-field-bg);
border: var(--k-bw, 1px) solid var(--k-field-border-color); border-bottom-color: var(--k-field-underline-color);
color: var(--k-fg);
font-size: var(--k-type-small);
font-family: inherit;
text-align: left;
width: 100%;
cursor: pointer;
}
.select-trigger:hover { border-color: var(--k-state-border, var(--k-fg-faint)); }
/* Invalid state (B1) — a select with a validation error reads like an errored
* input field: the danger border + a soft danger halo. Mirrors .in.is-error so
* a select sitting in a form validates with the same language. Toggle with
* .is-error or aria-invalid="true". */
.select-trigger.is-error,
.select-trigger[aria-invalid="true"] {
border-color: var(--k-input-error-border);
box-shadow: 0 0 0 var(--k-ring-w) color-mix(in srgb, var(--k-input-error-border) 22%, transparent);
}
/* Native <select class="select"> as a first-class PREVIEW form control.
* The configurator chrome has its OWN unscoped `.select` in panel.css
* (hardcoded 8px radius + --app-* colours). App/preview screens must not
* borrow that — scope this one to .cockpit-preview and key it to --k-* so a
* native select matches the .in search field beside it (same radius, surface,
* border, height) and tracks the box/input radius like every other field.
* Buttons keep their independent --k-radius-button on purpose (#75). */
.cockpit-preview select.select {
min-height: var(--k-in-h-default, 40px);
padding: 0 var(--k-s-28) 0 max(var(--k-s-12), calc(var(--k-radius-md) * 0.6));
background-color: var(--k-field-bg);
border: var(--k-bw, 1px) solid var(--k-field-border-color); border-bottom-color: var(--k-field-underline-color);
border-radius: var(--k-field-radius);
color: var(--k-fg);
font-size: var(--k-type-small);
font-family: var(--k-font-body);
appearance: none;
-webkit-appearance: none;
background-image: url("data:image/svg+xml,%3Csvg width='10' height='6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23888' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 11px center;
cursor: pointer;
}
.cockpit-preview select.select:hover { border-color: var(--k-state-border, var(--k-fg-faint)); }
.cockpit-preview select.select:focus,
.cockpit-preview select.select:focus-visible {
outline: none;
/* Match the .in focus exactly — --k-ring border + --k-ring-halo (28%) shadow.
Was an UNDEFINED --k-focus-ring token (silently fell back to a 22% halo) so
the native select's focus read lighter than every sibling field. */
border-color: var(--k-ring);
box-shadow: 0 0 0 var(--k-ring-w) var(--k-ring-halo);
}