Select
Displays a list of options for the user to pick from—triggered by a button.
Examples
Basic
Name | Default | Type | Description |
---|---|---|---|
items | - | array | Set the select items. |
placeholder | - | string | The content that will be rendered inside the SelectValue when no value or defaultValue is set. |
label | - | string | Set the select items label. |
defaultOpen | - | boolean | The open state of the select when it is initially rendered. Use when you do not need to control its open state. |
defaultValue | - | string | The value of the select when initially rendered. Use when you do not need to control the state of the Select |
open | - | boolean | The controlled open state of the Select. Can be bind as v-model:open . |
modelValue | - | string | The controlled value of the Select. Can be bind as v-model . |
status | - | string | Set the status of the select. Values: info , success , warning , error |
Read more in Reka Select Root API
Read more in Reka Select Value API
Preview
Code
<script setup lang="ts">
const selected = ref()
const items = ['Evan You', 'Anthony Fu', 'Daniel Roe', 'Pooya Parsa', 'Sébastien Chopin', 'Alexander Lichter']
</script>
<template>
<div class="max-w-50">
<NSelect
v-model="selected"
:items
placeholder="Select Contributor"
label="Vue Community"
/>
</div>
</template>
Multiple
Prop | Default | Type | Description |
---|---|---|---|
multiple | false | boolean | Enable multiple selection mode. |
Preview
Code
Selected:
<script setup lang="ts">
const selected = ref([])
const items = ['Evan You', 'Anthony Fu', 'Daniel Roe', 'Pooya Parsa', 'Sébastien Chopin', 'Alexander Lichter']
</script>
<template>
<div class="space-y-4">
<div class="max-w-50">
<NSelect
v-model="selected"
:items
multiple
placeholder="Select Contributors"
label="Vue Community"
/>
</div>
<div class="text-sm text-muted">
Selected: {{ selected.join(', ') }}
</div>
</div>
</template>
Disabled
Prop | Default | Type | Description |
---|---|---|---|
disabled | false | boolean | Disable the select component. |
Preview
Code
<script setup lang="ts">
const selected = ref()
const items = ['Evan You', 'Anthony Fu', 'Daniel Roe', 'Pooya Parsa', 'Sébastien Chopin', 'Alexander Lichter']
</script>
<template>
<div class="max-w-50">
<NSelect
v-model="selected"
:items
disabled
placeholder="Select Contributor"
label="Vue Community (Disabled)"
/>
</div>
</template>
Group
Prop | Default | Type | Description |
---|---|---|---|
group | - | boolean | Enable support for group items. |
Preview
Code
<script setup lang="ts">
const selected = ref()
const items = [
{
label: 'A',
items: ['Apple', 'Aeroplane', 'Ant'],
},
{
label: 'B',
items: ['Banana', 'Ball', 'Bat'],
},
{
label: 'C',
items: ['Cat', 'Car', 'Cup'],
},
{
label: 'D',
items: ['Dog', 'Duck', 'Doll'],
},
]
</script>
<template>
<div class="max-w-50">
<NSelect
v-model="selected"
:items
group
placeholder="Select Option"
/>
</div>
</template>
Read more in Reka Select Group Items API
Objects
Control the attribute value to be displayed in the select and the item.
Prop | Default | Type | Description |
---|---|---|---|
valueKey | - | string | The key name to be displayed in the selected value. |
itemKey | - | string | The key name to be displayed in the item. |
Preview
Code
Output:
<script setup lang="ts">
const items = [
{
code: '81253',
label: 'Ford',
},
{
code: '29932',
label: 'Chevrolet',
},
{
code: '54509',
label: 'Dodge',
},
{
code: '94253',
label: 'Toyota',
},
]
const selected = ref()
</script>
<template>
<div class="space-y-4">
Output:
<span class="text-primary-500">
{{ selected }}
</span>
<div class="w-64">
<NSelect
v-model="selected"
:items
placeholder="Select a brand"
item-key="label"
/>
</div>
</div>
</template>
Form Field
The NSelect
component can be easily embedded within the NFormField
component.
Preview
Code
<script setup lang="ts">
import { toTypedSchema } from '@vee-validate/zod'
import * as z from 'zod'
const formSchema = toTypedSchema(z.object({
contributor: z.string().min(1, 'This field is required'),
}))
useForm({
validationSchema: formSchema,
validateOnMount: true,
})
const selected = ref<string>()
const items = ['Evan You', 'Anthony Fu', 'Daniel Roe', 'Pooya Parsa', 'Sébastien Chopin', 'Alexander Lichter']
</script>
<template>
<form>
<div class="flex items-end">
<NFormField
name="contributor"
label="Contributor"
description="Select a contributor from the Vue community"
required
>
<NSelect
v-model="selected"
placeholder="Options"
:items="items"
/>
</NFormField>
</div>
</form>
</template>
Read more in Form component
Variant and Color
Prop | Default | Type | Description |
---|---|---|---|
select | soft-white | {variant}-{color} | Change the color of the select. |
select-item | gray | {color} | Change the color of the select item. |
Preview
Code
<script setup lang="ts">
const selected = ref()
const items = ['Evan You', 'Anthony Fu', 'Daniel Roe', 'Pooya Parsa', 'Sébastien Chopin', 'Alexander Lichter']
</script>
<template>
<div class="grid gap-4 sm:grid-cols-3">
<NSelect
v-model="selected"
:items="items"
select="outline-white"
placeholder="This is the gray color"
/>
<NSelect
v-model="selected"
:items="items"
select="outline-primary"
select-item="primary"
placeholder="This is the primary color (default)"
/>
<NSelect
v-model="selected"
:items="items"
select="soft-rose"
select-item="rose"
placeholder="This is the rose color"
/>
</div>
</template>
Read more in Button variant and color section
Size
Adjust the select size without limits. Use breakpoints
(e.g., sm:sm
, xs:lg
) for responsive sizes or states
(e.g., hover:lg
, focus:3xl
) for state-based sizes.
Prop | Default | Type | Description |
---|---|---|---|
size | sm | string | Adjusts the overall size of the select component. |
_selectItem.size | sm | string | Customizes the size of each item within the select dropdown. |
_selectTrigger.size | sm | string | Modifies the size of the select trigger element. |
Preview
Code
<script setup lang="ts">
const selected = ref()
const items = ['Evan You', 'Anthony Fu', 'Daniel Roe', 'Pooya Parsa', 'Sébastien Chopin', 'Alexander Lichter']
</script>
<template>
<div class="grid gap-4 sm:grid-cols-2">
<NSelect
v-model="selected"
:items
placeholder="Select Contributor"
label="Vue Community"
/>
<NSelect
v-model="selected"
:items
size="md"
placeholder="Select Contributor"
label="Vue Community"
/>
</div>
</template>
Slots
Name | Props | Description |
---|---|---|
trigger | value | The trigger slot. |
value | value | The value slot. |
content | items | The content slot. |
label | label | The label slot. |
item | item | The item slot. |
group | items | The group slot. |
Preview
Code
<script setup lang="ts">
const items = [
{
name: 'Evan You',
avatar: 'https://avatars.githubusercontent.com/u/499550?v=4',
},
{
name: 'Anthony Fu',
avatar: 'https://avatars.githubusercontent.com/u/11247099?v=4',
},
{
name: 'Daniel Roe',
avatar: 'https://avatars.githubusercontent.com/u/28706372?v=4',
},
]
const selected = ref(items[0])
</script>
<template>
<div class="max-w-50">
<NSelect
v-model="selected"
:items
placeholder="Select Contributor"
label="Vue Community"
:_select-trigger="{
una: {
selectTriggerTrailingIcon: 'i-lucide-chevrons-up-down',
},
}"
>
<template #label="{ label }">
<div class="flex flex-col space-y-0.5">
<span class="text-primary">{{ label }}</span>
<span class="text-xs text-muted">Mini example list of contributors</span>
</div>
</template>
<template #item="{ item }">
<div class="flex items-center space-x-2">
<img
:src="item.avatar"
:alt="item.name"
class="h-6 w-6 rounded-full"
>
<span>{{ item.name }}</span>
</div>
</template>
<template #value>
<div class="flex items-center space-x-2">
<img
:src="selected?.avatar"
:alt="selected?.name"
class="h-6 w-6 rounded-full"
>
<span>{{ selected?.name }}</span>
</div>
</template>
</NSelect>
</div>
</template>
Presets
shortcuts/select.ts
type SelectPrefix = 'select'
export const staticSelect: Record<`${SelectPrefix}-${string}` | SelectPrefix, string> = {
// configurations
'select': '',
'select-default-variant': 'btn-solid-white',
'select-disabled': 'n-disabled',
'select-scroll': 'flex cursor-default items-center justify-center py-1',
'select-trigger-info-icon': 'i-info',
'select-trigger-error-icon': 'i-error',
'select-trigger-success-icon': 'i-success',
'select-trigger-warning-icon': 'i-warning',
// components
'select-root': '',
'select-trigger': 'w-full [&>span]:truncate',
'select-trigger-trailing-icon': 'i-lucide-chevron-down n-disabled',
'select-trigger-trailing': 'ml-auto data-[status]:text-1.2em data-[status=error]:text-error data-[status=success]:text-success data-[status=warning]:text-warning data-[status=info]:text-info',
'select-trigger-leading': '',
'select-value': 'h-1.5em data-[status=error]:text-error data-[status=success]:text-success data-[status=warning]:text-warning data-[status=info]:text-info data-[placeholder]:n-disabled',
'select-content': 'relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border border-base bg-popover text-popover shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
'select-content-popper': 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
'select-group': 'p-1 w-full',
'select-separator': '-mx-1 my-1 h-px bg-muted',
'select-item': 'select-item-gray relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-1em outline-none data-[disabled]:pointer-events-none data-[disabled]:n-disabled',
'select-item-indicator': 'absolute left-2 h-0.75em w-0.75em flex items-center justify-center',
'select-item-indicator-icon': 'i-check',
'select-viewport': 'p-1',
'select-viewport-popper': 'h-[--reka-select-trigger-height] w-full min-w-[--reka-select-trigger-width]',
'select-scroll-up-button': 'select-scroll',
'select-scroll-down-button': 'select-scroll',
'select-scroll-up-button-icon': 'i-lucide-chevron-up',
'select-scroll-down-button-icon': 'i-lucide-chevron-down',
'select-label': 'py-1.5 pl-8 pr-2 text-1em font-semibold',
// ⚠️ for overriding purposes only
'select-item-selectItem': '',
}
export const dynamicSelect = [
[/^select-([^-]+)-([^-]+)$/, ([, v = 'solid', c = 'gray']) => `btn-${v}-${c}`],
[/^select-item(-(\S+))?$/, ([, , c = 'gray']) => `focus:bg-${c}-100 focus:text-${c}-800 dark:focus:bg-${c}-800 dark:focus:text-${c}-100`],
]
export const select = [
...dynamicSelect,
staticSelect,
]
Props
types/select.ts
import type { AcceptableValue, SelectContentProps, SelectGroupProps, SelectItemIndicatorProps, SelectItemProps, SelectItemTextProps, SelectLabelProps, SelectRootProps, SelectScrollDownButtonProps, SelectScrollUpButtonProps, SelectSeparatorProps, SelectTriggerProps, SelectValueProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import type { NButtonProps } from './button'
interface BaseExtensions {
class?: HTMLAttributes['class']
size?: HTMLAttributes['class']
}
type RootExtensions = SelectRootProps & BaseExtensions
type TriggerExtensions = SelectTriggerProps & Omit<NButtonProps, 'una'> & BaseExtensions
type ValueExtensions = SelectValueProps & BaseExtensions
type ScrollDownButtonExtensions = SelectScrollDownButtonProps & BaseExtensions
type ScrollUpButtonExtensions = SelectScrollUpButtonProps & BaseExtensions
type ContentExtensions = SelectContentProps & BaseExtensions
type ItemExtensions = SelectItemProps & BaseExtensions
type ItemTextExtensions = SelectItemTextProps & BaseExtensions
type GroupExtensions = SelectGroupProps & BaseExtensions
type LabelExtensions = SelectLabelProps & BaseExtensions
type SeparatorExtensions = SelectSeparatorProps & BaseExtensions
type SelectExtensions = NSelectRootProps
& BaseExtensions
& Pick<NSelectValueProps, 'placeholder'>
& Pick<NSelectItemProps, 'selectItem'>
& Pick<NSelectTriggerProps, 'status' | 'select' | 'id'>
export interface SelectGroup<T extends AcceptableValue> {
label?: string
items: T[]
_selectLabel?: Partial<NSelectLabelProps>
_selectItem?: Partial<NSelectItemProps>
}
export interface NSelectProps<T extends AcceptableValue> extends SelectExtensions {
/**
* s
* The items to display in the select.
*/
items: T[] | SelectGroup<T>[]
/**
* The key name to use to display in the select items.
*/
itemKey?: keyof T
/**
* The key name to use to display in the selected value.
*/
valueKey?: keyof T
/**
* The label to display above the select items.
*/
label?: string
/**
* Allows for multiple groups within the select.
*/
group?: boolean
/**
* Sub-component configurations
*/
_selectScrollUpButton?: Partial<NSelectScrollUpButtonProps>
_selectItemText?: Partial<NSelectItemTextProps>
_selectScrollDownButton?: Partial<NSelectScrollDownButtonProps>
_selectGroup?: Partial<NSelectGroupProps>
_selectSeparator?: Partial<NSelectSeparator>
_selectContent?: Partial<NSelectContentProps>
_selectValue?: Partial<NSelectValueProps>
_selectTrigger?: Partial<NSelectTriggerProps>
_selectItem?: Partial<NSelectItemProps>
_selectLabel?: Partial<NSelectLabelProps>
}
export interface NSelectRootProps extends RootExtensions {
una?: {
selectRoot?: HTMLAttributes['class']
}
}
export interface NSelectTriggerProps extends TriggerExtensions {
/**
* The unique id of the select trigger to be used for the form field.
*/
id?: string
/**
* Allows you to add `UnaUI` button preset properties,
* Think of it as a shortcut for adding options or variants to the preset if available.
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/select.ts
* @example
* select="solid-green"
*/
select?: string
/**
* The status of the select input.
*/
status?: 'info' | 'success' | 'warning' | 'error'
/**
* `UnaUI` preset configuration
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/select.ts
*/
una?: {
selectTrigger?: HTMLAttributes['class']
selectTriggerTrailing?: HTMLAttributes['class']
selectTriggerTrailingIcon?: HTMLAttributes['class']
selectTriggerLeading?: HTMLAttributes['class']
selectTriggerInfoIcon?: HTMLAttributes['class']
selectTriggerSuccessIcon?: HTMLAttributes['class']
selectTriggerWarningIcon?: HTMLAttributes['class']
selectTriggerErrorIcon?: HTMLAttributes['class']
} & NButtonProps['una']
}
export interface NSelectValueProps extends ValueExtensions {
una?: {
selectValue?: HTMLAttributes['class']
}
}
export interface NSelectScrollDownButtonProps extends ScrollDownButtonExtensions {
una?: {
selectScrollDownButton?: HTMLAttributes['class']
selectScrollDownButtonIcon?: HTMLAttributes['class']
}
}
export interface NSelectScrollUpButtonProps extends ScrollUpButtonExtensions {
una?: {
selectScrollUpButton?: HTMLAttributes['class']
selectScrollUpButtonIcon?: HTMLAttributes['class']
}
}
export interface NSelectContentProps extends ContentExtensions {
_selectScrollDownButton?: NSelectScrollDownButtonProps
_selectScrollUpButton?: NSelectScrollUpButtonProps
_selectSeparator?: NSelectSeparator
una?: {
selectContent?: HTMLAttributes['class']
}
}
export interface NSelectItemIndicatorProps extends SelectItemIndicatorProps {
icon?: HTMLAttributes['class']
class?: HTMLAttributes['class']
una?: {
selectItemIndicator?: HTMLAttributes['class']
selectItemIndicatorIcon?: HTMLAttributes['class']
}
}
export interface NSelectItemProps extends ItemExtensions {
selectItem?: HTMLAttributes['class']
isSelected?: boolean
_selectItemText?: NSelectItemTextProps
_selectItemIndicator?: NSelectItemIndicatorProps
una?: {
selectItem?: HTMLAttributes['class']
selectItemIndicatorWrapper?: HTMLAttributes['class']
}
}
export interface NSelectItemTextProps extends ItemTextExtensions {
una?: {
selectItemText?: HTMLAttributes['class']
}
}
export interface NSelectGroupProps extends GroupExtensions {
una?: {
selectGroup?: HTMLAttributes['class']
}
}
export interface NSelectLabelProps extends LabelExtensions {
una?: {
selectLabel?: HTMLAttributes['class']
}
}
export interface NSelectSeparator extends SeparatorExtensions {
una?: {
selectSeparator?: HTMLAttributes['class']
}
}
Components
Select.vue
SelectContent.vue
SelectGroup.vue
SelectItem.vue
SelectItemText.vue
SelectLabel.vue
SelectRoot.vue
SelectScrollDownButton.vue
SelectScrollUpButton.vue
SelectSeperator.vue
SelectTrigger.vue
SelectValue.vue
<script lang="ts">
import type { AcceptableValue, SelectRootEmits } from 'reka-ui'
import type { NSelectProps, SelectGroup as SelectGroupType } from '../../../types'
</script>
<script setup lang="ts" generic="T extends AcceptableValue">
import { reactivePick } from '@vueuse/core'
import { useForwardPropsEmits } from 'reka-ui'
import { isEqualObject } from '../../../utils'
import SelectContent from './SelectContent.vue'
import SelectGroup from './SelectGroup.vue'
import SelectItem from './SelectItem.vue'
import SelectLabel from './SelectLabel.vue'
import SelectRoot from './SelectRoot.vue'
import SelectSeparator from './SelectSeparator.vue'
import SelectTrigger from './SelectTrigger.vue'
import SelectValue from './SelectValue.vue'
const props = withDefaults(defineProps<NSelectProps<T>>(), {
size: 'sm',
})
const emits = defineEmits<SelectRootEmits>()
const rootProps = reactivePick(props, [
'modelValue',
'defaultValue',
'multiple',
'disabled',
])
const forwarded = useForwardPropsEmits(rootProps, emits)
function formatSelectedValue(value: unknown) {
if (!value || (Array.isArray(value) && value.length === 0))
return null
if (props.multiple && Array.isArray(value)) {
return value.map((val) => {
if (props.valueKey && typeof val === 'object') {
return (val as Record<string, any>)[props.valueKey as string]
}
return val
}).join(', ')
}
if (props.valueKey && typeof value === 'object') {
return (value as Record<string, any>)[props.valueKey as string]
}
return value
}
function isItemSelected(item: unknown, modelValue: unknown) {
if (!modelValue)
return false
if (props.multiple && Array.isArray(modelValue)) {
return modelValue.some((val) => {
const valObj = typeof val === 'object' && val ? val : { value: val }
const itemObj = typeof item === 'object' && item ? item : { value: item }
return isEqualObject(valObj, itemObj)
})
}
const modelObj = typeof modelValue === 'object' && modelValue ? modelValue : { value: modelValue }
const itemObj = typeof item === 'object' && item ? item : { value: item }
return isEqualObject(modelObj, itemObj)
}
</script>
<template>
<SelectRoot
v-slot="{ modelValue, open }"
v-bind="forwarded"
>
<SelectTrigger
:id
:size
:status
:select
v-bind="props._selectTrigger"
>
<slot name="trigger" :model-value :open="open">
<SelectValue
:placeholder="props.placeholder"
v-bind="props._selectValue"
:aria-label="formatSelectedValue(modelValue)"
:data-status="status"
>
<slot name="value" :model-value :open>
{{ formatSelectedValue(modelValue) || props.placeholder }}
</slot>
</SelectValue>
</slot>
</SelectTrigger>
<SelectContent
:size
v-bind="{
..._selectContent,
_selectScrollDownButton,
_selectScrollUpButton,
}"
>
<slot name="content" :items="items">
<template v-if="!group">
<SelectLabel
v-if="label"
v-bind="_selectLabel"
>
<slot name="label" :label>
{{ label }}
</slot>
</SelectLabel>
<template
v-for="item in items"
:key="item"
>
<SelectItem
:value="item"
:size="size"
v-bind="props._selectItem"
:is-selected="isItemSelected(item, modelValue)"
>
<slot name="item" :item="item">
{{ props.itemKey && item ? (item as any)[props.itemKey] : item }}
</slot>
</SelectItem>
</template>
</template>
<template v-if="group">
<SelectGroup
v-for="(group, i) in items as SelectGroupType<T>[]"
:key="i"
v-bind="props._selectGroup"
>
<SelectSeparator
v-if="i > 0"
v-bind="props._selectSeparator"
/>
<slot name="group" :items="group">
<SelectLabel
v-if="group.label"
:size="size"
v-bind="{ ...props._selectLabel, ...group._selectLabel }"
>
<slot name="label" :label="group.label">
{{ group.label }}
</slot>
</SelectLabel>
<template
v-for="item in group.items"
:key="item"
>
<SelectItem
:value="item"
:size="size"
v-bind="{ ..._selectItem, ...group._selectItem }"
:is-selected="isItemSelected(item, modelValue)"
>
<slot name="item" :item="item">
{{ props.itemKey ? (item as any)[props.itemKey] : item }}
</slot>
</SelectItem>
</template>
</slot>
</SelectGroup>
</template>
<slot />
</slot>
</SelectContent>
</SelectRoot>
</template>
<script setup lang="ts">
import type { SelectContentEmits } from 'reka-ui'
import type { NSelectContentProps } from '../../../types'
import {
SelectContent,
SelectPortal,
SelectViewport,
useForwardPropsEmits,
} from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
import SelectScrollDownButton from './SelectScrollDownButton.vue'
import SelectScrollUpButton from './SelectScrollUpButton.vue'
defineOptions({
inheritAttrs: false,
})
const props = withDefaults(
defineProps<NSelectContentProps>(),
{
position: 'popper',
},
)
const emits = defineEmits<SelectContentEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<SelectPortal>
<SelectContent
v-bind="{ ...forwarded, ...$attrs }"
:class="cn(
'select-content',
position === 'popper'
&& 'select-content-popper',
props.class,
)
"
>
<SelectScrollUpButton
v-bind="_selectScrollUpButton"
/>
<SelectViewport
:class="cn(
'select-viewport',
position === 'popper' && 'select-viewport-popper')"
>
<slot />
</SelectViewport>
<SelectScrollDownButton
v-bind="_selectScrollDownButton"
/>
</SelectContent>
</SelectPortal>
</template>
<script setup lang="ts">
import type { NSelectGroupProps } from '../../../types'
import { SelectGroup } from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
const props = defineProps<NSelectGroupProps>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<SelectGroup :class="cn('select-group', props.class)" v-bind="delegatedProps">
<slot />
</SelectGroup>
</template>
<script setup lang="ts">
import type { NSelectItemProps } from '../../../types'
import {
SelectItem,
useForwardProps,
} from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
import SelectItemIndicator from './SelectItemIndicator.vue'
import SelectItemText from './SelectItemText.vue'
const props = withDefaults(defineProps<NSelectItemProps>(), {})
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<SelectItem
v-bind="forwardedProps"
:class="
cn(
'select-item',
props.class,
props.una?.selectItem,
)
"
:select-item
>
<SelectItemIndicator
v-if="isSelected"
v-bind="props._selectItemIndicator"
>
<slot name="item-indicator" />
</SelectItemIndicator>
<SelectItemText
v-bind="props._selectItemText"
>
<slot />
</SelectItemText>
</SelectItem>
</template>
<script setup lang="ts">
import type { NSelectItemTextProps } from '../../../types'
import { SelectItemText } from 'reka-ui'
const props = defineProps<NSelectItemTextProps>()
</script>
<template>
<SelectItemText v-bind="props">
<slot />
</SelectItemText>
</template>
<script setup lang="ts">
import type { NSelectLabelProps } from '../../../types'
import { SelectLabel } from 'reka-ui'
import { cn } from '../../../utils'
const props = defineProps<NSelectLabelProps>()
</script>
<template>
<SelectLabel :class="cn('select-label', props.class)">
<slot />
</SelectLabel>
</template>
<script setup lang="ts">
import type { SelectRootEmits } from 'reka-ui'
import type { NSelectRootProps } from '../../../types'
import { SelectRoot, useForwardPropsEmits } from 'reka-ui'
import { cn } from '../../../utils'
const props = defineProps<NSelectRootProps>()
const emits = defineEmits<SelectRootEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<SelectRoot
v-slot="slotProps"
:class="cn(
'select-root',
props.class,
props.una?.selectRoot,
)"
v-bind="forwarded"
>
<slot
v-bind="slotProps"
/>
</SelectRoot>
</template>
<script setup lang="ts">
import type { NSelectScrollDownButtonProps } from '../../../types'
import { SelectScrollDownButton, useForwardProps } from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
import Icon from '../../elements/Icon.vue'
const props = defineProps<NSelectScrollDownButtonProps>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<SelectScrollDownButton v-bind="forwardedProps" :class="cn('select-scroll-down-button', props.class)">
<slot>
<Icon
:name="forwardedProps?.una?.selectScrollDownButtonIcon || 'select-scroll-down-button-icon'"
/>
</slot>
</SelectScrollDownButton>
</template>
<script setup lang="ts">
import type { NSelectScrollUpButtonProps } from '../../../types'
import { SelectScrollUpButton, useForwardProps } from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
import Icon from '../../elements/Icon.vue'
const props = defineProps<NSelectScrollUpButtonProps>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<SelectScrollUpButton v-bind="forwardedProps" :class="cn('select-scroll-up-button', props.class)">
<slot>
<Icon
:name="forwardedProps?.una?.selectScrollUpButtonIcon || 'select-scroll-up-button-icon'"
/>
</slot>
</SelectScrollUpButton>
</template>
<script setup lang="ts">
import type { NSelectSeparator } from '../../../types'
import { SelectSeparator } from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
const props = defineProps<NSelectSeparator>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<SelectSeparator v-bind="delegatedProps" :class="cn('select-separator', props.class)" />
</template>
<script setup lang="ts">
import type { NSelectTriggerProps } from '../../../types'
import { reactiveOmit } from '@vueuse/core'
import { SelectIcon, SelectTrigger, useForwardProps } from 'reka-ui'
import { computed } from 'vue'
import { cn, randomId } from '../../../utils'
import Button from '../../elements/Button.vue'
import Icon from '../../elements/Icon.vue'
const props = defineProps<NSelectTriggerProps>()
const forwardedProps = useForwardProps(reactiveOmit(props, 'class', 'status', 'una'))
const statusClassVariants = computed(() => {
const btn = {
info: 'btn-outline-info',
success: 'btn-outline-success',
warning: 'btn-outline-warning',
error: 'btn-outline-error',
default: props.select ? `select-${props.select}` : 'select-default-variant',
}
const icon = {
info: props.una?.selectTriggerInfoIcon ?? 'select-trigger-info-icon',
success: props.una?.selectTriggerSuccessIcon ?? 'select-trigger-success-icon',
warning: props.una?.selectTriggerWarningIcon ?? 'select-trigger-warning-icon',
error: props.una?.selectTriggerErrorIcon ?? 'select-trigger-error-icon',
default: props.una?.selectTriggerTrailingIcon ?? 'select-trigger-trailing-icon',
}
return {
btn: btn[props.status ?? 'default'],
icon: icon[props.status ?? 'default'],
}
})
const id = computed(() => props.id ?? randomId('select-trigger'))
</script>
<template>
<SelectTrigger
as-child
>
<Button
v-bind="forwardedProps"
:id
:data-status="status"
:class="cn(
'select-trigger justify-between font-normal',
props.class,
)"
:una="{
...props.una,
...{
btnLeading: cn(
'select-trigger-leading',
props.una?.btnLeading,
),
btnDefaultVariant: statusClassVariants.btn,
},
}"
>
<slot />
<template #trailing>
<SelectIcon
as-child
>
<Icon
:data-status="status"
:name="statusClassVariants.icon"
:class="cn(
'select-trigger-trailing',
props.una?.btnTrailing,
)"
/>
</SelectIcon>
</template>
</Button>
</SelectTrigger>
</template>
<script setup lang="ts">
import type { NSelectValueProps } from '../../../types'
import { SelectValue } from 'reka-ui'
import { cn } from '../../../utils'
const props = defineProps<NSelectValueProps>()
</script>
<template>
<SelectValue
:class="cn('select-value', props.class)"
v-bind="props"
>
<slot />
</SelectValue>
</template>