feat: 添加 FaSelect 组件的定位模式支持

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Hooray
2026-04-25 21:56:26 +08:00
co-authored by Copilot
parent 1d86ef87d3
commit 81beda6e56
17 changed files with 91 additions and 35 deletions
@@ -1,40 +1,25 @@
<script setup lang="ts">
const modal = shallowRef(false)
const cityInFaModal = shallowRef('shanghai')
const popperValue = ref('2')
const itemAlignedValue = ref('2')
const options = [
{ label: 'Beijing', value: 'beijing' },
{ label: 'Shanghai', value: 'shanghai' },
{ label: 'Shenzhen', value: 'shenzhen' },
{ label: 'Option 1', value: '1' },
{ label: 'Option 2', value: '2' },
{ label: 'Option 3', value: '3' },
]
</script>
<template>
<div>
<div class="flex gap-2">
<FaButton @click="modal = true">
打开 FaModal
</FaButton>
</div>
<FaModal
v-model="modal"
title="FaModal 中的选择器"
description="在模态框内容区内使用 FaSelect"
:footer="false"
class="sm:max-w-lg"
content-class="min-h-auto"
>
<div class="py-4 flex flex-col gap-4">
<FaSelect
v-model="cityInFaModal"
:options="options"
placeholder="请选择城市"
class="w-full"
/>
<div class="text-sm text-muted-foreground">
当前值:{{ cityInFaModal }}
</div>
</div>
</FaModal>
<div class="space-y-2">
<FaSelect
v-model="popperValue"
:options="options"
position="popper"
/>
<FaSelect
v-model="itemAlignedValue"
:options="options"
position="item-aligned"
/>
</div>
</template>
@@ -0,0 +1,40 @@
<script setup lang="ts">
const modal = shallowRef(false)
const cityInFaModal = shallowRef('shanghai')
const options = [
{ label: 'Beijing', value: 'beijing' },
{ label: 'Shanghai', value: 'shanghai' },
{ label: 'Shenzhen', value: 'shenzhen' },
]
</script>
<template>
<div>
<div class="flex gap-2">
<FaButton @click="modal = true">
打开 FaModal
</FaButton>
</div>
<FaModal
v-model="modal"
title="FaModal 中的选择器"
description="在模态框内容区内使用 FaSelect"
:footer="false"
class="sm:max-w-lg"
content-class="min-h-auto"
>
<div class="py-4 flex flex-col gap-4">
<FaSelect
v-model="cityInFaModal"
:options="options"
placeholder="请选择城市"
class="w-full"
/>
<div class="text-sm text-muted-foreground">
当前值:{{ cityInFaModal }}
</div>
</div>
</FaModal>
</div>
</template>
@@ -3,6 +3,7 @@ import Demo1 from './_demo1.vue'
import Demo2 from './_demo2.vue'
import Demo3 from './_demo3.vue'
import Demo4 from './_demo4.vue'
import Demo5 from './_demo5.vue'
</script>
<template>
@@ -23,10 +24,15 @@ import Demo4 from './_demo4.vue'
<Demo3 />
</div>
</FaPageMain>
<FaPageMain title="在 FaModal 里展示" main-class="p-0">
<FaPageMain title="定位模式" main-class="p-0">
<div class="p-4">
<Demo4 />
</div>
</FaPageMain>
<FaPageMain title="在 FaModal 里展示" main-class="p-0">
<div class="p-4">
<Demo5 />
</div>
</FaPageMain>
</div>
</template>
+25 -1
View File
@@ -1,6 +1,6 @@
# FaSelect 选择器组件
下拉选择器组件,支持单选、多选、分组和自定义选项。
下拉选择器组件,支持单选、多选、分组和下拉内容定位方式。
## 使用场景
@@ -16,6 +16,7 @@
|------|------|--------|------|
| `multiple` | `boolean` | `false` | 是否多选 |
| `disabled` | `boolean` | `false` | 是否禁用 |
| `position` | `'popper' \| 'item-aligned'` | `'popper'` | 下拉内容的定位模式 |
| `options` | `(Option \| GroupOption)[]` | **必需** | 选项数据 |
| `placeholder` | `string` | - | 占位提示文本 |
| `class` | `HTMLAttributes['class']` | - | 自定义 CSS 类 |
@@ -155,6 +156,28 @@ function handleChange(value) {
</template>
```
### 定位模式
```vue
<script setup lang="ts">
const popperValue = ref('2')
const itemAlignedValue = ref('2')
const options = [
{ label: '选项 1', value: '1' },
{ label: '选项 2', value: '2' },
{ label: '选项 3', value: '3' },
]
</script>
<template>
<div class="flex flex-col gap-4">
<FaSelect v-model="popperValue" :options="options" position="popper" />
<FaSelect v-model="itemAlignedValue" :options="options" position="item-aligned" />
</div>
</template>
```
### 禁用选择器
```vue
@@ -196,3 +219,4 @@ const cities = [
3. **值类型**:`value` 可以是字符串、数字等类型
4. **分组显示**:当 `options` 中包含 `options` 属性时,会自动识别为分组选项
5. **z-index**:下拉菜单的 z-index 默认为 2000,确保在其他内容上方显示
6. **定位模式**:`position="popper"` 时下拉内容跟随触发器定位,`position="item-aligned"` 时会更接近原生 Select 的对齐方式
+3 -2
View File
@@ -1,5 +1,5 @@
<script setup lang="ts">
import type { AcceptableValue } from 'reka-ui'
import type { AcceptableValue, SelectContentProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { useTextDirection } from '@vueuse/core'
import { cn } from '../../utils'
@@ -30,6 +30,7 @@ defineOptions({
const props = defineProps<{
multiple?: boolean
disabled?: boolean
position?: SelectContentProps['position']
options: (Option | GroupOption)[]
placeholder?: string
class?: HTMLAttributes['class']
@@ -97,7 +98,7 @@ const selectedOption = computed({
<SelectTrigger :class="cn('w-[200px]', props.class)">
<SelectValue :placeholder="props.placeholder" :selected-option="selectedOption?.label" />
</SelectTrigger>
<SelectContent class="z-2000">
<SelectContent :position class="z-2000">
<template v-for="option in props.options" :key="option.label">
<SelectGroup v-if="option.hasOwnProperty('options')">
<SelectLabel>{{ option.label }}</SelectLabel>
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File