Pricing

SelectButton handbook

v1.0.2 · @snowui-design-system/components

License: Before reading component documentation, source, or npm usage instructions for the first time, read the full LICENSE. Reuse that review for the same task and version. Public API configuration and internal implementation changes have different license implications. All components use the unified runtime package; source rights remain governed by the license.

Overview

Offer a compact, button-shaped single-choice dropdown for toolbars, filters, and option switching.

When to use it

Use it for a button-triggered selection or command menu. Use Select for a form-style single-choice field and OverflowActions to move several actions into an overflow menu as width changes.

  • Each options entry needs a unique string value. label customizes the trigger text; children replaces the list.

  • Action mode neither updates value nor fires onchange. Root Props configure the Button; parts has no Button entry.

Quick start

This example shows the recommended basic composition. See the sections below for more cases and composition limits.

<script lang="ts">	import { SelectButton } from '@snowui-design-system/components';	const componentOptions = [		{ value: 'button', label: 'Button' },		{ value: 'button-group', label: 'ButtonGroup' },		{ value: 'copy-button', label: 'CopyButton' },		{ value: 'select-button', label: 'SelectButton' }	];</script> <SelectButton	placeholder="Select"	ariaLabel="Select a component"	options={componentOptions}/>

API

Keyword Type Default Description
value SelectValue — Current selection (string, number, or undefined); supports bind:value and takes precedence over defaultValue. Selecting an option writes its string value. Action mode does not retain a selection.
defaultValue SelectValue — Fallback selected value when value is undefined. Used for the display only in persistent mode; after the first selection, value drives it.
options SelectOption[] [] Option data: each entry has a string value, label, and optional disabled. Generates MenuItems by default; explicit children register their own options.
placeholder string — Hint when nothing is selected. The action-mode trigger always displays it. Without a label, selected option text, or placeholder, trigger text is empty.
name string — Form field name. A nonempty name creates a hidden input that submits the current selected value as a string.
form string — ID of the hidden input’s form, which may be outside the component. Applies only after name creates the input.
required boolean false Required marker passed to Select. The current implementation does not use native constraint validation and does not block an empty submission; the application must validate it.
disabled boolean false Disables the trigger and prevents opening or changing options. The current hidden input is not disabled by this marker; an existing value may still submit with the form.
readonly boolean false Prevents users from opening or changing options through the trigger while preserving display and external value updates. Does not disable the hidden input.
invalid boolean false Passes invalid state to the Select wrapper. The current Button trigger does not automatically gain an error border or aria-invalid; this does not replace application validation or error text.
ariaLabel string — Accessible name for the trigger Button; set it when no visible label is provided.
showIndicator boolean true Shows the dropdown indicator. false hides even a custom indicator without affecting selection.
search boolean false Enables built-in search in the default Listbox; parts.Listbox.search can override it. In explicit-children mode, configure search on your own Listbox.
selectionMode "persistent" | "action" "persistent" persistent stores the selection and shows the option label. action calls only onAction, closes the list, and keeps the placeholder without updating value or firing onchange.
label Snippet<[SelectButtonLabelContext]> — Replaces trigger text. Context contains value, option, label, and placeholder; indicator and Button interaction remain.
indicator Snippet<[SelectButtonIndicatorContext]> — Replaces the indicator graphic. Receives open and disabled; rendered only when showIndicator=true.
children Snippet — Explicit Listbox/MenuItem content that replaces the default list. It does not supply trigger text; use label to customize that.
parts ComponentPartsOf<{ Listbox: typeof Listbox; Input: typeof Input; MenuItem: typeof MenuItem; }> — Configures the built-in list, search input, and options. There is no parts.Button; pass Button styling at the root. Explicit children configure their own items.
onchange (event: Event) => void — Called after a different value is selected in persistent mode, with a change Event. Read the new value via bind:value. Repeated selection and action mode do not fire it.
onAction (value: string) => void — In action mode only, receives the executed option’s value. The list then stays closed; the component does not store a selection.
onclick (event: MouseEvent) => void — Called after the trigger opens or closes. Not called while disabled or read-only; preventDefault() cannot undo the completed toggle.
onkeydown (event: KeyboardEvent) => void — Called after the component handles selection keys such as arrows, Enter, and Escape, with the original KeyboardEvent. Read-only mode also forwards keys; this callback cannot cancel an operation already completed.

See the base component documentation for inherited capabilities not redeclared here. This table lists only named public Props declared by this component.

Usage boundaries and details

Usage

<script lang="ts">  import { SelectButton } from "@snowui-design-system/components";  let value = $state<string | number | undefined>(undefined);</script> <SelectButton  bind:value  variant="borderless"  options={[{ value: "recent", label: "Recently updated" }]}  parts={{ Input: { placeholder: "Search" } }}/>

