Fandry UI
Forms

Select

A custom listbox-style select, with optional grouped options.

fandry-select

Example

Link to section Example

Custom colors and parts

Link to section Custom colors and parts

The same component with a few --fd-* tokens set around it and its parts restyled. The code is under Parts below.

Props

Link to section Props
PropTypeDefaultDescription
labelstring''Visible label.
placeholderstring''Shown when nothing is selected.
options{ label, value, disabled?, component?, componentProps? }[][]Flat option list. An option's component (with componentProps) draws its own row instead of the label -- see the custom options example.
groups{ label, options }[][]Grouped option list (used instead of options).
valuestring''Selected value. '' (or null) is no selection and shows the placeholder, unless an option has that value: give one value: '' to offer "None".
change (event)CustomEvent<string>—Fires when the user picks a different value; event.detail is the new value. Not fired when value is set from code.
help-textstring''Helper text below the field.
error-textstring''An error shown under the field: the field is invalid while it has one (aria-invalid, the invalid state), and a screen reader hears it when it appears and when the field is focused.
label · help-text · error-text (slots)slotthe propsMarkup in place of the label, help text or error text. Shown even without the matching prop.

Parts

Link to section Parts

Style the elements inside the component from your own CSS with ::part(). Every fandry component renders in native shadow DOM, so parts work on LWR and Salesforce alike. For colors, spacing, radius and type across many components, set the --fd-* tokens instead. The code for the "Custom colors and parts" example above:

PartDescription
baseThe outermost element.
labelThe label.
requiredThe required-field asterisk.
controlThe box the field draws: a text field's border, a select's button, a checkbox's box, a radio's circle, a switch's track.
valueThe selected value, as shown in the closed field.
chevronThe dropdown arrow.
listboxThe list of options.
optionOne option.
groupA group of options.
group-labelA group's heading.
help-textThe help text under the field.
error-textThe error under the field. In the page even while empty, so style it only for a field that is invalid.
panelThe surface that opens: a dropdown's list, a popover, a tooltip, a dialog, a loading overlay's box.

States are extra names on a part while the state is on. Name both to style one state, e.g.fandry-checkbox::part(control checked).

StateDescription
disabledA control, option or item that cannot be used.
invalidA field that has error text.
selectedThe chosen option, a selected table row, or the selected tab.
activeThe option the keyboard or pointer is on.
<!-- template -->
<div class="brand narrow">
  <fandry-select label="Size" placeholder="Choose a size" options={options} value="m"></fandry-select>
</div>

/* css */
/* Scoped to this demo. Set the same --fd-* tokens on :root to theme
   every fandry-* component on the site. */
.brand {
  --fd-radius-md: 0.75rem;
  --fd-border-focus: 160 84% 36%;
  --fd-ring-color: 160 84% 36%;
  --fd-bg-muted: 160 40% 94%;
}

fandry-select::part(control) {
  background: hsl(160 40% 98%);
  font-weight: 600;
}

fandry-select::part(panel) {
  box-shadow: 0 12px 32px hsl(160 40% 20% / 0.18);
}

fandry-select::part(option) {
  padding-block: 0.5rem;
}

/* A state: only the chosen option. */
fandry-select::part(option selected) {
  font-weight: 700;
  color: hsl(160 84% 26%);
}
​

Code

Link to section Code
<fandry-select
  label="Plan"
  placeholder="Choose a plan"
  options={planOptions}
  value="pro"
></fandry-select>
​

Example: Custom options

Link to section Example: Custom options

Code

<!-- template -->
<fandry-select label="Plan" options={planOptions}
  value={value} onchange={handleChange}></fandry-select>

// component
import PlanRow from 'my/planRow'; // your LWC: @api icon, label, hint

planOptions = [
  {
    label: 'Free', value: 'free', component: PlanRow,
    componentProps: { icon: '🌱', label: 'Free' }
  },
  {
    label: 'Pro', value: 'pro', component: PlanRow,
    componentProps: { icon: '💎', label: 'Pro', hint: 'Popular' }
  },
  { label: 'Enterprise', value: 'enterprise', disabled: true } // plain option
];

// The component draws only the inside of the row; the row keeps its
// highlight, hover, keyboard and click, and `label` stays the accessible
// name and what typeahead matches, so give every option a real one.
// The chosen option's component is also shown in the closed control.
//
// On Salesforce this uses lwc:is: fandry-select's .js-meta.xml needs the
// lightning__dynamicComponent capability (API 55+), which `fandry add` writes.
​

Example: A long list, with the keyboard

Link to section Example: A long list, with the keyboard

Code

<!-- template -->
<fandry-select label="Country" placeholder="Choose a country"
  options={countryOptions} value={value} onchange={handleChange}></fandry-select>

// component
handleChange(event) {
  this.value = event.detail;
}

// The list scrolls once it is taller than --fd-listbox-max-height, and
// the option the keyboard is on is kept in view. Hovering never scrolls.
//
// Closed:  Enter, Space, ArrowDown or ArrowUp open the list
//          ArrowLeft / ArrowRight choose the previous or next option
//          typing chooses the option that starts with what was typed
// Open:    ArrowUp / ArrowDown move, and stop at the first and last option
//          Home / End, Page Up / Page Down move further
//          typing moves to a match: "new z" finds New Zealand, and "s"
//          pressed again steps through the options that start with s
//          Enter or Space choose; Escape or Tab close without choosing
​