组件

选择

显示一个选项列表供用户选择——由按钮触发。

import React from 'react';
import * as Select from '@radix-ui/react-select';
import classnames from 'classnames';
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from '@radix-ui/react-icons';
import './styles.css';
const SelectDemo = () => (
<Select.Root>
<Select.Trigger className="SelectTrigger" aria-label="Food">
<Select.Value placeholder="Select a fruit…" />
<Select.Icon className="SelectIcon">
<ChevronDownIcon />
</Select.Icon>
</Select.Trigger>
<Select.Portal>
<Select.Content className="SelectContent">
<Select.ScrollUpButton className="SelectScrollButton">
<ChevronUpIcon />
</Select.ScrollUpButton>
<Select.Viewport className="SelectViewport">
<Select.Group>
<Select.Label className="SelectLabel">Fruits</Select.Label>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="blueberry">Blueberry</SelectItem>
<SelectItem value="grapes">Grapes</SelectItem>
<SelectItem value="pineapple">Pineapple</SelectItem>
</Select.Group>
<Select.Separator className="SelectSeparator" />
<Select.Group>
<Select.Label className="SelectLabel">Vegetables</Select.Label>
<SelectItem value="aubergine">Aubergine</SelectItem>
<SelectItem value="broccoli">Broccoli</SelectItem>
<SelectItem value="carrot" disabled>
Carrot
</SelectItem>
<SelectItem value="courgette">Courgette</SelectItem>
<SelectItem value="leek">Leek</SelectItem>
</Select.Group>
<Select.Separator className="SelectSeparator" />
<Select.Group>
<Select.Label className="SelectLabel">Meat</Select.Label>
<SelectItem value="beef">Beef</SelectItem>
<SelectItem value="chicken">Chicken</SelectItem>
<SelectItem value="lamb">Lamb</SelectItem>
<SelectItem value="pork">Pork</SelectItem>
</Select.Group>
</Select.Viewport>
<Select.ScrollDownButton className="SelectScrollButton">
<ChevronDownIcon />
</Select.ScrollDownButton>
</Select.Content>
</Select.Portal>
</Select.Root>
);
const SelectItem = React.forwardRef(({ children, className, ...props }, forwardedRef) => {
return (
<Select.Item className={classnames('SelectItem', className)} {...props} ref={forwardedRef}>
<Select.ItemText>{children}</Select.ItemText>
<Select.ItemIndicator className="SelectItemIndicator">
<CheckIcon />
</Select.ItemIndicator>
</Select.Item>
);
});
export default SelectDemo;

特性

    可以是受控或非受控的。

    提供 2 种定位模式。

    支持项目、标签和项目组。

    完全管理焦点。

    完整的键盘导航。

    支持自定义占位符。

    支持自动完成。

    支持从右到左方向。

安装

从命令行安装组件。

npm install @radix-ui/react-select

结构

导入所有部分并将其组合在一起。

import * as Select from '@radix-ui/react-select';
export default () => (
<Select.Root>
<Select.Trigger>
<Select.Value />
<Select.Icon />
</Select.Trigger>
<Select.Portal>
<Select.Content>
<Select.ScrollUpButton />
<Select.Viewport>
<Select.Item>
<Select.ItemText />
<Select.ItemIndicator />
</Select.Item>
<Select.Group>
<Select.Label />
<Select.Item>
<Select.ItemText />
<Select.ItemIndicator />
</Select.Item>
</Select.Group>
<Select.Separator />
</Select.Viewport>
<Select.ScrollDownButton />
<Select.Arrow />
</Select.Content>
</Select.Portal>
</Select.Root>
);

API 参考

包含选择的所有部分。

属性类型默认值
defaultValue
字符串
无默认值
value
字符串
无默认值
onValueChange
函数
无默认值
defaultOpen
布尔值
无默认值
open
布尔值
无默认值
onOpenChange
函数
无默认值
dir
枚举
无默认值
name
字符串
无默认值
disabled
布尔值
无默认值
required
布尔值
无默认值

触发器

切换选择的按钮。 Select.Content 将通过与触发器对齐来定位自身。

属性类型默认值
asChild
布尔值
false
数据属性
[data-state]"open" |"closed"
[data-disabled]

禁用时出现

[data-placeholder]

存在占位符时出现

反映所选值的部件。默认情况下,将渲染所选项目的文本。如果您需要更多控制,则可以改为控制选择并传递您自己的 children。不应对其进行样式设置以确保正确的定位。当选择没有值时,还可以使用可选的 placeholder 属性。

