Mono control family

Proposal B: Button (incl. icon-only), Dropdown & Toggle all speak one mono language — JetBrains Mono, radius 3, uppercase, 0.62rem, one standard height (the dropdown's, 24px) — drawn from a limited set of color schemes rather than a free-form hue per call site. Toggle segments regular weight, bold on the selected one. The toggle is the real shipped component (dropped from the /venact/ bundle); the button & dropdown are drawn at the target look the plan would make real. Decide here: how many schemes, which hues, how the states read.

The limited color schemes — 9 schemes: neutral + 5 node hues + green + mentor + danger

Each scheme is a light fill / mid border / dark text triple. The studio hues already live in NODE_COLORS; the question is whether the family draws from a closed named set like this, or keeps deriving from an arbitrary tint.

Button — the CREATE / OPEN / CLONE AS look, one per scheme

default
disabled
real landing cluster (as it ships today)
icon + label — the git action buttons (GitStatusPanel)
icon-only — same component, X icon instead of a label (OPTIONS “remove option”)

The remove-option [x] is just the button with an icon and no text — square at the standard height. Shown in danger (its real role) and a few other schemes to show icon-only isn't tied to red. The git buttons show the icon + label form (green = in-sync, blue = branch, neutral = actions).

Dropdown — the TEMPLATE IDENTITY base-type selector

interactive — click to unfold
closed states, one per scheme

Real base-type picker at controlStyle (mono, radius 3, 0.62rem) — click the live one to see the menu unfold with tinted rows. Option values here render in natural case (agreed).

Combobox — NEW: a typed field for the family, used first for DATA TYPES

filterable select — must resolve to a real type
editable — ↵ also accepts a free value

The field is not a textbox — it's the blue underscore (the shared inlineRenameFieldStyle: transparent, no border, inset 0 -2px 0 #3b82f6), so a typed field reads as the same affordance as an inline rename, not a foreign form input. Try it: type tim — the list filters on contains (so datetime shows too), while the field shows an inline ghost completion of the first alphabetical prefix match (tim dark + e gray). Type int → list shows bigint/smallint too, ghost completes integer. Where nothing starts with what you typed, there's no ghost — just your dark text.

Keys: ↑ ↓ move the highlight · Tab accepts the highlighted/ghost option (both modes) · Enter accepts the option in select mode, but accepts what you typed in editable mode · Esc / blur reverts. In select mode with no match, confirm is refused (the underline shakes); in editable mode a no-match Enter commits the new value.

Chevron + dynamic width: a chevron at the end marks it as a combobox (click it to open, same glyph the Dropdown carries). The underline is dynamic-width — it grows to fit the value as you type but never shrinks below the min the call site sets; the chevron adds its own length beyond that.

Combobox · asset types — the real ROLES / DATA-tab consumer: grouped, label shown / id committed

standard template — 12 asset types, grouped
eSQL template — non-engine tables greyed (a reason, not vanished)

The real asset_types registry (12 entries from shared-config-release-constants.yaml). Browse with the field empty → the menu shows the Files / Folders / Tables group headers. Start typing (e.g. tab, my, lake) → headers drop and it goes flat, filtered on the label. The field shows the human label (Parquet); the committed value is the id (parquet) under the hood. In the eSQL variant the table types with no registered engine are greyed & unselectable with a reason (reusing the family's per-option disabled + onDisabledClick), rather than silently disappearing.

Usable as a plain dropdown, too. When the field holds an exact match of one option (e.g. open a filled field — Parquet is already there), the menu re-expands to the full grouped list with that option highlighted, so you can browse to a different one without clearing first. And while a filter is hiding options, a · · · row at the bottom reveals the rest (keeping what you typed) — try my then click ···.

Toggle — real component, tint per scheme

join type — already this exact toggle (OPTIONS join-type selector)

The join-type “slider” is already a <venact-segmented-toggle> today ([OptionsEditor] icon-only + describe) — so it's the same component for free. Shown here with text labels; the real one uses Venn-diagram join icons and a description readout to the right.

This is the shipped <venact-segmented-toggle>. Passing each scheme's border hue as tint derives the whole palette — visual proof of the “derive from one hue” path. Compare its fill against the button/dropdown swatches above: if they match, one derivation feeds the whole family.

Icons — every app icon is now available by name in the bundle

Drop <venact-icon name="InnerJoin"> for any glyph venact uses — the full lucide set we import (130) plus the custom venact glyphs (join icons, set-square, ports, Abc…). Same registry feeds toggle/button icon options, so mocks use the genuine icons, never look-alikes.

Cohesion — all three in one scheme, side by side

Dial it in — test an arbitrary hue against the family

SAMPLE PY
border #167ACE · fill #E7F2FB · text #0F4C82

Answers: does the limited set need to be a fixed enum, or is any hue → derived scheme good enough that call sites keep passing tint from their own SSOT?