样式
Reka UI 是无样式的,并且与任何样式解决方案兼容,让您完全控制样式。
样式概述
功能样式
您可以控制样式的所有方面,包括功能样式。例如,默认情况下,Dialog Overlay 不会覆盖整个视口。您需要负责添加这些样式以及任何呈现样式。
类
所有组件都接受 class 属性,就像普通组件一样。此 class 将传递到 DOM 元素。您可以像预期一样在 CSS 中使用它。
传送元素
某些元素(例如模态框或弹出框)会传送到 body。当使用作用域样式应用 CSS 时,您需要使用 深层选择器 来定位它们。
数据属性
当组件是有状态时,它们的状态将通过 data-state 属性暴露。例如,当 Accordion Item 打开时,它会包含 data-state="open" 属性。
使用 CSS 样式
样式化部件
您可以通过定位提供的 class 来样式化组件部件。
<script setup lang="ts">
import { AccordionRoot, AccordionItem, ... } from "reka-ui";
</script>
<template>
<AccordionRoot>
<AccordionItem class="AccordionItem" value="item-1" />
<!-- ... -->
</AccordionRoot>
</template>
<style>
.AccordionItem {
/* ... */
}
</style>
样式化状态
您可以通过定位组件的 data-state 属性来样式化组件状态。
.AccordionItem {
border-bottom: 1px solid gainsboro;
}
.AccordionItem[data-state="open"] {
border-bottom-width: 2px;
}
作用域样式
您可以使用作用域样式来样式化组件。请注意传送的元素,因为它们需要使用 深层选择器 才能被定位。
<script setup lang="ts">
import { DropdownMenuRoot, DropdownMenuItem, ... } from "reka-ui";
</script>
<template>
<DropdownMenuRoot>
<!-- ... -->
<DropdownMenuPortal>
<DropdownMenuContent class="DropdownMenuContent">
<DropdownMenuItem class="DropdownMenuItem">An item</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenuPortal>
</DropdownMenuRoot>
</template>
<style scoped>
:deep(.DropdownMenuContent) {
/* ... */
}
.DropdownMenuItem {
/* ... */
}
</style>
DropdownMenuContent 需要 :deep() 是因为它很可能通过 Portal 机制渲染到了当前 Vue 组件 DOM 树之外的位置,导致它无法获得当前组件 允许你的样式选择器穿透这种组件作用域的隔离,从而能够正确地应用样式。DropdownMenuItem 则通常在被 Portal 的 DropdownMenuContent 的内部正常渲染,所以可能不需要 deep。使用 Tailwind CSS 样式
以下示例使用 Tailwind CSS,但您可以使用任何您选择的库。
样式化部件
您可以通过定位 class 来样式化组件部件。
<script setup lang="ts">
import { AccordionRoot, AccordionItem, ... } from "reka-ui";
</script>
<template>
<AccordionRoot>
<AccordionItem class="border border-gray-400 rounded-2xl" value="item-1" />
<!-- ... -->
</AccordionRoot>
</template>
样式化状态
借助 Tailwind CSS 强大的变体选择器,您可以通过定位组件的 data-state 属性来样式化组件状态。
<script setup lang="ts">
import { AccordionRoot, AccordionItem, ... } from "reka-ui";
</script>
<template>
<AccordionRoot>
<AccordionItem
class="
border border-gray-400 rounded-2xl
data-[state=open]:border-b-2 data-[state=open]:border-gray-800
"
value="item-1"
/>
<!-- ... -->
</AccordionRoot>
</template>
Tailwind CSS 是一个原子化 CSS 框架(Utility-First CSS framework)。它的核心思想是:
- 直接在 HTML 中应用原子类: 你不是写 CSS 规则来定义一个组件的样式,而是直接在你的 HTML 元素上添加一系列预定义的、单一用途的工具类(如 flex, pt-4, text-center, bg-blue-500)。
- 按需生成 CSS: Tailwind JIT (Just-In-Time) 编译器或 PostCSS 插件会在构建时扫描你的代码,只生成你实际用到的那些工具类的 CSS。
- 全局作用域: Tailwind 生成的 CSS 类(例如 .pt-4)是全局的,它们没有被限定在特定的组件或文件中。当你应用 pt-4 类时,它就是 padding-top: 1rem;,这个规则在你的整个应用中都是一样的。
<style scoped> 来编写那些 Tailwind 无法覆盖或你希望更具组件特定性的自定义 CSS 规则。扩展原始元素
扩展原始元素与扩展任何 Vue 组件的方式相同。
<script setup lang="ts">
import { AccordionItem, type AccordionItemProps } from "reka-ui";
interface Props extends AccordionItemProps {
foo: string;
}
defineProps<Props>();
</script>
<template>
<AccordionItem v-bind="$props"><slot /></AccordionItem>
</template>
v-bind="$props": 这是 Vue 的一个特殊用法。$props 是一个内置的变量,它包含了当前组件接收到的所有 props。- 当
v-bind="$props"被应用到一个子组件时,它会将当前组件接收到的所有props,原封不动地传递给子组件。 - 这意味着,
AccordionItem将接收到所有AccordionItemProps中定义的props,以及你自定义的fooprop(尽管 AccordionItem 可能不认识 foo,但它会忽略)。这种模式称为 "透传 Attributes" (Attribute Inheritance),在封装组件时非常有用,因为它减少了手动绑定每个prop的繁琐。
总结
Reka UI 旨在封装可访问性问题和其他复杂功能,同时确保您完全控制样式。
为方便起见,有状态组件包含 data-state 属性。