Select With Extras
SelectWithExtras is a headless enhanced select component that wraps a native <select> element with optional content areas before and after it. This allows consumers to place supplementary elements such as icons, flags, status indicators, or helper text alongside the select without breaking its accessibility.
Use SelectWithExtras when you need a native select dropdown with additional visual context. For example, displaying a country flag before a country selector, showing a unit label after a measurement selector, or adding an icon before a category picker. The component preserves full native select behavior including keyboard navigation, form submission, and screen reader support.
Implementation Notes
- Renders a wrapper
<div>containing optionalbeforeslot, a native<select>, and optionalafterslot - The
<select>element receivesaria-labelfor accessibility, with two-way binding - Supports
requiredanddisabledattributes on the native select - Supports two-way binding for the
valueprop, enabling two-wayvaluebinding from the parent - The
beforeandafterslots are conditionally rendered only when provided - Spreads
restPropsonto the wrapper div for consumer customization
Props
label: string (required) -- accessible label for the select element, applied viaaria-labelvalue: string (default:"") -- the currently selected value; two-way bindable viavaluerequired: boolean (default:false) -- whether the select is required for form validationdisabled: boolean (default:false) -- whether the select is disabledchildren: slot (required) --<option>elements for the selectbefore: slot (optional) -- content rendered before the select elementafter: slot (optional) -- content rendered after the select element...restProps: unknown -- additional attributes spread onto the wrapper<div>element
Usage
Country selector with a flag icon before the select:
<SelectWithExtras label="Country" value={country}>
{#snippet before()}<span class="flag-icon">🏳</span>{/snippet}
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
<option value="fr">France</option>
</SelectWithExtras>
Currency selector with symbol after the select:
<SelectWithExtras label="Currency" value={currency}>
<option value="GBP">British Pound</option>
<option value="USD">US Dollar</option>
<option value="EUR">Euro</option>
{#snippet after()}<span class="currency-symbol">£</span>{/snippet}
</SelectWithExtras>
Unit selector with a label before:
<SelectWithExtras label="Measurement unit" value={unit}>
{#snippet before()}<span>Unit:</span>{/snippet}
<option value="kg">Kilograms</option>
<option value="lb">Pounds</option>
</SelectWithExtras>
Keyboard Interactions
- Tab: Moves focus to the native select element
- Arrow Up / Arrow Down: Navigates between options (native select behavior)
- Space / Enter: Opens the select dropdown on some platforms (native select behavior)
- Escape: Closes the dropdown if open (native select behavior)
ARIA
aria-label={label}-- provides an accessible name for the select element so screen readers announce its purpose
When to Use
- Use SelectWithExtras when a native select dropdown needs supplementary visual context such as icons, flags, or unit labels alongside the options.
- Use SelectWithExtras to preserve full native select behavior (keyboard navigation, form submission, screen reader support) while adding decorative elements.
- Use SelectWithExtras for country selectors with flag icons, currency selectors with symbols, or unit selectors with labels.
- Use SelectWithExtras when the before/after content is purely decorative or informational.
When Not to Use
- Do not use SelectWithExtras when a native Select without extra visual context is sufficient.
- Do not use SelectWithExtras for free-text search or filterable dropdowns -- use Combobox instead.
- Do not use SelectWithExtras when the before/after content is interactive -- interactive elements in these slots can confuse keyboard navigation.
Headless
This headless component provides the semantic structure of a native <select> element wrapped in a container with optional before/after slots, along with proper aria-label for accessibility. The consumer provides all visual styling for the wrapper, the select element, and any supplementary content placed in the before/after slots.
Styles
The consumer provides all CSS styling. The component renders with a .select-with-extras class for targeting. No default styles are included — this is a fully headless component.
Testing
- Verify the component renders a
<div>element with classselect-with-extras - Verify aria-label={label}` -- provides an accessible name for the select element so screen readers announce its purpose
- Verify keyboard interactions work correctly
- Verify pass-through attributes are applied
Advice
- Designers: Keep before/after content compact so it does not visually overwhelm the select control. Use consistent icon sizes and spacing across all SelectWithExtras instances.
- Developers: Ensure the
beforeandafterslot content is decorative or supplementary only; interactive elements in these slots can confuse keyboard navigation. Use thearia-labelprop rather than relying on before/after content for accessible naming.
Related components
select— a dropdown select element for choosing one optioncombobox— a text input combined with a dropdown list for filtering optionscascader— a multi-level dropdown for selecting a value from a hierarchy
References
- WAI-ARIA Listbox Pattern: https://www.w3.org/WAI/ARIA/apg/patterns/listbox/
- HTML
<select>element: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select