Select
Picks one value, or several, from a fixed list the user cannot type into.
Select is a listbox behind a trigger, for picking one value or several from a
fixed set. Use it where you would reach for a native <select>; once the list is
long enough to scroll, use Combobox.
The example switches the teleport off, so the popup renders in place and scrolls with the frame around it rather than with the page.
<template>
<Select.Root v-model="framework" :options="options">
<Select.Trigger
class="group border-surface rounded-component-lg focus:focus-ring data-[content-open=true]:focus-ring data-[disabled=true]:border-disabled-subtle flex h-12 w-64 cursor-pointer items-center justify-between gap-1.5 border-2 px-3.5 text-left outline-4 outline-transparent transition-all duration-100 ease-linear select-none data-[disabled=true]:cursor-not-allowed"
>
<span
class="pointer-events-none flex max-h-full w-full flex-col-reverse justify-center gap-0 px-1 transition-all duration-100 ease-linear group-data-[filled=true]:gap-1"
>
<Select.Value
class="text-primary-solid type-component-lg group-data-[disabled=true]:text-disabled-on-subtle flex h-0 w-full items-center overflow-hidden [line-height:normal]! opacity-0 transition-all duration-100 ease-linear group-data-[filled=true]:h-[0.9375rem] group-data-[filled=true]:opacity-100"
/>
<span
class="text-primary-muted type-component-lg group-data-[filled=true]:type-component-2xs group-data-[disabled=true]:text-disabled-muted flex w-full items-center [line-height:normal]! transition-all duration-100 ease-linear"
>
Framework
</span>
</span>
<Select.Icon
class="text-primary-muted group-data-[filled=true]:text-primary-solid group-data-[disabled=true]:text-disabled-muted flex shrink-0 items-center transition-all duration-100 ease-linear"
>
<svg class="size-4.5" viewBox="0 0 16 16" aria-hidden="true">
<path
d="m4 6.5 4 4 4-4"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</Select.Icon>
</Select.Trigger>
<Select.Content
class="rounded-component-2xl bg-primary-inverted shadow-component-high overflow-y-auto p-1.5 backdrop-blur-[8rem] [&_[data-scope=list]]:outline-none"
>
<Select.Item
v-for="name in frameworks"
:key="name"
class="group/item rounded-component-md type-component-lg text-primary-on-subtle hover:bg-primary-subtle active:bg-primary-subtle-hover data-[highlighted=true]:bg-primary-subtle data-[disabled=true]:text-disabled-on-subtle flex h-12 w-full items-center justify-start gap-4 px-1 transition-colors duration-100 ease-linear select-none [--mirror-select-item-cursor:pointer]"
:value="name"
>
<Select.ItemText
class="inline-flex h-full min-w-0 flex-1 items-center overflow-hidden pr-1.5 pl-5.5"
>
<span class="truncate">{{ name }}</span>
</Select.ItemText>
<Select.ItemIndicator
class="text-primary-muted group-hover/item:text-primary-solid group-data-[highlighted=true]/item:text-primary-solid group-data-[disabled=true]/item:text-disabled-muted flex shrink-0 items-center pr-4 leading-none transition-colors duration-100 ease-linear"
>
<svg class="size-4.5" viewBox="0 0 16 16" aria-hidden="true">
<path
d="m3.5 8.5 3 3 6-6.5"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</Select.ItemIndicator>
</Select.Item>
</Select.Content>
</Select.Root>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { Select } from '@maas/mirror/vue/Select'
const options = {
modal: false,
teleport: { disabled: true },
}
const frameworks = ['Nuxt', 'Astro', 'Remix', 'SvelteKit']
const framework = ref<string | null>('Nuxt')
</script>
Usage guidelines
- Make sure the select has an accessible name, either through a
Labelinside aFieldor anaria-labelon the trigger.must Select.Contentteleports to the end of<body>unless you turn that off withoptions.teleport.disabled. Leave it on where the trigger sits inside anything withoverflow: hidden.should- The content resolves everything but
sideandalignonce, during setup, so change the rest before the popup first renders or key the root to remount it.must - Once the list is long enough to scroll, reach for
Comboboxinstead, so the user can narrow it by typing.should - Where the OS picker is the better control, on a phone or a tablet, set
options.nativeand keep the same markup.may