Back to Tooljet

Select — Rocket Design Spec

frontend/src/components/ui/Rocket/Select/Select.spec.md

3.20.154-lts6.7 KB
Original Source

Select — Rocket Design Spec

<!-- figma: https://www.figma.com/design/XQdM9x8x9YHcj1lUK8abUG/Rocket-components?node-id=6866-4557 --> <!-- synced: 2026-03-17 -->

Overview

Select is a trigger + dropdown combo for choosing one value from a list. The trigger reuses the same visual tokens as Input (bg, border, focus ring, sizing). The dropdown is a popover panel with selectable items.

Wraps shadcn Select (Radix @radix-ui/react-select).

Sub-components

ComponentWrapsToken overrides
SelectTriggershadcn SelectTriggerSame tokens as Input — bg, border, focus, hover, disabled, error, sizes
SelectContentshadcn SelectContentbg-surface-layer-01, border-weak, rounded-lg (10px), elevation-300
SelectItemshadcn SelectItem32px height, text-default, hover → interactive-hover, rounded-md

Re-exported from shadcn (no token overrides)

Select (root), SelectValue, SelectGroup, SelectLabel, SelectSeparator

Props (SelectTrigger)

PropTypeValuesDefault
sizestringlarge | default | smalldefault
classNamestring
disabledbooleanfalse

Sizes (trigger)

ValueHeightFont sizeTailwind
large40px14px / 20pxtw-h-10 tw-text-lg
default32px12px / 18pxtw-h-8 tw-text-base
small28px12px / 18pxtw-h-7 tw-text-base

Token Mapping — Trigger

ElementStateToolJet tokenTailwind class
backgrounddefault--background-surface-layer-01tw-bg-background-surface-layer-01
borderdefault--border-defaulttw-border-border-default
borderhover--border-stronghover:tw-border-border-strong
textdefault--text-defaulttw-text-text-default
placeholderdefault--text-placeholderdata-[placeholder]:tw-text-text-placeholder
shadowdefaultnonetw-shadow-none
focus ringfocus--interactive-focus-outlinefocus:tw-ring-2 focus:tw-ring-[var(--interactive-focus-outline)] focus:tw-ring-offset-1
chevron icondefault--icon-defaulttw-text-icon-default
bordererror--border-danger-strongaria-[invalid=true]:tw-border-border-danger-strong
backgrounderror--background-error-weakaria-[invalid=true]:tw-bg-background-error-weak
backgrounddisabled--background-surface-layer-02disabled:tw-bg-background-surface-layer-02
textdisabled--text-disableddisabled:tw-text-text-disabled
borderdisablednone (no border)disabled:tw-border-transparent

Token Mapping — Content (dropdown)

ElementTokenTailwind class
background--background-surface-layer-01tw-bg-background-surface-layer-01
border--border-weaktw-border-border-weak
border radius10pxtw-rounded-[10px]
shadowelevation-300tw-shadow-elevation-300
padding8pxtw-p-2

Token Mapping — Item

ElementStateTokenTailwind class
textdefault--text-defaulttw-text-text-default
height32pxtw-h-8
paddingtw-px-2 tw-py-1.5
border-radius6pxtw-rounded-md
backgroundhover/focus--interactive-hoverfocus:tw-bg-interactive-hover
check iconselected--text-brandtw-text-text-brand

Composition

Basic

jsx
<Select>
  <SelectTrigger>
    <SelectValue placeholder="Choose..." />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="a">Option A</SelectItem>
    <SelectItem value="b">Option B</SelectItem>
  </SelectContent>
</Select>

With Field

jsx
<Field>
  <FieldLabel>Country</FieldLabel>
  <Select>
    <SelectTrigger>
      <SelectValue placeholder="Select country" />
    </SelectTrigger>
    <SelectContent>
      <SelectItem value="us">United States</SelectItem>
      <SelectItem value="uk">United Kingdom</SelectItem>
    </SelectContent>
  </Select>
</Field>

Notes

  • Trigger chevron: ChevronDown (lucide) when closed, arrow rotates via Radix data attributes.
  • allowClearSelection from Figma is not in v1 — can be added later as an enhancement.
  • Leading visual on trigger (icon before placeholder) from Figma — supported via children composition inside SelectTrigger.
  • Leading/trailing visuals on items — supported via custom content inside SelectItem children.
  • Disabled state uses --background-surface-layer-02 bg token (consistent with Input).

Truncating long values (opt-in pattern)

Select itself does not auto-truncate selected values or option rows. Long content already clips visually because shadcn's SelectTrigger carries [&>span]:tw-line-clamp-1 on direct child spans. To get a hover tooltip showing the full string, opt in by composing with TruncatingText. TruncatingText uses the browser's native title attribute, so no provider or extra wiring is needed.

Selected value (in the trigger)

The shadcn line-clamp targets the trigger's direct child spans. Wrap inside a <div> to take that selector out of the picture, then apply TruncatingText. The selected value text is rendered by Radix from context, so pass it explicitly via the title prop:

jsx
<SelectTrigger>
  <div className="tw-min-w-0 tw-flex-1">
    <TruncatingText title={selectedLabel}>
      <SelectValue placeholder="Select query" />
    </TruncatingText>
  </div>
</SelectTrigger>

The div is a flex item of the trigger (which is display: flex); tw-min-w-0 lets it shrink below its content width, tw-flex-1 lets it claim the available space so the chevron sits flush right.

If the consumer doesn't already track the selected label as state, pass text={selectedLabel} instead of children — but the SelectValue child form is the cleanest fit for most callsites because Radix handles the placeholder fallback automatically.

Option rows (in the dropdown)

SelectItem children render as text inside Select.ItemText. Wrap the label children in TruncatingText per row — string children make auto-detection work without the manual title prop:

jsx
<SelectItem value={item.value}>
  <TruncatingText>{item.name}</TruncatingText>
</SelectItem>

Why opt-in, not built-in

Truncation is a layout decision, not a primitive concern. Most callsites either size the trigger generously enough to never overflow, or actively want clipped text without a tooltip. Forcing TruncatingText into SelectValue would also collide with the shadcn line-clamp selector on the trigger — fixing that cleanly would require modifying the primitive itself. The opt-in pattern keeps the primitive untouched and gives consumers control where the truncation actually matters.