属性类型默认值
asChild
布尔值
false
placeholder
ReactNode
无默认值

图标

一个小图标,通常显示在值的旁边,作为其可以打开的视觉提示。默认情况下渲染 ▼,但您可以通过 asChild 使用您自己的图标,或使用 children

属性类型默认值
asChild
布尔值
false

传送门

使用时,将内容部分传送至 body

属性类型默认值
container
HTMLElement
document.body

内容

选择打开时弹出的组件。

属性类型默认值
asChild
布尔值
false
onCloseAutoFocus
函数
无默认值
onEscapeKeyDown
函数
无默认值
onPointerDownOutside
函数
无默认值
position
枚举
"item-aligned"
side
枚举
"bottom"
sideOffset
数字
0
align
枚举
"start"
alignOffset
数字
0
avoidCollisions
布尔值
true
collisionBoundary
边界
[]
collisionPadding
数字 | 填充

10
箭头填充
数字
0
粘性
枚举
“部分”
分离时隐藏
布尔值
false
数据属性
[data-state]"open" |"closed"
[data-side]“左” |“右” |“底部” |“顶部”
[data-align]“开始” |“结束” |“中心”
CSS 变量描述
--radix-select-content-transform-origin根据内容和箭头位置/偏移计算出的transform-origin。仅在position="popper"时存在。
--radix-select-content-available-width触发器和边界边缘之间的剩余宽度。仅在position="popper"时存在。
--radix-select-content-available-height触发器和边界边缘之间的剩余高度。仅在position="popper"时存在。
--radix-select-trigger-width触发器的宽度。仅在 position="popper".
--radix-select-trigger-height触发器的高度。仅在 position="popper".

视口

包含所有项目的滚动视口。

属性类型默认值
asChild
布尔值
false

项目

包含选择项目的组件。

属性类型默认值
asChild
布尔值
false
value*
字符串
无默认值
disabled
布尔值
无默认值
textValue
字符串
无默认值
数据属性
[data-state]“选中” |“未选中”
[data-highlighted]

突出显示时出现

[data-disabled]

禁用时出现

项目文本

项目的文本部分。它应该只包含您希望在选择该项目时在触发器中看到的文本。不应对其进行样式设置以确保正确的位置。

属性类型默认值
asChild
布尔值
false

项目指示器

项目被选中时呈现。您可以直接设置此元素的样式,也可以将其用作包装器以放入图标,或者两者兼而有之。

属性类型默认值
asChild
布尔值
false

向上滚动按钮

一个可选按钮,用作显示视口溢出以及功能性启用向上滚动的辅助手段。

属性类型默认值
asChild
布尔值
false

向下滚动按钮

一个可选按钮,用作显示视口溢出以及功能性启用向下滚动的辅助手段。

属性类型默认值
asChild
布尔值
false

用于对多个项目进行分组。与Select.Label结合使用,以确保通过自动标签实现良好的可访问性。

属性类型默认值
asChild
布尔值
false

标签

用于渲染组的标签。它不能使用箭头键聚焦。

属性类型默认值
asChild
布尔值
false

分隔符

用于在选择中视觉上分隔项目。

属性类型默认值
asChild
布尔值
false

箭头

一个可选的箭头元素,用于与内容一起渲染。这可以用于帮助视觉上将触发器与Select.Content关联。必须渲染在Select.Content内部。仅当position设置为popper时可用。

属性类型默认值
asChild
布尔值
false
宽度
数字
10
高度
数字
5

示例

更改定位模式

默认情况下,Select的行为类似于本机 MacOS 菜单,通过将Select.Content相对于活动项目定位。如果您更喜欢类似于PopoverDropdownMenu的替代定位方法,则可以将position设置为popper,并使用其他对齐选项,如sidesideOffset等。

// index.jsx
import * as Select from '@radix-ui/react-select';
export default () => (
<Select.Root>
<Select.Trigger></Select.Trigger>
<Select.Portal>
<Select.Content position="popper" sideOffset={5}>
</Select.Content>
</Select.Portal>
</Select.Root>
);

约束内容大小

Select.Content上使用position="popper"时,您可能希望约束内容的宽度以使其与触发器宽度匹配。您可能还希望约束其高度,使其不超过视口。

我们公开了一些 CSS 自定义属性,例如--radix-select-trigger-width--radix-select-content-available-height来支持此功能。使用它们来约束内容尺寸。

