Design
llms.txt digitalcrew.tech

Forms

TypedOptionPicker

A searchable, grouped picker for long option lists (Popover + Command), in single and multi versions.

MaxFormsDigitalCrew.TypedOptionPicker
TypedOptionPicker · liveOpen

Guidelines#

Use it for choices with more than ~15 options or with groups: buyer roles, industries, sender accounts. Short lists belong in a Select.

What you provide: value (or values for TypedMultiOptionPicker), options as { value, label, group?, description? }, onChange, ariaLabel, id, and a placeholder (default "Choose…"). Ungrouped options fall under "Choices".

Anatomy: a full-width 44px trigger (min-h-11), the popover as wide as the trigger. The multi version lists up to two labels, then summarises as "N selected".

Facts#

GroupForms
ProductMax
Globalwindow.DigitalCrew.TypedOptionPicker
Sourcemax-agent: src/components/typed-option-picker.tsx
Import in the appimport { TypedOptionPicker } from "@/components/typed-option-picker";

API#

TypeScript declarations emitted from src/components/typed-option-picker.tsx (the module also exports TypedOptionPicker, TypedMultiOptionPicker).

export type TypedOption = {
    value: string;
    label: string;
    group?: string;
    description?: string;
};
export declare function TypedOptionPicker({ value, options, onChange, ariaLabel, id, placeholder, }: {
    value: string;
    options: TypedOption[];
    onChange: (value: string) => void;
    ariaLabel: string;
    id?: string;
    placeholder?: string;
}): JSX.Element;
export declare function TypedMultiOptionPicker({ values, options, onChange, ariaLabel, id, placeholder, }: {
    values: string[];
    options: TypedOption[];
    onChange: (values: string[]) => void;
    ariaLabel: string;
    id?: string;
    placeholder?: string;
}): JSX.Element;

Example#

The code of the preview above: plain React.createElement against window.DigitalCrew, with realistic data.

<div id="root" class="p-6"></div>
<script>
(function () {
  var h = React.createElement, DC = window.DigitalCrew, I = DC.Icons;
var OPTIONS = [
  { value: "vp_sales", label: "VP Sales", group: "Revenue" },
  { value: "head_growth", label: "Head of Growth", group: "Revenue" },
  { value: "cfo", label: "CFO", group: "Finance", description: "Signs off budgets over 50k" },
  { value: "cto", label: "CTO", group: "Technology" }];
function App() {
  var one = React.useState("vp_sales"), many = React.useState(["cfo", "cto", "head_growth"]);
  return h("div", { className: "grid grid-cols-2 gap-8" },
    h("div", { className: "flex flex-col gap-2" }, h(DC.Label, null, "Buyer role"),
      h(DC.TypedOptionPicker, { value: one[0], options: OPTIONS, onChange: one[1], ariaLabel: "Buyer role" })),
    h("div", { className: "flex flex-col gap-2" }, h(DC.Label, null, "Also involve"),
      h(DC.TypedMultiOptionPicker, { values: many[0], options: OPTIONS, onChange: many[1], ariaLabel: "Also involve" })));
}
  ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>