Select
A list of options that opens from a field and takes one, on the browser's own select. Use a Combobox to search a long list.
The preview needs JavaScript. The code is in the Code tab.
<script>
const sizes = [
{ value: 's', label: 'Small' },
{ value: 'm', label: 'Medium' },
{ value: 'l', label: 'Large' },
]
</script>
<template>
<Select :options="sizes" value="m">
<span slot="label">Size</span>
</Select>
</template>
Installation
npx @pixelscriptio/tessera add Selectpnpm exec tessera add Selectyarn tessera add Selectbunx @pixelscriptio/tessera add Select- Works with Tessera 0.9.0 or newer.
Copy and paste the code into your project
Put it in
system/components.system/components/Select.tess <contract> { "name": "Select", "role": "generic", "description": "A list of options that opens from a field and takes one, on the browser's own select. Use a Combobox to search a long list.", "since": "0.5.0", "parts": ["root", "label", "select"], "variants": { "size": ["md", "sm"] // first value is the default }, "states": ["hover", "focus-visible", "disabled"], "slots": { "label": "the visible label, required" }, "events": { "change": "fired with { value, label } when the person chooses an option" }, "preview": { "props": { "options": [ { "value": "apple", "label": "Apple" }, { "value": "apricot", "label": "Apricot" }, { "value": "banana", "label": "Banana" }, { "value": "blueberry", "label": "Blueberry" } ] }, "slots": { "label": "Fruit" } } } </contract> <script> const { options, value, disabled } = props({ options: [], value: '', disabled: false }) // The select owns what is chosen, starts from the prop and follows it when it changes. const current = state(value.value) effect(() => { current.value = value.value }) function changed(event) { const chosen = options.value.find((o) => o.value === event.target.value) emit('change', { value: event.target.value, label: chosen ? chosen.label : '' }) } </script> <template> <label class="root"> <span class="label"><slot name="label" /></span> <select class="select" :disabled="disabled" bind:value="current" @change="changed($event)"> <option each="o in options" key="o.value" :value="o.value" :selected="o.value === current" > {o.label} </option> </select> </label> </template> <style> .root { display: flex; flex-direction: column; gap: $space.1; color: $color.text.default; font-family: var(--t-font-family-sans); font-size: $font.size.sm; } .label { font-size: $font.size.sm; font-weight: $font.weight.bold; } .select { padding: $space.2 $space.3; border: 1px solid $color.border.strong; border-radius: $radius.md; background: $color.surface.default; color: $color.text.default; font: inherit; transition-duration: $motion.duration.fast; &:hover:not(:disabled) { border-color: $color.text.default; } &:focus-visible { outline: 2px solid $color.focus.ring; outline-offset: 2px; } &:disabled { opacity: $opacity.disabled; cursor: not-allowed; } } .root[data-size='sm'] .select { padding: $space.1 $space.2; font-size: $font.size.sm; } </style>Check your design tokens
Your design system needs these.
tessera addreports the ones that are missing; by hand, runnpx @pixelscriptio/tessera check.color.border.strongcolor.focus.ringcolor.surface.defaultcolor.text.defaultfont.size.smfont.weight.boldmotion.duration.fastopacity.disabledradius.mdspace.1space.2space.3
Usage
Using Select
Use a select to choose one option from a short list, on the browser's own select, so it works the way people already know on every device. For a long list that people search, use a Combobox.
- The label is required: it is what assistive technology reads.
- Give it
options, a list of{ value, label }, andvalueto start with one chosen. changefires with{ value, label }when the person chooses an option.
The preview needs JavaScript. The code is in the Code tab.
<script>
const sizes = [
{ value: 's', label: 'Small' },
{ value: 'm', label: 'Medium' },
{ value: 'l', label: 'Large' },
]
</script>
<template>
<Select :options="sizes" value="m">
<span slot="label">Size</span>
</Select>
</template>
API reference
Variants
| Variant | Values |
|---|---|
size | md default sm |
Slots
| Slot | Content |
|---|---|
label | the visible label, required |
Events
| Event | When |
|---|---|
change | fired with { value, label } when the person chooses an option |
Anatomy
| Role | generic |
| Parts | root label select |
| States | hover focus-visible disabled |
| Since | 0.5.0 |
Design tokens it uses
Your design system needs these. tessera add checks that it has them, and can add the ones it lacks.
color.border.strong color.focus.ring color.surface.default color.text.default font.size.sm font.weight.bold motion.duration.fast opacity.disabled radius.md space.1 space.2 space.3
Checksum
a2a7e52d99e169896261531b4d6c865c587bcc876a3bce901bd353b56b669210