// index.jsx
import * as Select from '@radix-ui/react-select';
import './styles.css';
export default () => (
<Select.Root>
<Select.Trigger></Select.Trigger>
<Select.Portal>
<Select.Content className="SelectContent" position="popper" sideOffset={5} >
</Select.Content>
</Select.Portal>
</Select.Root>
);
/* styles.css */
.SelectContent {
width: var(--radix-select-trigger-width);
max-height: var(--radix-select-content-available-height);
}

带有禁用项目

您可以通过data-disabled属性为禁用的项目添加特殊样式。

// index.jsx
import * as Select from '@radix-ui/react-select';
import './styles.css';
export default () => (
<Select.Root>
<Select.Trigger></Select.Trigger>
<Select.Portal>
<Select.Content>
<Select.Viewport>
<Select.Item className="SelectItem" disabled>
</Select.Item>
<Select.Item></Select.Item>
<Select.Item></Select.Item>
</Select.Viewport>
</Select.Content>
</Select.Portal>
</Select.Root>
);
/* styles.css */
.SelectItem[data-disabled] {
color: 'gainsboro';
}

带有占位符

您可以使用placeholder道具在Value上,用于选择没有值时。在Trigger上还有一个data-placeholder属性,以帮助设置样式。

// index.jsx
import * as Select from '@radix-ui/react-select';
import './styles.css';
export default () => (
<Select.Root>
<Select.Trigger className="SelectTrigger">
<Select.Value placeholder="Pick an option" />
<Select.Icon />
</Select.Trigger>
<Select.Portal>
<Select.Content></Select.Content>
</Select.Portal>
</Select.Root>
);
/* styles.css */
.SelectTrigger[data-placeholder] {
color: 'gainsboro';
}

带有分隔符

使用Separator部分在项目之间添加分隔符。

<Select.Root>
<Select.Trigger></Select.Trigger>
<Select.Portal>
<Select.Content>
<Select.Viewport>
<Select.Item></Select.Item>
<Select.Item></Select.Item>
<Select.Item></Select.Item>
<Select.Separator />
<Select.Item></Select.Item>
<Select.Item></Select.Item>
</Select.Viewport>
</Select.Content>
</Select.Portal>
</Select.Root>

带有分组项目

使用GroupLabel部分将项目分组到一个部分中。

<Select.Root>
<Select.Trigger></Select.Trigger>
<Select.Portal>
<Select.Content>
<Select.Viewport>
<Select.Group>
<Select.Label>Label</Select.Label>
<Select.Item></Select.Item>
<Select.Item></Select.Item>
<Select.Item></Select.Item>
</Select.Group>
</Select.Viewport>
</Select.Content>
</Select.Portal>
</Select.Root>

带有复杂项目

您可以在项目中使用自定义内容。

import * as Select from '@radix-ui/react-select';
export default () => (
<Select.Root>
<Select.Trigger></Select.Trigger>
<Select.Portal>
<Select.Content>
<Select.Viewport>
<Select.Item>
<Select.ItemText>
<img src="" />
Adolfo Hess
</Select.ItemText>
<Select.ItemIndicator></Select.ItemIndicator>
</Select.Item>
<Select.Item></Select.Item>
<Select.Item></Select.Item>
</Select.Viewport>
</Select.Content>
</Select.Portal>
</Select.Root>
);

控制触发器中显示的值

默认情况下,触发器会自动显示所选项目ItemText的内容。您可以通过选择将内容放入ItemText部分的内部/外部来控制显示的内容。

如果您需要更多灵活性,您可以使用value/onValueChange道具控制组件,并将children传递给SelectValue。请务必确保您放入其中的内容是可访问的。

const countries = { france: '🇫🇷', 'united-kingdom': '🇬🇧', spain: '🇪🇸' };
export default () => {
const [value, setValue] = React.useState('france');
return (
<Select.Root value={value} onValueChange={setValue}>
<Select.Trigger>
<Select.Value aria-label={value}>
{countries[value]}
</Select.Value>
<Select.Icon />
</Select.Trigger>
<Select.Portal>
<Select.Content>
<Select.Viewport>
<Select.Item value="france">
<Select.ItemText>France</Select.ItemText>
<Select.ItemIndicator></Select.ItemIndicator>
</Select.Item>
<Select.Item value="united-kingdom">
<Select.ItemText>United Kingdom</Select.ItemText>
<Select.ItemIndicator></Select.ItemIndicator>
</Select.Item>
<Select.Item value="spain">
<Select.ItemText>Spain</Select.ItemText>
<Select.ItemIndicator></Select.ItemIndicator>
</Select.Item>
</Select.Viewport>
</Select.Content>
</Select.Portal>
</Select.Root>
);
};

带有自定义滚动条