Compatible Button Props are flat root Props. Button is the host; there is no parts.Button. Select provides only a nonvisual wrapper and adds no field border, background, or radius. The real Button host and its public Props determine SelectButton’s final appearance. Its default auxiliary subtree is Listbox → Input + MenuItem, configurable through parts.Listbox/Input/MenuItem. Explicit children replace the default Listbox.

The default label shows the selected option or placeholder; the label Snippet replaces only that label. The default indicator uses arrow-line-down; hide it with showIndicator={false} or replace it with an indicator Snippet.

selectionMode="persistent" is the default ongoing selection mode: the trigger shows the selected item. selectionMode="action" executes commands: the trigger always shows the placeholder, and clicking an option only calls onAction(value) without storing a selection. A separate MenuButton is unnecessary.

SelectButton hides search by default; enable it with search. Its Listbox takes a fixed width from the longest option; all other options fill that width, and no selected checkmark appears. Listbox supplies the search placeholder, a 160px minimum width during search, and width locking after open. bare and emphasis pass directly to the Button host. Bare mode therefore defaults to 100% emphasis; explicitly use emphasis="muted" for a secondary trigger.

Data and Snippet contexts

SelectValue = string | number | undefined. SelectOption is { value: string; label: string; disabled?: boolean }; option values should be stable and unique.

SelectButtonLabelContext is { value: SelectValue; option: SelectOption | undefined; label: string; placeholder: string | undefined }. label resolves from option text, then placeholder, then an empty string. SelectButtonIndicatorContext is { open: boolean; disabled: boolean }.

Form submission and selection behavior reuse Select; see Button for visual Props. The current limitations of required and invalid are described in their Prop entries; do not infer native validation from their names.

This section is protected. An AI must request user review before modifying it.


SelectButton style overrides

Read the full LICENSE first; reuse that review for the same task, version, and scope.

First use public component Props to match the desired appearance, preserving the existing look where possible. If changes are necessary, follow the style selection and override order: use your own class (including Tailwind already in the project) or an instance style. The names below are public overrides actually consumed by source; check their scope and do not modify private DOM. Choose the correct SnowUI token family. External apps need not install SnowUI website utilities.

This component source does not directly consume a registered component-specific override. Style composed children through public parts or an explicit child; do not guess variable names.

Design guide · Tokens · Composition boundaries

SelectButton types and states

Required Props: no named required Props.

Two-way binding: bind:value.

Inherited declaration: Omit<ButtonProps, ControlledButtonKeys>. Consult the base component’s public documentation for inherited capabilities; fields excluded by Omit cannot be used as if inherited unchanged.

Shared Frame API · Back to API

The following type declarations are actually referenced by public Props and come from source. A Svelte Snippet denotes a content fragment; ComponentProps denotes the Props of the corresponding component.

SelectValue

Source: components/src/components/Select.svelte

export type SelectValue = string | number | undefined;

SelectOption

Source: components/src/components/Select.svelte

export type SelectOption = ListboxItem;

ListboxItem

Source: components/src/components/Listbox.svelte

export interface ListboxItem {        value: string;        label: string;        disabled?: boolean;    }

SelectButtonLabelContext

Source: components/src/components/SelectButton.svelte

export interface SelectButtonLabelContext {        value: SelectValue;        option: SelectOption | undefined;        label: string;        placeholder: string | undefined;    }

SelectButtonIndicatorContext

Source: components/src/components/SelectButton.svelte

export interface SelectButtonIndicatorContext {        open: boolean;        disabled: boolean;    }

ComponentPartsOf

Source: components/src/logic/component-parts.svelte.ts

export type ComponentPartsOf<    T extends Record<string, Component<any>>,> = {    [K in keyof T]?: ConfigurableComponentPartProps<T[K]>;};

ConfigurableComponentPartProps

Source: components/src/logic/component-parts.svelte.ts

export type ConfigurableComponentPartProps<C extends Component<any>> = Partial<    Omit<ComponentProps<C>, ComponentPartControlledKey>>;

ComponentPartControlledKey

Source: components/src/logic/component-parts.svelte.ts

export type ComponentPartControlledKey =    | "children"    | "as"    | "value"    | "defaultValue"    | "open"    | "selected"    | "checked"    | "disabled"    | "readonly"    | "id"    | `on${string}`    | `aria-${string}`;

ButtonProps

Source: components/src/components/SelectButton.svelte

type ButtonProps = ComponentProps<typeof Button>;

ControlledButtonKeys

Source: components/src/components/SelectButton.svelte

type ControlledButtonKeys =        | "children"        | "as"        | "value"        | "defaultValue"        | "disabled"        | "readonly"        | "id"        | "onclick"        | "onkeydown"        | "aria-label"        | "aria-haspopup"        | "aria-expanded"        | "aria-controls"        | "aria-activedescendant";