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 . |
Read more in Radix Select Root API
Read more in Radix 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>
Group Items
Prop | Default | Type | Description |
---|---|---|---|
groupItems | - | 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-items
placeholder="Select Option"
/>
</div>
</template>
Objects
Control the attribute value to be displayed in the select and the item.
Prop | Default | Type | Description |
---|---|---|---|
valueAttribute | - | string | The attribute value to be displayed in the select. |
itemAttribute | - | string | The attribute value 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-attribute="label"
/>
</div>
</div>
</template>
Form Group
You can use the select
component inside the form-group
component, or you can use it with the label
component.
Preview
Code
Select a contributor from the Vue community
This field is required
<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="flex items-end">
<NFormGroup
label="Contributor"
description="Select a contributor from the Vue community"
:status="selected ? undefined : 'error'"
:message="selected ? '' : 'This field is required'"
required
>
<NSelect
v-model="selected"
placeholder="Options"
:items
/>
</NFormGroup>
</div>
</template>
Read more in Form-group component
Read more in Label 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. |
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]:line-clamp-1
'select-trigger-trailing-icon': 'i-lucide-chevrons-up-down !text-1.042em',
'select-trigger-trailing': 'ml-auto',
'select-trigger-leading': '',
'select-value': 'h-1.5em',
'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-[--radix-select-trigger-height] w-full min-w-[--radix-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 { SelectContentProps, SelectGroupProps, SelectItemIndicatorProps, SelectItemProps, SelectItemTextProps, SelectLabelProps, SelectRootProps, SelectScrollDownButtonProps, SelectScrollUpButtonProps, SelectSeparatorProps, SelectTriggerProps, SelectValueProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import type { NButtonProps } from './button'
interface BaseExtensions {
class?: HTMLAttributes['class']
size?: HTMLAttributes['class']
}
type RootExtensions = Omit<SelectRootProps, 'modelValue' > & 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 = Omit<SelectItemProps, 'value'> & BaseExtensions
type ItemTextExtensions = SelectItemTextProps & BaseExtensions
type GroupExtensions = SelectGroupProps & BaseExtensions
type LabelExtensions = SelectLabelProps & BaseExtensions
type SeparatorExtensions = SelectSeparatorProps & BaseExtensions
type SelectExtensions = NSelectRootProps
& BaseExtensions
& Pick<NSelectItemProps, 'selectItem'>
& Pick<NSelectTriggerProps, 'status' | 'select'>
export interface NSelectProps extends SelectExtensions {
/**
* The unique id of the select.
*/
id?: string
/**
* The attribute name to use to display in the select items.
*
*/
itemAttribute?: string | number
/**
* The attribute name to use to display in the selected value.
*/
valueAttribute?: string | number
/**
* The placeholder to display when no value is selected.
*/
placeholder?: string
/**
* The label to display above the select items.
*/
label?: string
/**
* The items to display in the select.
*
* @default []
*/
items: any[]
/**
* Allows for multiple groups within the select.
*
* @default false
* @example
* items: [
* { label: 'Group 1', items: [1, 2, 3] },
* ]
*/
groupItems?: boolean
// sub-components
_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 {
/**
* 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
}
}
export interface NSelectItemProps extends ItemExtensions {
value: any
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 setup lang="ts">
import type { SelectRootEmits } from 'radix-vue'
import type { NSelectProps } from '../../../types'
import {
useForwardPropsEmits,
} from 'radix-vue'
import { computed, provide } from 'vue'
import { isEqualObject, omitProps } 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>(), {
size: 'sm',
})
const emits = defineEmits<SelectRootEmits>()
const modelValue = defineModel<any>('modelValue')
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
const transformerValue = computed(() => {
if (typeof modelValue.value === 'object') {
if (forwarded.value.valueAttribute)
return modelValue.value[forwarded.value.valueAttribute]
if (forwarded.value.itemAttribute)
return modelValue.value[forwarded.value.itemAttribute]
}
return modelValue.value
})
provide('selectModelValue', modelValue)
</script>
<template>
<SelectRoot
v-bind="omitProps(forwarded, ['items', 'groupItems', 'itemAttribute', 'placeholder', 'label', 'id', 'select'])"
:model-value="transformerValue"
>
<SelectTrigger
:id
:size
:status
:select
v-bind="forwarded._selectTrigger"
>
<slot name="trigger" :value="modelValue">
<SelectValue
v-bind="forwarded._selectValue"
:placeholder="forwarded._selectValue?.placeholder || forwarded.placeholder"
>
<slot name="value" :value="modelValue">
{{ transformerValue }}
</slot>
</SelectValue>
</slot>
</SelectTrigger>
<SelectContent
:size
v-bind="{
...forwarded._selectContent,
_selectScrollDownButton: forwarded._selectScrollDownButton,
_selectScrollUpButton: forwarded._selectScrollUpButton,
_selectViewport: forwarded._selectViewport,
}"
>
<slot name="content" :items="forwarded.items">
<!-- single-group -->
<template v-if="!groupItems">
<SelectLabel
v-if="forwarded.label"
v-bind="forwarded._selectLabel"
>
<slot name="label" :label="forwarded.label">
{{ forwarded.label }}
</slot>
</SelectLabel>
<template
v-for="item in items"
:key="item"
>
<SelectItem
:value="item"
:size
:select-item
v-bind="{ ...props._selectItem, ...item._selectItem }"
:is-selected="isEqualObject(item, modelValue)"
>
<slot name="item" :item="item">
{{ props.itemAttribute ? item[props.itemAttribute] : item }}
</slot>
</SelectItem>
</template>
</template>
<!-- multiple-group -->
<template
v-else
>
<SelectGroup
v-for="(groupItems, i) in items"
:key="i"
v-bind="props._selectGroup"
>
<SelectSeparator
v-if="i > 0"
v-bind="props._selectSeparator"
/>
<slot name="group" :items="groupItems">
<SelectLabel
v-if="groupItems.label"
:size
v-bind="{ ...props._selectLabel, ...groupItems._selectLabel }"
>
<slot name="label" :label="groupItems.label">
{{ groupItems.label }}
</slot>
</SelectLabel>
<template
v-for="groupItem in groupItems.items"
:key="groupItem"
>
<SelectItem
:value="groupItem"
:size
v-bind="{ ...forwarded._selectItem, ...groupItems?._selectItem, ...groupItem._selectItem }"
:is-selected="groupItem === transformerValue"
>
<slot name="item" :item="groupItem">
{{ props.itemAttribute ? groupItem[props.itemAttribute] : groupItem }}
</slot>
</SelectItem>
</template>
</slot>
</SelectGroup>
</template>
<slot />
</slot>
</SelectContent>
</SelectRoot>
</template>
<script setup lang="ts">
import type { NSelectContentProps } from '../../../types'
import {
SelectContent,
type SelectContentEmits,
SelectPortal,
SelectViewport,
useForwardPropsEmits,
} from 'radix-vue'
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="forwarded._selectScrollUpButton"
/>
<SelectViewport
:class="cn(
'select-viewport',
position === 'popper' && 'select-viewport-popper')"
v-bind="forwarded._selectViewport"
>
<slot />
</SelectViewport>
<SelectScrollDownButton
v-bind="forwarded._selectScrollDownButton"
/>
</SelectContent>
</SelectPortal>
</template>
<script setup lang="ts">
import type { NSelectGroupProps } from '../../../types'
import { SelectGroup } from 'radix-vue'
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, NSelectProps } from '../../../types'
import {
SelectItem,
useForwardProps,
} from 'radix-vue'
import { computed, inject } 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)
const modelValue = inject<NSelectProps>('selectModelValue')
const isSelected = computed(() => {
return props.isSelected || modelValue === props.value
})
</script>
<template>
<SelectItem
v-bind="forwardedProps"
:class="
cn(
'select-item',
props.class,
props.una?.selectItem,
)
"
:select-item
:aria-selected="isSelected"
:aria-checked="isSelected"
:is-selected="isSelected"
:data-state="true ? 'checked' : 'unchecked'"
>
<SelectItemIndicator
v-if="isSelected"
v-bind="forwardedProps._selectItemIndicator"
>
<slot name="item-indicator" />
</SelectItemIndicator>
<SelectItemText
v-bind="forwardedProps._selectItemText"
>
<slot />
</SelectItemText>
</SelectItem>
</template>
<script setup lang="ts">
import type { NSelectItemTextProps } from '../../../types'
import { SelectItemText } from 'radix-vue'
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 'radix-vue'
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 'radix-vue'
import type { NSelectRootProps } from '../../../types'
import { SelectRoot, useForwardPropsEmits } from 'radix-vue'
import { cn } from '../../../utils'
const props = defineProps<NSelectRootProps>()
const emits = defineEmits<SelectRootEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<SelectRoot
:class="cn(
'select-root',
props.class,
props.una?.selectRoot,
)"
v-bind="forwarded"
>
<slot />
</SelectRoot>
</template>
<script setup lang="ts">
import type { NSelectScrollDownButtonProps } from '../../../types'
import { SelectScrollDownButton, useForwardProps } from 'radix-vue'
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 'radix-vue'
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 'radix-vue'
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 { SelectTrigger, useForwardProps } from 'radix-vue'
import { computed } from 'vue'
import { cn, randomId } from '../../../utils'
import Button from '../../elements/Button.vue'
const props = defineProps<NSelectTriggerProps>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
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 text = {
info: 'text-info',
success: 'text-success',
warning: 'text-warning',
error: 'text-error',
default: '',
}
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: 'select-trigger-trailing-icon',
}
return {
btn: btn[props.status ?? 'default'],
text: text[props.status ?? 'default'],
icon: icon[props.status ?? 'default'],
}
})
</script>
<template>
<SelectTrigger
as-child
>
<Button
v-bind="forwardedProps"
:id="randomId('select-trigger')"
:class="cn(
'select-trigger justify-between font-normal',
props.class,
)"
:trailing="statusClassVariants.icon"
:una="{
...props.una,
...{
btnLeading: cn(
'select-trigger-leading',
props.una?.btnLeading,
),
btnTrailing: cn(
'select-trigger-trailing',
props.una?.btnTrailing,
statusClassVariants.text,
),
btnDefaultVariant: statusClassVariants.btn,
},
}"
>
<slot />
</Button>
</SelectTrigger>
</template>
<script setup lang="ts">
import type { NSelectValueProps } from '../../../types'
import { SelectValue } from 'radix-vue'
const props = defineProps<NSelectValueProps>()
</script>
<template>
<SelectValue
:class="{ 'select-value': !props.placeholder }"
v-bind="props"
>
<slot />
</SelectValue>
</template>