默认情况下,本机滚动条是隐藏的,因为我们建议使用ScrollUpButtonScrollDownButton部分以获得最佳用户体验。如果您不想使用这些部分,请使用我们的滚动区域基本组件组合您的选择。

// index.jsx
import * as Select from '@radix-ui/react-select';
import * as ScrollArea from '@radix-ui/react-scroll-area';
import './styles.css';
export default () => (
<Select.Root>
<Select.Trigger></Select.Trigger>
<Select.Portal>
<Select.Content>
<ScrollArea.Root className="ScrollAreaRoot" type="auto">
<Select.Viewport asChild>
<ScrollArea.Viewport className="ScrollAreaViewport">
<StyledItem></StyledItem>
<StyledItem></StyledItem>
<StyledItem></StyledItem>
</ScrollArea.Viewport>
</Select.Viewport>
<ScrollArea.Scrollbar className="ScrollAreaScrollbar" orientation="vertical" >
<ScrollArea.Thumb className="ScrollAreaThumb" />
</ScrollArea.Scrollbar>
</ScrollArea.Root>
</Select.Content>
</Select.Portal>
</Select.Root>
);
/* styles.css */
.ScrollAreaRoot {
width: 100%;
height: 100%;
}
.ScrollAreaViewport {
width: 100%;
height: 100%;
}
.ScrollAreaScrollbar {
width: 4px;
padding: 5px 2px;
}
.ScrollAreaThumb {
background: rgba(0, 0, 0, 0.3);
border-radius: 3px;
}

可访问性

遵循ListBox WAI-ARIA 设计模式

请参阅 W3C 仅选择组合框示例以了解更多信息。

键盘交互

描述
空格
当焦点位于Select.Trigger上时,打开选择并聚焦所选项目。
当焦点位于项目上时,选择焦点所在的项目。
回车
当焦点位于Select.Trigger上时,打开选择并聚焦第一个项目。
当焦点位于项目上时,选择焦点所在的项目。
向下箭头
当焦点位于Select.Trigger上时,打开选择。
当焦点位于项目上时,将焦点移动到下一个项目。
向上箭头
当焦点位于Select.Trigger上时,打开选择。
当焦点位于项目上时,将焦点移动到上一个项目。
Esc
关闭选择并将焦点移动到Select.Trigger

标签

使用我们的标签组件为选择提供视觉和可访问的标签。

import * as Select from '@radix-ui/react-select';
import { Label } from '@radix-ui/react-label';
export default () => (
<>
<Label>
Country
<Select.Root></Select.Root>
</Label>
{/* or */}
<Label htmlFor="country">Country</Label>
<Select.Root>
<Select.Trigger id="country"></Select.Trigger>
<Select.Portal>
<Select.Content></Select.Content>
</Select.Portal>
</Select.Root>
</>
);

自定义 API

通过将基本组件抽象到您自己的组件中来创建您自己的 API。

抽象到SelectSelectItem

此示例抽象了大部分组件。

用法

import { Select, SelectItem } from './your-select';
export default () => (
<Select defaultValue="2">
<SelectItem value="1">Item 1</SelectItem>
<SelectItem value="2">Item 2</SelectItem>
<SelectItem value="3">Item 3</SelectItem>
</Select>
);

实现

// your-select.jsx
import React from 'react';
import * as SelectPrimitive from '@radix-ui/react-select';
import { CheckIcon, ChevronDownIcon, ChevronUpIcon, } from '@radix-ui/react-icons';
export const Select = React.forwardRef(
({ children, ...props }, forwardedRef) => {
return (
<SelectPrimitive.Root {...props}>
<SelectPrimitive.Trigger ref={forwardedRef}>
<SelectPrimitive.Value />
<SelectPrimitive.Icon>
<ChevronDownIcon />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
<SelectPrimitive.Portal>
<SelectPrimitive.Content>
<SelectPrimitive.ScrollUpButton>
<ChevronUpIcon />
</SelectPrimitive.ScrollUpButton>
<SelectPrimitive.Viewport>{children}</SelectPrimitive.Viewport>
<SelectPrimitive.ScrollDownButton>
<ChevronDownIcon />
</SelectPrimitive.ScrollDownButton>
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
</SelectPrimitive.Root>
);
}
);
export const SelectItem = React.forwardRef(
({ children, ...props }, forwardedRef) => {
return (
<SelectPrimitive.Item {...props} ref={forwardedRef}>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
<SelectPrimitive.ItemIndicator>
<CheckIcon />
</SelectPrimitive.ItemIndicator>
</SelectPrimitive.Item>
);
}
);
上一页滚动区域
下一页分隔符